diff options
Diffstat (limited to 'src/core')
63 files changed, 9054 insertions, 7946 deletions
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index c8d8cb56..d39be754 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -12,6 +12,7 @@ #include "General.h" #include "Camera.h" #include "Vehicle.h" +#include "Bike.h" #include "PlayerSkin.h" #include "PlayerInfo.h" #include "World.h" @@ -48,11 +49,9 @@ CAnimViewer::Render(void) { // pTarget->GetPosition() = CVector(0.0f, 0.0f, 0.0f); if (pTarget) { #ifdef FIX_BUGS -#ifdef PED_SKIN if(pTarget->IsPed()) ((CPed*)pTarget)->UpdateRpHAnim(); #endif -#endif pTarget->Render(); CRenderer::RenderOneNonRoad(pTarget); } @@ -91,19 +90,20 @@ 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(); CAnimManager::LoadAnimFiles(); CWorld::PlayerInFocus = 0; CWeapon::InitialiseWeapons(); - CShadows::Init(); CPed::Initialise(); CTimer::Initialise(); CClock::Initialise(60000); @@ -136,11 +136,7 @@ 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 } } @@ -269,6 +265,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()) { @@ -342,13 +340,7 @@ 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); } diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index fcffce9b..3b11e16f 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,12 +27,19 @@ #include "Debug.h" #include "Camera.h" #include "DMAudio.h" +#include "Bike.h" +#include "Pickups.h" + +//--MIAMI: file done bool PrintDebugCode = false; int16 DebugCamMode; +extern float fRangePlayerRadius; +extern float fCloseNearClipLimit; + #ifdef FREE_CAM -bool CCamera::bFreeCam; +bool CCamera::bFreeCam = false; int nPreviousMode = -1; #endif @@ -56,6 +65,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 +90,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 +102,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 +141,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 +174,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); @@ -159,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: @@ -167,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: @@ -197,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) @@ -217,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; @@ -244,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: @@ -253,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: @@ -288,13 +312,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) @@ -323,7 +353,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(); } @@ -367,22 +397,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; @@ -394,65 +421,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 @@ -461,6 +484,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; @@ -510,96 +535,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; } @@ -620,18 +558,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(); @@ -646,12 +596,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(); } @@ -662,55 +608,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) @@ -720,8 +687,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(); @@ -729,10 +709,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; } } @@ -742,24 +720,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) @@ -769,8 +759,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(); @@ -778,10 +781,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; } } @@ -857,11 +858,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 @@ -873,16 +870,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 @@ -906,10 +909,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); @@ -970,41 +973,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) @@ -1012,85 +990,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); @@ -1112,24 +1077,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) @@ -1140,166 +1111,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; @@ -1309,13 +1166,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(); @@ -1330,8 +1197,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; @@ -1355,7 +1221,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); @@ -1374,59 +1247,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{ @@ -1445,24 +1301,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; @@ -1470,7 +1326,6 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl GetVectorsReadyForRW(); TheCamera.m_bCamDirectlyBehind = false; TheCamera.m_bCamDirectlyInFront = false; - PreviouslyObscured = BuildingCheckObscured; ResetStatics = false; } @@ -1479,10 +1334,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) @@ -1506,30 +1362,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) @@ -1549,10 +1420,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)) @@ -1564,17 +1431,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; @@ -1604,7 +1471,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); @@ -1625,8 +1492,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 @@ -1638,18 +1505,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_WEAPON_PUMP) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROW) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROWU) || - RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_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; @@ -1658,7 +1524,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; @@ -1688,7 +1555,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; @@ -1706,303 +1573,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; + 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; - 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); - - // 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); @@ -2019,7 +1754,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; @@ -2043,78 +1778,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) @@ -2122,38 +1790,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; } @@ -2161,8 +1908,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; @@ -2445,13 +2201,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; @@ -2470,11 +2226,16 @@ CCam::Process_Rocket(const CVector &CameraTarget, float, float, float) ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + 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; @@ -2501,7 +2262,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; @@ -2545,22 +2306,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; @@ -2570,14 +2339,6 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) ResetStatics = false; } -#ifndef GTA3_1_1_PATCH - ((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(); @@ -2594,6 +2355,11 @@ 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; @@ -2605,62 +2371,134 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float) if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f); else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f); -#ifdef GTA3_1_1_PATCH - 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 += 2*PI; + while(Beta >= PI) Beta -= 2*PI; + } - 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 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; @@ -2678,6 +2516,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; } @@ -2698,11 +2537,22 @@ CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, fl ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + 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(); @@ -2758,16 +2608,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) @@ -2785,9 +2667,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(); @@ -2818,16 +2700,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((RwV3d*)&HeadPos, (RwV3d*)&HeadPos, 1, &mats[idx]); + RwV3d scl = { 0.0f, 0.0f, 0.0f }; + RwMatrixScale(&mats[idx], &scl, rwCOMBINEPRECONCAT); if(ResetStatics){ Beta = TargetOrientation; @@ -2896,6 +2774,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; @@ -2935,12 +2839,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; @@ -2961,11 +2868,23 @@ CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float ResetStatics = false; } - ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD); + 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; @@ -3035,8 +2954,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(); @@ -3069,6 +2993,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(); @@ -3077,6 +3003,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) { @@ -3087,82 +3019,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(); } @@ -3179,8 +3152,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; @@ -3211,22 +3182,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) { @@ -3237,118 +3210,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) { @@ -3356,26 +3346,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; @@ -3399,32 +3388,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 @@ -3432,6 +3404,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(); @@ -3550,6 +3524,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) @@ -3628,37 +3607,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(); @@ -3672,7 +3719,22 @@ CCam::Process_Fixed(const CVector &CameraTarget, float, float, float) if(TheCamera.m_bUseSpecialFovTrain) FOV = TheCamera.m_fFovForTrain; - if(CMenuManager::m_ControlMethod == CONTROL_STANDARD && Using3rdPersonMouseCam()){ + 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); + } + } + + if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD && Using3rdPersonMouseCam()){ CPed *player = FindPlayerPed(); if(player && player->CanStrafeOrMouseControl()){ float Heading = Front.Heading(); @@ -3685,16 +3747,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; @@ -3706,20 +3833,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) { @@ -3727,6 +3840,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(); @@ -3824,11 +3939,11 @@ CCam::Process_Debug(const CVector&, float, float, float) } // stay inside sectors - while(CWorld::GetSectorX(Source.x) > 95.0f) + while(CWorld::GetSectorX(Source.x) > 75.0f) Source.x -= 1.0f; while(CWorld::GetSectorX(Source.x) < 5.0f) Source.x += 1.0f; - while(CWorld::GetSectorY(Source.y) > 95.0f) + while(CWorld::GetSectorY(Source.y) > 75.0f) Source.y -= 1.0f; while(CWorld::GetSectorY(Source.y) < 5.0f) Source.y += 1.0f; @@ -3895,11 +4010,11 @@ CCam::Process_Debug(const CVector&, float, float, float) } // stay inside sectors - while(CWorld::GetSectorX(Source.x) > 95.0f) + while(CWorld::GetSectorX(Source.x) > 75.0f) Source.x -= 1.0f; while(CWorld::GetSectorX(Source.x) < 5.0f) Source.x += 1.0f; - while(CWorld::GetSectorY(Source.y) > 95.0f) + while(CWorld::GetSectorY(Source.y) > 75.0f) Source.y -= 1.0f; while(CWorld::GetSectorY(Source.y) < 5.0f) Source.y += 1.0f; @@ -3975,11 +4090,11 @@ CCam::Process_Editor(const CVector&, float, float, float) } // stay inside sectors - while(CWorld::GetSectorX(Source.x) > 95.0f) + while(CWorld::GetSectorX(Source.x) > 75.0f) Source.x -= 1.0f; while(CWorld::GetSectorX(Source.x) < 5.0f) Source.x += 1.0f; - while(CWorld::GetSectorY(Source.y) > 95.0f) + while(CWorld::GetSectorY(Source.y) > 75.0f) Source.y -= 1.0f; while(CWorld::GetSectorY(Source.y) < 5.0f) Source.y += 1.0f; @@ -4021,109 +4136,372 @@ 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]->IsStatic() && 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, 0.1f) > 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, 0.1f) > 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; + } + + 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); + if(CamSource.z > Source.z + ARRESTCAM_S_ROTATION_UP*CTimer::GetTimeStep()) + CamSource.z = Source.z + ARRESTCAM_S_ROTATION_UP*CTimer::GetTimeStep(); + }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; } @@ -4173,376 +4551,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) @@ -4670,6 +4678,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)); @@ -4717,7 +4727,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); @@ -4773,9 +4783,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); @@ -4786,8 +4796,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) { @@ -4844,6 +4856,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) { @@ -4858,6 +4878,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)) { @@ -4872,6 +4895,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (ResetStatics) { FOV = DefaultFOV; + // TODO(Miami): Remove that when cam is done! // GTA 3 has this in veh. camera if (TheCamera.m_bIdleOn) TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds(); @@ -4908,10 +4932,12 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, ResetStatics = false; Rotating = false; m_bCollisionChecksOn = true; - // TheCamera.m_bResetOldMatrix = 1; + + + // TODO(Miami): Uncomment that when cam is done! // Garage exit cam is not working well in III... - // if (!TheCamera.m_bJustCameOutOfGarage) // && !sthForScript) + // if (!TheCamera.m_bJustCameOutOfGarage) // { Alpha = 0.0f; Beta = car->GetForward().Heading() - HALFPI; @@ -4933,7 +4959,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; } @@ -4985,9 +5011,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,7 +5067,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, 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 { @@ -5145,8 +5171,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; } @@ -5296,19 +5322,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; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index abe0833e..2f977a20 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 }; @@ -62,6 +71,11 @@ enum CCamera TheCamera; bool CCamera::m_bUseMouse3rdPerson = true; 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) @@ -72,48 +86,27 @@ bool bDidWeProcessAnyCinemaCam; #define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) #endif -CCamera::CCamera(void) -{ -#ifdef GTA3_1_1_PATCH - 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) { -#ifdef GTA3_1_1_PATCH - 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 - - #ifdef GTA3_1_1_PATCH - m_fMouseAccelHorzntl = fMouseAccelHorzntl; - m_fMouseAccelVertical = fMouseAccelVertical; - #endif - m_pRwCamera = nil; - -#ifdef PS2_MENU - } -#endif - + 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; @@ -122,8 +115,21 @@ CCamera::Init(void) Cams[2].Init(); Cams[0].Mode = CCam::MODE_FOLLOWPED; Cams[1].Mode = CCam::MODE_FOLLOWPED; - unknown = 0; - m_bJustJumpedOutOf1stPersonBecauseOfTarget = 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; @@ -180,26 +186,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; @@ -218,6 +216,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; @@ -237,21 +237,18 @@ CCamera::Init(void) m_uiTransitionState = 0; m_uiTimeTransitionStart = 0; m_bLookingAtPlayer = true; -#ifndef GTA3_1_1_PATCH - 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; @@ -279,6 +276,7 @@ CCamera::Process(void) if(m_WideScreenOn) ProcessWideScreenOn(); +#ifndef MASTER #ifdef IMPROVED_CAMERA if(CPad::GetPad(1)->GetCircleJustDown() || CTRLJUSTDOWN('B')){ #else @@ -290,6 +288,7 @@ CCamera::Process(void) else CPad::m_bMapPadOneToPadTwo = false; } +#endif RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); @@ -309,19 +308,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) @@ -333,169 +324,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; @@ -506,37 +378,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); @@ -567,33 +424,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); @@ -625,21 +469,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) @@ -652,6 +509,32 @@ 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; + Cams[ActiveCam].FOV *= (1.0f + CMBlur::Drunkness); + + 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; @@ -668,13 +551,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; @@ -695,7 +586,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(); @@ -704,25 +597,33 @@ 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) DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y); // LOD dist - if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()) + if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){ LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f); - else + + 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; - // missing on PS2 GenerationDistMultiplier = LODDistMultiplier; LODDistMultiplier *= CRenderer::ms_lodDistScale; - // + + CDraw::SetNearClipZ(RwCameraGetNearClipPlane(m_pRwCamera)); + CDraw::SetFarClipZ(RwCameraGetFarClipPlane(m_pRwCamera)); // Keep track of speed if(m_bJustInitalised || m_bJust_Switched){ @@ -738,8 +639,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; @@ -757,6 +656,7 @@ CCamera::Process(void) } m_bCameraJustRestored = false; + m_bMoveCamToAvoidGeom = false; } void @@ -764,10 +664,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; @@ -780,20 +680,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; @@ -802,11 +694,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; @@ -822,25 +714,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; @@ -850,45 +752,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 @@ -899,9 +844,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)); @@ -931,33 +882,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; @@ -965,7 +921,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){ @@ -1009,7 +965,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; } } @@ -1019,29 +976,29 @@ 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; @@ -1060,8 +1017,10 @@ CCamera::CamControl(void) 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; + m_bJustJumpedOutOf1stPersonBecauseOfTarget = true; + } } }else m_bFirstPersonBeingUsed = false; @@ -1070,7 +1029,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 @@ -1108,6 +1067,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); @@ -1122,15 +1083,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; @@ -1165,20 +1124,37 @@ CCamera::CamControl(void) }else{ whichDoor = 1; garageDoorPos1 = Cams[ActiveCam].Source; + garageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2.0f, (stairsZone->miny+stairsZone->maxy)/2.0f, 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){ +// 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; + } } 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 == nil) // how can this be true? garageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f); } if(whichDoor == 1) @@ -1192,9 +1168,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; @@ -1202,8 +1184,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)); @@ -1231,6 +1213,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()) @@ -1253,8 +1242,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){ @@ -1264,7 +1255,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; @@ -1306,7 +1297,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){ @@ -1332,8 +1323,6 @@ CCamera::CamControl(void) } } - m_bIdleOn = false; - if(DebugCamMode) ReqMode = DebugCamMode; @@ -1342,56 +1331,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(); @@ -1403,7 +1402,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; @@ -1437,16 +1435,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; @@ -1470,6 +1472,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) @@ -1484,7 +1490,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()) @@ -1502,11 +1508,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 || @@ -1521,8 +1532,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 || @@ -1533,7 +1546,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; @@ -1542,7 +1556,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 @@ -1561,7 +1575,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; @@ -1579,12 +1598,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(); } @@ -1618,8 +1636,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; @@ -1632,7 +1648,6 @@ CCamera::CamControl(void) m_bWaitForInterpolToFinish = true; } } -#endif if(m_bWaitForInterpolToFinish) startTransition = false; @@ -1642,19 +1657,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); @@ -1668,7 +1696,12 @@ CCamera::CamControl(void) }else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT){ 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; @@ -1694,23 +1727,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)->CycleCameraModeUpJustDown() && + !CReplay::IsPlayingBack() && + (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && + !m_WideScreenOn && + (WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam)) + DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 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){ @@ -1728,7 +1780,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 || @@ -1738,14 +1789,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){ @@ -1757,16 +1815,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) @@ -1797,6 +1848,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()) @@ -1815,33 +1867,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 @@ -1886,6 +1911,143 @@ 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){ + 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 @@ -1915,7 +2077,6 @@ CCamera::TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 cont m_iTypeOfSwitch = typeOfSwitch; m_bLookingAtPlayer = false; m_bStartInterScript = true; - // FindPlayerPed(); // unused } } @@ -1945,8 +2106,6 @@ CCamera::TakeControlWithSpline(int16 typeOfSwitch) m_bcutsceneFinished = false; m_iTypeOfSwitch = typeOfSwitch; m_bStartInterScript = true; - - //FindPlayerPed(); // unused }; void @@ -1981,10 +2140,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 @@ -2001,6 +2163,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; @@ -2030,27 +2194,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; @@ -2063,20 +2225,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; @@ -2088,6 +2251,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; @@ -2095,12 +2259,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; @@ -2115,70 +2273,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; @@ -2190,11 +2320,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 @@ -2243,6 +2369,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 @@ -2250,10 +2377,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; @@ -2261,73 +2384,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_vehEnterType; - 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; @@ -2335,7 +2402,6 @@ CCamera::StartTransition(int16 newMode) break; } -#ifndef PS2_CAM_TRANSITION Cams[ActiveCam].Init(); Cams[ActiveCam].Mode = newMode; @@ -2345,30 +2411,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; @@ -2399,28 +2466,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) { @@ -2433,7 +2504,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 @@ -2467,26 +2538,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)); } @@ -2504,7 +2573,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; @@ -2514,7 +2585,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; @@ -2523,14 +2594,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; @@ -2542,10 +2613,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: @@ -2556,13 +2627,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; @@ -2571,7 +2642,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: @@ -2635,6 +2706,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; } @@ -2644,7 +2799,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; @@ -2654,7 +2810,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(); @@ -2669,7 +2825,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); @@ -2686,17 +2842,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(); @@ -2719,10 +2875,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)); @@ -2779,7 +2935,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){ @@ -2807,7 +2963,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){ @@ -2902,12 +3058,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, @@ -2923,19 +3286,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]); } } @@ -2943,6 +3306,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 @@ -2970,6 +3367,7 @@ CCamera::DontProcessObbeCinemaCamera(void) bDidWeProcessAnyCinemaCam = false; } +#ifdef GTA_TRAIN void CCamera::LoadTrainCamNodes(char const *name) { @@ -3154,6 +3552,7 @@ CCamera::Process_Train_Camera_Control(void) } } } +#endif void @@ -3165,9 +3564,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; @@ -3211,6 +3615,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); @@ -3271,26 +3686,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 @@ -3305,33 +3736,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; } } @@ -3342,46 +3763,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); } } @@ -3397,22 +3800,13 @@ CCamera::Fade(float timeout, int16 direction) m_iMusicFadingDirection = direction; m_fTimeToFadeMusic = timeout; m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds(); -// Not on PS2 - if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){ - unknown++; - if(unknown >= 2){ - m_bJustJumpedOutOf1stPersonBecauseOfTarget = 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; @@ -3519,6 +3913,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; @@ -3528,6 +3923,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; @@ -3571,6 +3967,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 @@ -3595,8 +4003,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 @@ -3681,7 +4090,5 @@ CCamera::IsBoxVisible(RwV3d *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 dd78d952..ff74931c 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); @@ -231,42 +227,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); }; @@ -355,6 +338,7 @@ public: bool m_bInitialNoNodeStaticsSet; bool m_bIgnoreFadingStuffForMusic; bool m_bPlayerIsInGarage; + bool m_bPlayerWasOnBike; bool m_bJustCameOutOfGarage; bool m_bJustInitalised; bool m_bJust_Switched; @@ -379,6 +363,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; @@ -394,15 +381,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; @@ -425,12 +413,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; @@ -441,7 +426,6 @@ public: float m_fFOVSpeedAtStartInter; float m_fStartingBetaForInterPol; float m_fStartingAlphaForInterPol; -#endif float m_PedOrientForBehindOrInFront; float m_CameraAverageSpeed; float m_CameraSpeedSoFar; @@ -466,17 +450,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]; @@ -491,7 +476,7 @@ public: CVector m_vecFixedModeSource; CVector m_vecFixedModeUpOffSet; CVector m_vecCutSceneOffset; -#ifndef PS2_CAM_TRANSITION + CVector m_cvecStartingSourceForInterPol; CVector m_cvecStartingTargetForInterPol; CVector m_cvecStartingUpForInterPol; @@ -501,17 +486,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; @@ -530,6 +515,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; @@ -553,7 +540,6 @@ public: // High level and misc CCamera(void); - CCamera(float); void Init(void); void Process(void); void CamControl(void); @@ -562,6 +548,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); @@ -587,6 +576,7 @@ public: bool TryToStartNewCamMode(int32 obbeMode); void DontProcessObbeCinemaCamera(void); void ProcessObbeCinemaCameraCar(void); + void ProcessObbeCinemaCameraHeli(void); void ProcessObbeCinemaCameraPed(void); // Train @@ -595,6 +585,7 @@ public: // Script void LoadPathSplines(int file); + void DeleteCutSceneCamDataMemory(void); void FinishCutscene(void); float GetPositionAlongSpline(void) { return m_fPositionAlongSpline; } uint32 GetCutSceneFinishTime(void); @@ -630,6 +621,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/ColStore.cpp b/src/core/ColStore.cpp new file mode 100644 index 00000000..070967e5 --- /dev/null +++ b/src/core/ColStore.cpp @@ -0,0 +1,237 @@ +#include "common.h" + +#include "templates.h" +#include "General.h" +#include "ModelInfo.h" +#include "Streaming.h" +#include "FileLoader.h" +#include "Script.h" +#include "Timer.h" +#include "Camera.h" +#include "Frontend.h" +#include "Physical.h" +#include "ColStore.h" + +CPool<ColDef,ColDef> *CColStore::ms_pColPool; + +void +CColStore::Initialise(void) +{ + if(ms_pColPool == nil) + ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles"); + AddColSlot("generic"); // slot 0. not streamed +} + +void +CColStore::Shutdown(void) +{ + int i; + for(i = 0; i < COLSTORESIZE; i++) + RemoveColSlot(i); + if(ms_pColPool) + delete ms_pColPool; + ms_pColPool = nil; +} + +int +CColStore::AddColSlot(const char *name) +{ + ColDef *def = ms_pColPool->New(); + assert(def); + def->isLoaded = false; + def->unused = 0; + def->bounds.left = 1000000.0f; + def->bounds.top = 1000000.0f; + def->bounds.right = -1000000.0f; + def->bounds.bottom = -1000000.0f; + def->minIndex = INT16_MAX; + def->maxIndex = INT16_MIN; + strcpy(def->name, name); + return ms_pColPool->GetJustIndex(def); +} + +void +CColStore::RemoveColSlot(int slot) +{ + if(GetSlot(slot)){ + if(GetSlot(slot)->isLoaded) + RemoveCol(slot); + ms_pColPool->Delete(GetSlot(slot)); + } +} + +int +CColStore::FindColSlot(const char *name) +{ + ColDef *def; + int size = ms_pColPool->GetSize(); + for(int i = 0; i < size; i++){ + def = GetSlot(i); + if(def && !CGeneral::faststricmp(def->name, name)) + return i; + } + return -1; +} + +char* +CColStore::GetColName(int32 slot) +{ + return GetSlot(slot)->name; +} + +CRect& +CColStore::GetBoundingBox(int32 slot) +{ + return GetSlot(slot)->bounds; +} + +void +CColStore::IncludeModelIndex(int32 slot, int32 modelIndex) +{ + ColDef *def = GetSlot(slot); + if(modelIndex < def->minIndex) + def->minIndex = modelIndex; + if(modelIndex > def->maxIndex) + def->maxIndex = modelIndex; +} + +bool +CColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize) +{ + bool success; + ColDef *def = GetSlot(slot); + if(def->minIndex > def->maxIndex) + success = CFileLoader::LoadCollisionFileFirstTime(buffer, bufsize, slot); + else + success = CFileLoader::LoadCollisionFile(buffer, bufsize, slot); + if(success) + def->isLoaded = true; + else + debug("Failed to load Collision\n"); + return success; +} + +void +CColStore::RemoveCol(int32 slot) +{ + int id; + GetSlot(slot)->isLoaded = false; + for(id = 0; id < MODELINFOSIZE; id++){ + CBaseModelInfo *mi = CModelInfo::GetModelInfo(id); + if(mi){ + CColModel *col = mi->GetColModel(); + if(col && col->level == slot) + col->RemoveCollisionVolumes(); + } + } +} + +void +CColStore::LoadAllCollision(void) +{ + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i)) + CStreaming::RequestCol(i, 0); + + CStreaming::LoadAllRequestedModels(false); +} + +void +CColStore::RemoveAllCollision(void) +{ + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i)) + if(CStreaming::CanRemoveCol(i)) + CStreaming::RemoveCol(i); +} + +static bool bLoadAtSecondPosition; +static CVector2D secondPosition; + +void +CColStore::AddCollisionNeededAtPosn(const CVector2D &pos) +{ + bLoadAtSecondPosition = true; + secondPosition = pos; +} + +void +CColStore::LoadCollision(const CVector2D &pos) +{ + int i; + + if(CStreaming::ms_disableStreaming) + return; + + for(i = 1; i < COLSTORESIZE; i++){ + if(GetSlot(i) == nil) + continue; + + bool wantThisOne = false; + + if(GetBoundingBox(i).IsPointInside(pos) || + bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) || + CGeneral::faststrcmp(GetColName(i), "yacht") == 0){ + wantThisOne = true; + }else{ + for (int j = 0; j < MAX_CLEANUP; j++) { + CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j); + if (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) { + if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f)) + wantThisOne = true; + } + } + } + + if(wantThisOne) + CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY); + else + CStreaming::RemoveCol(i); + } + bLoadAtSecondPosition = false; +} + +void +CColStore::RequestCollision(const CVector2D &pos) +{ + int i; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f)) + CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY); +} + +void +CColStore::EnsureCollisionIsInMemory(const CVector2D &pos) +{ + int i; + + if(CStreaming::ms_disableStreaming) + return; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) && + !CStreaming::HasColLoaded(i)){ + CStreaming::RequestCol(i, 0); + if(TheCamera.GetScreenFadeStatus() == FADE_0) + FrontEndMenuManager.MessageScreen("LOADCOL", false); + CTimer::Suspend(); + CStreaming::LoadAllRequestedModels(false); + CTimer::Resume(); + } +} + +//--MIAMI: done +bool +CColStore::HasCollisionLoaded(const CVector2D &pos) +{ + int i; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f) && + !GetSlot(i)->isLoaded) + return false; + return true; +} diff --git a/src/core/ColStore.h b/src/core/ColStore.h new file mode 100644 index 00000000..8e2a3a70 --- /dev/null +++ b/src/core/ColStore.h @@ -0,0 +1,43 @@ +#pragma once + +#include "templates.h" + +struct ColDef { // made up name + int32 unused; + bool isLoaded; + CRect bounds; + char name[20]; + int16 minIndex; + int16 maxIndex; +}; + +class CColStore +{ + static CPool<ColDef,ColDef> *ms_pColPool; + +public: + static void Initialise(void); + static void Shutdown(void); + static int AddColSlot(const char *name); + static void RemoveColSlot(int32 slot); + static int FindColSlot(const char *name); + static char *GetColName(int32 slot); + static CRect &GetBoundingBox(int32 slot); + static void IncludeModelIndex(int32 slot, int32 modelIndex); + static bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize); + static void RemoveCol(int32 slot); + static void AddCollisionNeededAtPosn(const CVector2D &pos); + static void LoadAllCollision(void); + static void RemoveAllCollision(void); + static void LoadCollision(const CVector2D &pos); + static void RequestCollision(const CVector2D &pos); + static void EnsureCollisionIsInMemory(const CVector2D &pos); + static bool HasCollisionLoaded(const CVector2D &pos); + + static ColDef *GetSlot(int slot) { + assert(slot >= 0); + assert(ms_pColPool); + assert(slot < ms_pColPool->GetSize()); + return ms_pColPool->GetSlot(slot); + } +}; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 99be816f..268e3c5e 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -20,6 +20,10 @@ #include "SurfaceTable.h" #include "Lines.h" #include "Collision.h" +#include "Camera.h" +#include "ColStore.h" + +//--MIAMI: file done enum Direction { @@ -39,52 +43,22 @@ CCollision::Init(void) { ms_colModelCache.Init(NUMCOLCACHELINKS); ms_collisionInMemory = LEVEL_GENERIC; + CColStore::Initialise(); } void CCollision::Shutdown(void) { ms_colModelCache.Shutdown(); + CColStore::Shutdown(); } void CCollision::Update(void) { - CVector playerCoors; - playerCoors = FindPlayerCoors(); - eLevelName level = CTheZones::m_CurrLevel; - bool forceLevelChange = false; - - if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing()) - return; - - // hardcode a level if there are no zones - if(level == LEVEL_GENERIC){ - if(CGame::currLevel == LEVEL_INDUSTRIAL && - playerCoors.x < 400.0f){ - level = LEVEL_COMMERCIAL; - forceLevelChange = true; - }else if(CGame::currLevel == LEVEL_SUBURBAN && - playerCoors.x > -450.0f && playerCoors.y < -1400.0f){ - level = LEVEL_COMMERCIAL; - forceLevelChange = true; - }else{ - if(playerCoors.x > 800.0f){ - level = LEVEL_INDUSTRIAL; - forceLevelChange = true; - }else if(playerCoors.x < -800.0f){ - level = LEVEL_SUBURBAN; - forceLevelChange = true; - } - } - } - if(level != LEVEL_GENERIC && level != CGame::currLevel) - CGame::currLevel = level; - if(ms_collisionInMemory != CGame::currLevel) - LoadCollisionWhenINeedIt(forceLevelChange); - CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); } +//--MIAMI: unused eLevelName GetCollisionInSectorList(CPtrList &list) { @@ -101,6 +75,7 @@ GetCollisionInSectorList(CPtrList &list) return LEVEL_GENERIC; } +//--MIAMI: unused // Get a level this sector is in based on collision models eLevelName GetCollisionInSector(CSector §) @@ -124,133 +99,13 @@ GetCollisionInSector(CSector §) void CCollision::LoadCollisionWhenINeedIt(bool forceChange) { - eLevelName level, l; - bool multipleLevels; - CVector playerCoors; - CVehicle *veh; - CEntryInfoNode *ei; - int sx, sy; - int xmin, xmax, ymin, ymax; - int x, y; - - level = LEVEL_GENERIC; - - playerCoors = FindPlayerCoors(); - sx = CWorld::GetSectorIndexX(playerCoors.x); - sy = CWorld::GetSectorIndexY(playerCoors.y); - multipleLevels = false; - - veh = FindPlayerVehicle(); - if(veh && veh->IsTrain()){ - if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN) - return; - }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision()) - return; - - // Figure out whose level's collisions we're most likely to be interested in - if(!forceChange){ - if(veh && veh->IsBoat()){ - // on water we expect to be between levels - multipleLevels = true; - }else{ - xmin = Max(sx - 1, 0); - xmax = Min(sx + 1, NUMSECTORS_X-1); - ymin = Max(sy - 1, 0); - ymax = Min(sy + 1, NUMSECTORS_Y-1); - - for(x = xmin; x <= xmax; x++) - for(y = ymin; y <= ymax; y++){ - l = GetCollisionInSector(*CWorld::GetSector(x, y)); - if(l != LEVEL_GENERIC){ - if(level == LEVEL_GENERIC) - level = l; - if(level != l) - multipleLevels = true; - } - } - } - - if(multipleLevels && veh && veh->IsBoat()) - for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){ - level = GetCollisionInSector(*ei->sector); - if(level != LEVEL_GENERIC) - break; - } - } - - if(level == CGame::currLevel || forceChange){ - CTimer::Stop(); -#ifndef NO_ISLAND_LOADING - DMAudio.SetEffectsFadeVol(0); - CPad::StopPadsShaking(); - LoadCollisionScreen(CGame::currLevel); - DMAudio.Service(); -#endif - - CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false); - -#ifndef NO_ISLAND_LOADING - CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); - CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); - CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); - CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL); - CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL); - CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN); - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - CStreaming::RemoveUnusedModelsInLoadedList(); - CGame::TidyUpMemory(true, true); - CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); -#endif - - ms_collisionInMemory = CGame::currLevel; - CReplay::EmptyReplayBuffer(); -#ifndef NO_ISLAND_LOADING - if(CGame::currLevel != LEVEL_GENERIC) - LoadSplash(GetLevelSplashScreen(CGame::currLevel)); - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - CStreaming::RequestBigBuildings(CGame::currLevel); -#endif - CStreaming::LoadAllRequestedModels(true); -#ifndef NO_ISLAND_LOADING - CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); - - CGame::TidyUpMemory(true, true); -#endif - CTimer::Update(); -#ifndef NO_ISLAND_LOADING - DMAudio.SetEffectsFadeVol(127); -#endif - } } void CCollision::SortOutCollisionAfterLoad(void) { - if(ms_collisionInMemory == CGame::currLevel) - return; -#ifndef NO_ISLAND_LOADING - CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); -#endif - if (CGame::currLevel != LEVEL_GENERIC) { -#ifdef NO_ISLAND_LOADING - static bool bAlreadyLoaded = false; - if (bAlreadyLoaded) { - ms_collisionInMemory = CGame::currLevel; - return; - } - bAlreadyLoaded = true; - CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); - CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); - CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); -#else - CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); -#endif - if(!CGame::playingIntro) - LoadSplash(GetLevelSplashScreen(CGame::currLevel)); - } - ms_collisionInMemory = CGame::currLevel; - CGame::TidyUpMemory(true, false); + CColStore::LoadCollision(TheCamera.GetPosition()); + CStreaming::LoadAllRequestedModels(false); } void @@ -274,14 +129,14 @@ CCollision::LoadCollisionScreen(eLevelName level) bool -CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2) +CCollision::TestSphereSphere(const CSphere &s1, const CSphere &s2) { float d = s1.radius + s2.radius; return (s1.center - s2.center).MagnitudeSqr() < d*d; } bool -CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box) +CCollision::TestSphereBox(const CSphere &sph, const CBox &box) { if(sph.center.x + sph.radius < box.min.x) return false; if(sph.center.x - sph.radius > box.max.x) return false; @@ -293,7 +148,7 @@ CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box) } bool -CCollision::TestLineBox(const CColLine &line, const CColBox &box) +CCollision::TestLineBox(const CColLine &line, const CBox &box) { float t, x, y, z; // If either line point is in the box, we have a collision @@ -378,7 +233,7 @@ CCollision::TestLineBox(const CColLine &line, const CColBox &box) } bool -CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box) +CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box) { if(line.p0.x <= box.min.x) return false; if(line.p0.y <= box.min.y) return false; @@ -539,6 +394,8 @@ CCollision::TestSphereTriangle(const CColSphere &sphere, int testcase = insideAB + insideAC + insideBC; float dist = 0.0f; switch(testcase){ + case 0: + return false; // shouldn't happen case 1: // closest to a vertex if(insideAB) dist = (sphere.center - vc).Magnitude(); @@ -566,7 +423,7 @@ CCollision::TestSphereTriangle(const CColSphere &sphere, } bool -CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough) +CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough) { static CMatrix matTransform; int i; @@ -581,12 +438,14 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod for(i = 0; i < model.numSpheres; i++){ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue; if(TestLineSphere(newline, model.spheres[i])) return true; } for(i = 0; i < model.numBoxes; i++){ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue; if(TestLineBox(newline, model.boxes[i])) return true; } @@ -594,6 +453,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++){ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue; if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) return true; } @@ -601,6 +461,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod return false; } +// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used // // Process @@ -869,6 +730,7 @@ CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CC return true; } +//--MIAMI: unused bool CCollision::ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, @@ -1042,7 +904,7 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol bool CCollision::ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, - CColPoint &point, float &mindist) + CColPoint &point, float &mindist, CStoredCollPoly *poly) { float t; CVector normal; @@ -1115,6 +977,12 @@ CCollision::ProcessLineTriangle(const CColLine &line , point.pieceA = 0; point.surfaceB = tri.surface; point.pieceB = 0; + if(poly){ + poly->verts[0] = va; + poly->verts[1] = vb; + poly->verts[2] = vc; + poly->valid = true; + } mindist = t; return true; } @@ -1160,6 +1028,8 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, float dist = 0.0f; CVector p; switch(testcase){ + case 0: + return false; // shouldn't happen case 1: // closest to a vertex if(insideAB) p = vc; @@ -1203,7 +1073,7 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, bool CCollision::ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough) + CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough) { static CMatrix matTransform; int i; @@ -1219,17 +1089,20 @@ CCollision::ProcessLineOfSight(const CColLine &line, float coldist = mindist; for(i = 0; i < model.numSpheres; i++){ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue; ProcessLineSphere(newline, model.spheres[i], point, coldist); } for(i = 0; i < model.numBoxes; i++){ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue; ProcessLineBox(newline, model.boxes[i], point, coldist); } CalculateTrianglePlanes(&model); for(i = 0; i < model.numTriangles; i++){ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue; ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); } @@ -1245,7 +1118,7 @@ CCollision::ProcessLineOfSight(const CColLine &line, bool CCollision::ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, - CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly) + CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly) { static CStoredCollPoly TempStoredPoly; int i; @@ -1253,28 +1126,27 @@ CCollision::ProcessVerticalLine(const CColLine &line, // transform line to model space // Why does the game seem to do this differently than above? CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1)); - newline.p1.x = newline.p0.x; - newline.p1.y = newline.p0.y; - if(!TestVerticalLineBox(newline, model.boundingBox)) + if(!TestLineBox(newline, model.boundingBox)) return false; + // BUG? is IsSeeThroughVertical really the right thing? also not checking shoot through float coldist = mindist; for(i = 0; i < model.numSpheres; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue; ProcessLineSphere(newline, model.spheres[i], point, coldist); } for(i = 0; i < model.numBoxes; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue; ProcessLineBox(newline, model.boxes[i], point, coldist); } CalculateTrianglePlanes(&model); TempStoredPoly.valid = false; for(i = 0; i < model.numTriangles; i++){ - if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; - ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); + if(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue; + ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); } if(coldist < mindist){ @@ -1515,6 +1387,15 @@ CCollision::CalculateTrianglePlanes(CColModel *model) } void +CCollision::RemoveTrianglePlanes(CColModel *model) +{ + if(model->trianglePlanes){ + ms_colModelCache.Remove(model->GetLinkPtr()); + model->RemoveTrianglePlanes(); + } +} + +void CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) { int i; @@ -1736,15 +1617,75 @@ CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); } +static void +GetSurfaceColor(uint8 surf, uint8 &r, uint8 &g, uint8 &b) +{ + // game doesn't do this + r = 255; + g = 128; + b = 0; + + switch(CSurfaceTable::GetAdhesionGroup(surf)){ + case ADHESIVE_RUBBER: + r = 255; + g = 0; + b = 0; + break; + case ADHESIVE_HARD: + r = 255; + g = 255; + b = 128; + break; + case ADHESIVE_ROAD: + r = 128; + g = 128; + b = 128; + break; + case ADHESIVE_LOOSE: + r = 0; + g = 255; + b = 0; + break; + case ADHESIVE_SAND: + r = 255; + g = 128; + b = 128; + break; + case ADHESIVE_WET: + r = 0; + g = 0; + b = 255; + break; + } + + if(surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){ + r = 255; + g = 255; + b = 0; + } + + float f = (surf & 0xF)/32.0f + 0.5f; + r *= f; + g *= f; + b *= f; + + if(surf == SURFACE_TRANSPARENT_CLOTH || surf == SURFACE_METAL_CHAIN_FENCE || + surf == SURFACE_TRANSPARENT_STONE || surf == SURFACE_SCAFFOLD_POLE) + if(CTimer::GetFrameCounter() & 1){ + r = 0; + g = 0; + b = 0; + } +} + void CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id) { int i; int s; - float f; CVector verts[8]; CVector min, max; - int r, g, b; + uint8 r, g, b; RwImVertexIndex *iptr; RwIm3DVertex *vptr; @@ -1763,53 +1704,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, verts[1] = mat * verts[1]; verts[2] = mat * verts[2]; - // game doesn't do this - r = 255; - g = 128; - b = 0; - s = colModel.triangles[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } + GetSurfaceColor(s, r, g, b); if(s > SURFACE_METAL_GATE){ r = CGeneral::GetRandomNumber(); @@ -1850,47 +1746,7 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, verts[7] = mat * CVector(max.x, max.y, max.z); s = colModel.boxes[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } + GetSurfaceColor(s, r, g, b); RenderBuffer::StartStoring(36, 8, &iptr, &vptr); RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); @@ -1962,6 +1818,21 @@ CColSphere::Set(float radius, const CVector ¢er, uint8 surf, uint8 piece) this->piece = piece; } +bool +CColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit) +{ + CVector distToCenter = from - center; + float distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius); + float root1, root2; + + if (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2)) + return false; + + entry = from + dir * root1; + exit = from + dir * root2; + return true; +} + void CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece) { @@ -2003,6 +1874,19 @@ CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS; } +CColPoint& +CColPoint::operator=(const CColPoint& other) +{ + point = other.point; + normal = other.normal; + surfaceA = other.surfaceA; + pieceA = other.pieceA; + surfaceB = other.surfaceB; + pieceB = other.pieceB; + // doesn't copy depth + return *this; +} + CColModel::CColModel(void) { numSpheres = 0; @@ -2015,7 +1899,7 @@ CColModel::CColModel(void) vertices = nil; triangles = nil; trianglePlanes = nil; - level = CGame::currLevel; + level = 0; // generic col slot ownsCollisionVolumes = true; } @@ -2034,6 +1918,7 @@ CColModel::RemoveCollisionVolumes(void) RwFree(boxes); RwFree(vertices); RwFree(triangles); + CCollision::RemoveTrianglePlanes(this); } numSpheres = 0; numLines = 0; diff --git a/src/core/Collision.h b/src/core/Collision.h index d988f0c2..eb11d8c4 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -23,26 +23,38 @@ struct CompressedVector #endif }; -struct CColSphere +struct CSphere { CVector center; float radius; + void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; } +}; + +struct CBox +{ + CVector min; + CVector max; + CVector GetSize(void) { return max - min; } + void Set(const CVector &min, const CVector &max) { this->min = min; this->max = max; } +}; + +struct CColSphere : public CSphere +{ uint8 surface; uint8 piece; void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece); - void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; } + bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit); + using CSphere::Set; }; -struct CColBox +struct CColBox : public CBox { - CVector min; - CVector max; uint8 surface; uint8 piece; void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece); - CVector GetSize(void) { return max - min; } + using CBox::Set; }; struct CColLine @@ -91,6 +103,8 @@ struct CColPoint uint8 surfaceB; uint8 pieceB; float depth; + + CColPoint& operator=(const CColPoint& other); }; struct CStoredCollPoly @@ -99,16 +113,17 @@ struct CStoredCollPoly bool valid; }; +//--MIAMI: done struct struct CColModel { - CColSphere boundingSphere; - CColBox boundingBox; + CSphere boundingSphere; + CBox boundingBox; int16 numSpheres; - int16 numLines; int16 numBoxes; int16 numTriangles; - int32 level; - bool ownsCollisionVolumes; // missing on PS2 + int8 numLines; + uint8 level; // colstore slot but probably still named level + bool ownsCollisionVolumes; CColSphere *spheres; CColLine *lines; CColBox *boxes; @@ -144,26 +159,27 @@ public: static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id); static void CalculateTrianglePlanes(CColModel *model); + static void RemoveTrianglePlanes(CColModel *model); // all these return true if there's a collision - static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2); - static bool TestSphereBox(const CColSphere &sph, const CColBox &box); - static bool TestLineBox(const CColLine &line, const CColBox &box); - static bool TestVerticalLineBox(const CColLine &line, const CColBox &box); + static bool TestSphereSphere(const CSphere &s1, const CSphere &s2); + static bool TestSphereBox(const CSphere &sph, const CBox &box); + static bool TestLineBox(const CColLine &line, const CBox &box); + static bool TestVerticalLineBox(const CColLine &line, const CBox &box); static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); static bool TestLineSphere(const CColLine &line, const CColSphere &sph); static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); - static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough); + static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough); static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq); static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq); static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist); static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly); - static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist); + static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly = nil); static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist); static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); - static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough); - static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly); + static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough); + static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly); static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly); diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 6a5080e5..d194cebb 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -131,6 +131,7 @@ void CControllerConfigManager::SaveSettings(int32 file) void CControllerConfigManager::LoadSettings(int32 file) { bool bValid = true; + int nVersion = 0; if (file) { @@ -139,11 +140,13 @@ void CControllerConfigManager::LoadSettings(int32 file) if (!strncmp(buff, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1)) bValid = false; - else + else { CFileMgr::Seek(file, 0, 0); + CFileMgr::Read(file, (char*)&nVersion, sizeof(nVersion)); + } } - if (bValid) + if (bValid && nVersion >= 3) { ControlsManager.MakeControllerActionsBlank(); @@ -202,9 +205,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); @@ -217,6 +224,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 ? @@ -259,7 +268,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++) { @@ -336,13 +345,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); case 10: SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); case 9: SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); case 8: SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); case 7: - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); case 6: SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -384,13 +394,14 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) SetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, 11, JOYSTICK); case 10: SetControllerKeyAssociatedWithAction(VEHICLE_HORN, 10, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_DUCK, 10, JOYSTICK); case 9: SetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, 9, JOYSTICK); case 8: SetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, 8, JOYSTICK); SetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, 8, JOYSTICK); case 7: - SetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, 7, JOYSTICK); + SetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, 7, JOYSTICK); SetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 7, JOYSTICK); case 6: SetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, 6, JOYSTICK); @@ -430,8 +441,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); @@ -454,6 +468,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); @@ -754,6 +772,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) @@ -762,14 +782,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; @@ -835,7 +859,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)) { @@ -1616,8 +1640,12 @@ void CControllerConfigManager::DeleteMatching3rdPersonControls(e_ControllerActio ClearSettingsAssociatedWithAction(PED_JUMPING, type); if (key == GetControllerKeyAssociatedWithAction(PED_SPRINT, type)) ClearSettingsAssociatedWithAction(PED_SPRINT, type); + if (key == GetControllerKeyAssociatedWithAction(PED_DUCK, type)) + ClearSettingsAssociatedWithAction(PED_DUCK, type); + if (key == GetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, type)) + ClearSettingsAssociatedWithAction(PED_ANSWER_PHONE, type); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (key == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type)) ClearSettingsAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type); @@ -1640,7 +1668,7 @@ void CControllerConfigManager::DeleteMatching1rst3rdPersonControls(e_ControllerA if (key == GetControllerKeyAssociatedWithAction(GO_BACK, type)) ClearSettingsAssociatedWithAction(GO_BACK, type); - if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) + if (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC) { if (key == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_LEFT, type)) ClearSettingsAssociatedWithAction(PED_1RST_PERSON_LOOK_LEFT, type); @@ -1786,23 +1814,25 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio { switch (action) { - case CAMERA_CHANGE_VIEW_ALL_SITUATIONS: case PED_FIREWEAPON: 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: @@ -1829,13 +1859,13 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio return ACTIONTYPE_VEHICLE_3RDPERSON; break; - 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; diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 7d0e1073..05c37c22 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, VEHICLE_ACCELERATE, VEHICLE_BRAKE, VEHICLE_CHANGE_RADIO_STATION, @@ -59,6 +61,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 8dfae5b8..3c3e2b26 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 675040ea..e5f264c7 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -67,8 +67,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); @@ -189,8 +187,9 @@ CEventList::FindClosestEvent(eEventType type, CVector posn, int32 *event) return found; } +// --MIAMI: Done void -CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCare) +CEventList::ReportCrimeForEvent(eEventType type, size_t crimeId, bool copsDontCare) { eCrimeType crime; switch(type){ @@ -203,27 +202,39 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar 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->m_nWantedLevel == 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; CVector playerPedCoors = FindPlayerPed()->GetPosition(); 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 8840afc4..0531aed7 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -22,10 +22,12 @@ 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_ICECREAM, EVENT_ATM, - EVENT_SHOPSTALL, // used on graffitis + EVENT_SHOPSTALL, + EVENT_SHOPWINDOW, EVENT_LAST_EVENT }; @@ -59,7 +61,7 @@ public: static bool GetEvent(eEventType type, int32 *event); static void ClearEvent(int32 event); static bool FindClosestEvent(eEventType type, CVector posn, int32 *event); - static void ReportCrimeForEvent(eEventType type, int32, bool); + static void ReportCrimeForEvent(eEventType type, size_t, bool); }; extern CEvent gaEvent[NUMEVENTS];
\ No newline at end of file diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index b4da1a5e..635192ea 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 "Quaternion.h" @@ -24,6 +25,11 @@ #include "ZoneCull.h" #include "CdStream.h" #include "FileLoader.h" +#include "Streaming.h" +#include "ColStore.h" +#include "Occlusion.h" + +//--MIAMI: file done char CFileLoader::ms_line[256]; @@ -46,14 +52,12 @@ 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); @@ -77,12 +81,8 @@ CFileLoader::LoadLevel(const char *filename) AddTexDictionaries(savedTxd, txd); RwTexDictionaryDestroy(txd); }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); @@ -94,15 +94,17 @@ CFileLoader::LoadLevel(const char *filename) LoadObjectTypes(line + 4); }else if(strncmp(line, "IPL", 3) == 0){ if(!objectsLoaded){ - CModelInfo::ConstructMloClumps(); + LoadingScreenLoadingFile("Collision"); CObjectData::Initialise("DATA\\OBJECT.DAT"); + CStreaming::Init(); + CColStore::LoadAllCollision(); + for(int i = 0; i < MODELINFOSIZE; i++) + if(CModelInfo::GetModelInfo(i)) + CModelInfo::GetModelInfo(i)->ConvertAnimFileIndex(); objectsLoaded = true; } LoadingScreenLoadingFile(line + 4); LoadScene(line + 4); - }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()); @@ -114,30 +116,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* @@ -181,7 +166,7 @@ struct ColHeader }; void -CFileLoader::LoadCollisionFile(const char *filename) +CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) { int fd; char modelname[24]; @@ -190,6 +175,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(strncmp(header.ident, "COLL", 4) == 0); @@ -198,10 +184,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); } @@ -213,6 +200,79 @@ CFileLoader::LoadCollisionFile(const char *filename) CFileMgr::CloseFile(fd); } + +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(strncmp(header->ident, "COLL", 4) != 0) + 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(strncmp(header->ident, "COLL", 4) != 0) + 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) { @@ -242,13 +302,15 @@ 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)); 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; @@ -267,10 +329,12 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector)); 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 @@ -293,7 +357,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){ @@ -319,11 +383,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); } @@ -331,6 +395,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data) return atomic; } +#ifdef LIBRW +void +InitClump(RpClump *clump) +{ + RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil); +} +#else +#define InitClump(clump) +#endif + void CFileLoader::LoadModelFile(const char *filename) { @@ -342,6 +416,7 @@ CFileLoader::LoadModelFile(const char *filename) if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ clump = RpClumpStreamRead(stream); if(clump){ + InitClump(clump); RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump); RpClumpDestroy(clump); } @@ -367,6 +442,7 @@ CFileLoader::LoadClumpFile(const char *filename) GetNameAndLOD(nodename, name, &n); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil); if(mi){ + InitClump(clump); assert(mi->IsClump()); mi->SetClump(clump); }else @@ -387,16 +463,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); - if(clump){ - ((CPedModelInfo*)mi)->SetLowDetailClump(clump); - RpClumpDestroy(clump); - } - } return true; } @@ -422,6 +491,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id) clump = RpClumpGtaStreamRead2(stream); if(clump){ + InitClump(clump); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi->SetClump(clump); return true; @@ -442,6 +512,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) clump = RpClumpStreamRead(stream); if(clump == nil) return false; + InitClump(clump); gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump); RpClumpDestroy(clump); @@ -458,11 +529,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; } @@ -477,6 +548,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename) stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) clump = RpClumpStreamRead(stream); + if(clump) + InitClump(clump); RwStreamClose(stream, nil); return clump; } @@ -500,8 +573,9 @@ CFileLoader::LoadObjectTypes(const char *filename) enum { NONE, OBJS, - MLO, + MLO, // unused but enum still has it TOBJ, + WEAP, HIER, CARS, PEDS, @@ -512,16 +586,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; @@ -529,25 +604,27 @@ CFileLoader::LoadObjectTypes(const char *filename) if(section == NONE){ if(strncmp(line, "objs", 4) == 0) section = OBJS; else if(strncmp(line, "tobj", 4) == 0) section = TOBJ; + else if(strncmp(line, "weap", 4) == 0) section = WEAP; else if(strncmp(line, "hier", 4) == 0) section = HIER; else if(strncmp(line, "cars", 4) == 0) section = CARS; else if(strncmp(line, "peds", 4) == 0) section = PEDS; else if(strncmp(line, "path", 4) == 0) section = PATH; else if(strncmp(line, "2dfx", 4) == 0) section = TWODFX; }else if(strncmp(line, "end", 3) == 0){ - section = section == MLO ? OBJS : NONE; + section = NONE; }else switch(section){ case OBJS: - if(strncmp(line, "sta", 3) == 0) - 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); @@ -560,17 +637,15 @@ CFileLoader::LoadObjectTypes(const char *filename) break; case PATH: if(pathIndex == -1){ - id = LoadPathHeader(line, pathTypeStr); - if(strncmp(pathTypeStr, "ped", 4) == 0) - pathType = 1; - else if(strncmp(pathTypeStr, "car", 4) == 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; @@ -583,26 +658,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); + 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; @@ -613,7 +692,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: @@ -645,60 +724,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 someFloat; - - sscanf(line, "%s %s %d %f", smth, name, &modelIndex, &someFloat); - CMloModelInfo *minfo = CModelInfo::AddMloModel(modelIndex); - minfo->SetName(name); - minfo->field_34 = someFloat; - 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; @@ -710,7 +740,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: @@ -746,6 +776,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->SetName(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 @@ -768,21 +821,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->SetName(model); mi->SetTexDictionary(txd); + mi->SetAnimFile(animFile); for(p = gamename; *p; p++) if(*p == '_') *p = ' '; strcpy(mi->m_gameName, gamename); @@ -812,36 +866,34 @@ CFileLoader::LoadVehicleObject(const char *line) mi->m_handlingId = mod_HandlingManager.GetHandlingId(handlingId); - // Well this is kinda dumb.... - if(strncmp(vehclass, "poorfamily", 11) == 0){ + if(strncmp(vehclass, "normal", 7) == 0) + mi->m_vehicleClass = CCarCtrl::NORMAL; + else if(strncmp(vehclass, "poorfamily", 11) == 0) mi->m_vehicleClass = CCarCtrl::POOR; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::POOR); - }else if(strncmp(vehclass, "richfamily", 11) == 0){ + else if(strncmp(vehclass, "richfamily", 11) == 0) mi->m_vehicleClass = CCarCtrl::RICH; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::RICH); - }else if(strncmp(vehclass, "executive", 10) == 0){ + else if(strncmp(vehclass, "executive", 10) == 0) mi->m_vehicleClass = CCarCtrl::EXEC; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::EXEC); - }else if(strncmp(vehclass, "worker", 7) == 0){ + else if(strncmp(vehclass, "worker", 7) == 0) mi->m_vehicleClass = CCarCtrl::WORKER; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::WORKER); - }else if(strncmp(vehclass, "special", 8) == 0){ - mi->m_vehicleClass = CCarCtrl::SPECIAL; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::SPECIAL); - }else if(strncmp(vehclass, "big", 4) == 0){ + else if(strncmp(vehclass, "big", 4) == 0) mi->m_vehicleClass = CCarCtrl::BIG; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::BIG); - }else if(strncmp(vehclass, "taxi", 5) == 0){ + else if(strncmp(vehclass, "taxi", 5) == 0) mi->m_vehicleClass = CCarCtrl::TAXI; - while(frequency-- > 0) - CCarCtrl::AddToCarArray(id, CCarCtrl::TAXI); + else if(strncmp(vehclass, "moped", 6) == 0) + mi->m_vehicleClass = CCarCtrl::MOPED; + else if(strncmp(vehclass, "motorbike", 10) == 0) + mi->m_vehicleClass = CCarCtrl::MOTORBIKE; + else if(strncmp(vehclass, "leisureboat", 12) == 0) + mi->m_vehicleClass = CCarCtrl::LEISUREBOAT; + else if(strncmp(vehclass, "workerboat", 11) == 0) + mi->m_vehicleClass = CCarCtrl::WORKERBOAT; + else if(strncmp(vehclass, "ignore", 11) == 0){ + mi->m_vehicleClass = -1; + return; } + CCarCtrl::AddToCarArray(id, mi->m_vehicleClass); + mi->m_frequency = frequency; } void @@ -849,67 +901,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->SetName(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; @@ -982,6 +1054,18 @@ CFileLoader::Load2dEffect(const char *line) effect->attractor.type = flags; effect->attractor.probability = probability; 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(); @@ -995,20 +1079,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; @@ -1019,6 +1104,7 @@ CFileLoader::LoadScene(const char *filename) else if(strncmp(line, "cull", 4) == 0) section = CULL; else if(strncmp(line, "pick", 4) == 0) section = PICK; else if(strncmp(line, "path", 4) == 0) section = PATH; + else if(strncmp(line, "occl", 4) == 0) section = OCCL; }else if(strncmp(line, "end", 3) == 0){ section = NONE; }else switch(section){ @@ -1031,18 +1117,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); - // 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; @@ -1065,18 +1157,30 @@ 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()); + if(!CStreaming::IsObjectInCdImage(id)) + debug("Not in cdimage %s\n", mi->GetName()); + angle = -RADTODEG(2.0f * acosf(angle)); xform = RwMatrixCreate(); RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE); @@ -1091,7 +1195,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) @@ -1100,14 +1205,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); @@ -1153,53 +1269,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(strncmp(line, "zone", 4) == 0) section = ZONE; - }else if(strncmp(line, "end", 3) == 0){ - 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); } + +//--MIAMI: unused void CFileLoader::ReloadPaths(const char *filename) { @@ -1210,10 +1294,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; @@ -1229,17 +1313,15 @@ CFileLoader::ReloadPaths(const char *filename) switch (section) { case PATH: if (pathIndex == -1) { - id = LoadPathHeader(line, pathTypeStr); - if (strncmp(pathTypeStr, "ped", 4) == 0) - pathType = 1; - else if (strncmp(pathTypeStr, "car", 4) == 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; @@ -1269,6 +1351,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 == '#') @@ -1344,6 +1427,7 @@ 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)) { 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/FileMgr.cpp b/src/core/FileMgr.cpp index ac51f8de..4477a190 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -274,13 +274,13 @@ CFileMgr::OpenFileForWriting(const char *file) } size_t -CFileMgr::Read(int fd, const char *buf, int len) +CFileMgr::Read(int fd, const char *buf, size_t len) { return myfread((void*)buf, 1, len, fd); } size_t -CFileMgr::Write(int fd, const char *buf, int len) +CFileMgr::Write(int fd, const char *buf, size_t len) { return myfwrite((void*)buf, 1, len, fd); } diff --git a/src/core/FileMgr.h b/src/core/FileMgr.h index 0ad9daa7..51e30694 100644 --- a/src/core/FileMgr.h +++ b/src/core/FileMgr.h @@ -13,8 +13,8 @@ public: static int OpenFile(const char *file, const char *mode); static int OpenFile(const char *file) { return OpenFile(file, "rb"); } static int OpenFileForWriting(const char *file); - static size_t Read(int fd, const char *buf, int len); - static size_t Write(int fd, const char *buf, int len); + static size_t Read(int fd, const char *buf, size_t len); + static size_t Write(int fd, const char *buf, size_t len); static bool Seek(int fd, int offset, int whence); static bool ReadLine(int fd, char *buf, int len); static int CloseFile(int fd); diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index c6dece6a..a6928def 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -15,6 +15,7 @@ #include "DamageManager.h" #include "Ped.h" #include "Fire.h" +#include "GameLogic.h" CFireManager gFireManager; @@ -59,6 +60,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 +91,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); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 95d5f6e6..ccb89fbd 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -36,7 +36,22 @@ #include "Stats.h" #include "Messages.h" #include "FileLoader.h" -#include "frontendoption.h" + +// TODO(Miami): Remove that!! That was my map implementation for III, instead use MAP_ENHACEMENTS on some places +#define CUSTOM_MAP + +// Similar story to Hud.cpp: +// Game has colors inlined in code. +// For easier modification we collect them here: +CRGBA LABEL_COLOR(255, 150, 225, 255); +CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255); +CRGBA MENUOPTION_COLOR(255, 150, 225, 255); +CRGBA SELECTEDMENUOPTION_COLOR(255, 150, 225, 255); +CRGBA HEADER_COLOR(255, 150, 255, 255); +CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); +CRGBA SLIDERON_COLOR(97, 194, 247, 255); +CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); +CRGBA LIST_BACKGROUND_COLOR(49, 101, 148, 255); #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -50,11 +65,7 @@ #define FEET_IN_METER 3.33f #endif -#ifdef SCROLLABLE_STATS_PAGE -#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS) -#else #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) -#endif #ifdef TRIANGLE_BACK_BUTTON #define GetBackJustUp GetTriangleJustUp @@ -67,14 +78,6 @@ #define GetBackJustDown GetSquareJustDown #endif -#ifdef MENU_MAP -bool CMenuManager::bMenuMapActive = false; -bool CMenuManager::bMapMouseShownOnce = false; -bool CMenuManager::bMapLoaded = false; -float CMenuManager::fMapSize; -float CMenuManager::fMapCenterY; -float CMenuManager::fMapCenterX; -#endif #ifdef PS2_LIKE_MENU BottomBarOption bbNames[8]; @@ -87,39 +90,10 @@ int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #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; - -int8 CMenuManager::m_PrefsUseWideScreen; -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; - #ifdef CUTSCENE_BORDERS_SWITCH bool CMenuManager::m_PrefsCutsceneBorders = true; #endif -char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; - -int32 CMenuManager::m_KeyPressedCode = -1; - // Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) #ifdef PS2_LIKE_MENU const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); @@ -130,99 +104,54 @@ const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color 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); + +#ifdef CUSTOM_MAP +bool bMapLoaded = false; +bool bMapMouseShownOnce = false; +#endif #ifndef MASTER bool CMenuManager::m_PrefsMarketing = false; bool CMenuManager::m_PrefsDisableTutorials = false; #endif // !MASTER -// 0x5F311C +// 0x68C144 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 MENU_MAP -const char* MapFilenames[][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 ASPECT_RATIO_SCALE @@ -251,77 +180,40 @@ ScaleAndCenterX(float x) #define MENU_Y(y) StretchY(y) #endif -#ifdef PS2_LIKE_MENU -#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \ - do { \ - if (reverseAlpha) { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = pendingScreen; \ - m_nCurrOption = pendingOption; \ - reverseAlpha = false; \ - if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - if (withReverseAlpha) { \ - pendingOption = option; \ - pendingScreen = screen; \ - reverseAlpha = true; \ - } else { \ - m_nPrevScreen = m_nCurrScreen; \ - m_nCurrScreen = screen; \ - m_nCurrOption = option; \ - if (updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - } \ - m_nMenuFadeAlpha = 255; \ - } while(0) -#else -#define ChangeScreen(screen, option, updateDelay, clearAlpha) \ - do { \ - m_nPrevScreen = m_nCurrScreen; \ - int newOpt = option; \ - m_nCurrScreen = screen; \ - m_nCurrOption = newOpt; \ - if(updateDelay) \ - m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \ - if(clearAlpha) \ - m_nMenuFadeAlpha = 0; \ - } while(0) -#endif - #define PREPARE_MENU_HEADER \ - CFont::SetColor(CRGBA(0, 0, 0, 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 ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ +#define ProcessSlider(value, y, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ - lastActiveBarX = DisplaySlider(MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ + 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(hoverStartX, 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))) \ + if (!CheckHover(MENU_X(3.0f) + lastActiveBarX, hoverEndX, MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) \ 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; \ } while(0) +// TODO: this is COMPLETELY different in VC #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(225, 0, 0, 170)); \ + sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(255, 255, 255, 100)); \ 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) { @@ -335,7 +227,7 @@ CMenuManager::ScrollUpListByOne() } } -void +inline void CMenuManager::ScrollDownListByOne() { if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { @@ -351,13 +243,13 @@ CMenuManager::ScrollDownListByOne() } } -void +inline void CMenuManager::PageUpList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList > 0) { if(playSoundOnSuccess) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); @@ -369,13 +261,13 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) } } -void +inline void CMenuManager::PageDownList(bool playSoundOnSuccess) { if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { if(playSoundOnSuccess) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList); @@ -387,13 +279,13 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } } -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); } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - if (m_nPrefsAudio3DProviderIndex != -1) + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); @@ -401,19 +293,18 @@ CMenuManager::ThingsToDoBeforeGoingBack() #endif } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { m_nDisplayVideoMode = m_nPrefsVideoMode; +#ifdef IMPROVED_VIDEOMODE + m_nSelectedScreenMode = m_nPrefsWindowed; +#endif } if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { CPlayerSkin::EndFrontendSkinEdit(); } - if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { - m_nTotalListRow = 0; - } - #ifdef CUSTOM_FRONTEND_OPTIONS for (int i = 0; i < numCustomFrontendOptions; i++) { - FrontendOption &option = customFrontendOptions[i]; + FrontendOption& option = customFrontendOptions[i]; if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) { if (option.returnPrevPageFunc) option.returnPrevPageFunc(); @@ -432,9 +323,10 @@ int8 CMenuManager::GetPreviousPageOption() { #ifndef CUSTOM_FRONTEND_OPTIONS - return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; + 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)))); #else - int8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; + int8 prevPage = aScreens[m_nCurrScreen].m_PreviousPage; if (prevPage == -1) // Game also does same return 0; @@ -448,12 +340,201 @@ CMenuManager::GetPreviousPageOption() } // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?) - return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; + 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 } // ------ Functions not in the game/inlined ends +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); + +#ifdef PS2_LIKE_MENU +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + if (reverseAlpha) { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = pendingScreen; + m_nCurrOption = pendingOption; + reverseAlpha = false; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + if (withReverseAlpha) { + pendingOption = option; + pendingScreen = screen; + reverseAlpha = true; + } else { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = screen; + m_nCurrOption = option; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + m_nMenuFadeAlpha = 255; +} +#else + +// --MIAMI: Done +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(); + + ThingsToDoBeforeLeavingPage(); + + if (screen == -2) { + int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; + int oldOption = GetPreviousPageOption(); + + 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_nCurrOption = 0; + m_nCurrScreen = screen; + } + + if (m_nPrevScreen == MENUPAGE_SKIN_SELECT || m_nPrevScreen == MENUPAGE_KEYBOARD_CONTROLS) + m_nTotalListRow = 0; + + if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) + m_nCurrOption = 8; + m_nMenuFadeAlpha = 0; + m_nOptionHighlightTransitionBlend = 0; + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); +} +#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; + m_PrefsUseWideScreen = 0; + 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; + field_10 = 0; + m_bShutDownFrontEndRequested = false; + m_bStartUpFrontEndRequested = false; + pEditString = nil; + pControlEdit = nil; + DisplayComboButtonErrMsg = false; + m_PrefsDMA = 1; + OS_Language = LANG_ENGLISH; + m_ControlMethod = CONTROL_STANDARD; + CCamera::m_bUseMouse3rdPerson = true; + 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; + + // TODO(Miami) + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + m_bMenuActive = false; + m_bActivateSaveMenu = false; + m_bWantToLoad = false; + m_nMenuFadeAlpha = 0; + m_OnlySaveMenu = false; + m_fMapSize = 162.0f; + m_fMapCenterX = 320.0f; + m_fMapCenterY = 225.0f; + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); +} + +void +CMenuManager::SetFrontEndRenderStates(void) +{ + 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); +} + +void +CMenuManager::Initialise(void) +{ + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + m_AllowNavigation = false; + m_menuTransitionProgress = -50; // to start from black + m_nMenuFadeAlpha = 0; + m_nCurrOption = 0; + m_nOptionHighlightTransitionBlend = 0; + CentreMousePointer(); + m_bShowMouse = true; + m_fMapSize = 162.0f; + m_fMapCenterX = 320.0f; + m_fMapCenterY = 225.0f; + CPad::StopPadsShaking(); + if (!m_OnlySaveMenu) + 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); + m_PrefsRadioStation = DMAudio.GetRadioInCar(); + + // TODO(Miami) + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); + if (DMAudio.IsMP3RadioChannelAvailable()) { + if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > USERTRACK) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; + } else if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; + + CFileMgr::SetDir(""); + //CFileMgr::SetDir(""); + PcSaveHelper.PopulateSlotInfo(); + CTimer::StartUserPause(); +} + void CMenuManager::BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2) { @@ -588,31 +669,30 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512/16); - m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 511); + m_PrefsBrightness += value * 24.19f; + m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 384); break; case MENUACTION_DRAWDIST: if(value > 0) - m_PrefsLOD += ((1.8f - 0.8f) / 16.0f); + m_PrefsLOD += ((1.8f - 0.925f) / 16.0f); else - m_PrefsLOD -= ((1.8f - 0.8f) / 16.0f); - m_PrefsLOD = clamp(m_PrefsLOD, 0.8f, 1.8f); + m_PrefsLOD -= ((1.8f - 0.925f) / 16.0f); + m_PrefsLOD = clamp(m_PrefsLOD, 0.925f, 1.8f); CRenderer::ms_lodDistScale = m_PrefsLOD; break; case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128/16); - m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 127); + m_PrefsMusicVolume += value * (128/32); + m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 65); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128/16); - m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 127); + m_PrefsSfxVolume += value * (128/32); + m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 65); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); break; case MENUACTION_MOUSESENS: TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; break; default: return; @@ -620,89 +700,120 @@ CMenuManager::CheckSliderMovement(int value) SaveSettings(); } +// --MIAMI: Done void -CMenuManager::DisplayHelperText() +CMenuManager::DisplayHelperText(char *text) { + if (m_nMenuFadeAlpha != 255) + return; + // there was a unused static bool - static uint32 LastFlash = 0; - int32 alpha; + static PauseModeTime LastFlash = 0; + 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 + if (text) { + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get(text)); + return; + } + + if (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) { if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 10) { LastFlash = CTimer::GetTimeInMillisecondsPauseMode(); m_nHelperTextAlpha -= 2; } -#else - static float fadeAlpha = 0.0f; // To keep it precisely - if (m_nHelperTextAlpha >= 255 && fadeAlpha < 250) fadeAlpha = m_nHelperTextAlpha; - // -2 per every 33 ms (1000.f/30.f - original frame limiter fps) - fadeAlpha -= (frameTime / 33.0f) * 2.0f; - m_nHelperTextAlpha = fadeAlpha; -#endif if (m_nHelperTextAlpha < 1) ResetHelperText(); alpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha; } - CFont::SetCentreOn(); - CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - + 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(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); - } - break; - } case 1: - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_APP")); break; case 2: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_HRD")); break; case 3: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_RSO")); break; case 4: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_STS")); + break; + case 5: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), 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(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + 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(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + 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(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + 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(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nCurrScreen != MENUPAGE_STATS ? TheText.Get("FET_MIG") : TheText.Get("FEH_SSA")); + break; } - CFont::SetRightJustifyOff(); } +// --MIAMI: Done 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 < 16; i++) { curBarX = i * rectSize/16.0f + x; if (i / 16.0f + 1 / 32.0f < progress) { - color = CRGBA(255, 217, 106, FadeIn(255)); + color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255)); lastActiveBarX = curBarX; } else - color = CRGBA(185, 120, 0, FadeIn(255)); + color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255)); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); @@ -718,83 +829,90 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR return lastActiveBarX; } +// TODO(Miami) void CMenuManager::DoSettingsBeforeStartingAGame() { - CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#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); + SwitchMenuOnAndOff(); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); } void -CMenuManager::Draw() +CMenuManager::DrawStandardMenus(bool drawCurrScreen) { + float nextYToUse = 0.0f; // III leftover, set but unused in VC +#ifdef PS2_LIKE_MENU + bool itemsAreSelectable = !bottomBarActive; +#else + bool itemsAreSelectable = true; +#endif CFont::SetBackgroundOff(); CFont::SetPropOn(); CFont::SetCentreOff(); CFont::SetJustifyOn(); - CFont::SetBackGroundOnlyTextOn(); -#ifdef GTA3_1_1_PATCH - CFont::SetColor(CRGBA(235, 170, 50, 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); -#endif - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); + CFont::SetBackGroundOnlyTextOff(); + + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_UNK_X_MARGIN)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENU_UNK_WIDTH)); + CFont::SetCentreSize(SCREEN_WIDTH); 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(130))); + break; + /* + // TODO(Miami) + case MENUPAGE_SOUND_SETTINGS: + PrintSoundSettings(); + 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') { - + PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(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(235, 170, 50, 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(SCREEN_SCALE_X(MENULABEL_WIDTH)); + 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) @@ -802,8 +920,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 + 1] == SLOT_OK) + str = TheText.Get("FESZ_QO"); + else if (Slots[m_nCurrSaveSlot + 1] == SLOT_CORRUPTED) str = TheText.Get("FESZ_QZ"); else str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); @@ -819,621 +942,544 @@ 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(MENU_UNK_X_MARGIN)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENU_UNK_WIDTH)); } - CFont::SetCentreSize(SCREEN_WIDTH); + if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + if (m_bWaitingForNewKeyBind) + itemsAreSelectable = false; -#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; - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_GRAPHICS_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: - 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; - - 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]; char asciiTemp[32]; -#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, 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 - -#ifdef CUSTOM_FRONTEND_OPTIONS - static int lastOption = m_nCurrOption; -#endif + bool weHaveLabel = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; + uint8 section = 0; // 0: highlight trapezoid 1: texts - for (int i = 0; i < NUM_MENUROWS; ++i) { -#ifdef CUSTOM_FRONTEND_OPTIONS - bool isOptionDisabled = false; -#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; + while (section < 2) { + for (int i = 0; i < NUM_MENUROWS; ++i) { + 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(); - leftText = GetNameOfSavedGame(i - 1); + } 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 && !aScreens[m_nCurrScreen].m_aEntries[i].m_Y) { + if (i == 0 || (i == 1 && weHaveLabel)) { + aScreens[m_nCurrScreen].m_aEntries[i].m_X = MENU_DEFAULT_CONTENT_X; + aScreens[m_nCurrScreen].m_aEntries[i].m_Y = MENU_DEFAULT_CONTENT_Y; + + } 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 + MENU_DEFAULT_LINE_HEIGHT; + } + } - if (Slots[i] != SLOT_EMPTY) - rightText = GetSavedGameDateAndTime(i - 1); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') { - if (leftText[0] == '\0') { - sprintf(gString, "FEM_SL%d", i); - leftText = TheText.Get(gString); + if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) { + CFont::SetRightJustifyOff(); + + 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 (strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEO_AUD", 8) == 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 LEGACY_MENU_OPTIONS + 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"); +#endif + case MENUACTION_FRAMESYNC: + rightText = TheText.Get(m_PrefsVsyncDisp ? "FEM_ON" : "FEM_OFF"); break; - case 2: - rightText = TheText.Get("FEC_CF3"); + case MENUACTION_FRAMELIMIT: + rightText = TheText.Get(m_PrefsFrameLimiter ? "FEM_ON" : "FEM_OFF"); break; - case 3: - rightText = TheText.Get("FEC_CF4"); + case MENUACTION_TRAILS: + rightText = TheText.Get(CMBlur::BlurOn ? "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_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: - sprintf(asciiTemp, "AUTO"); - break; - case AR_4_3: - sprintf(asciiTemp, "4:3"); + switch (m_PrefsUseWideScreen) { + case AR_AUTO: + sprintf(asciiTemp, "AUTO"); + break; + case AR_4_3: + sprintf(asciiTemp, "4:3"); + break; + case AR_16_9: + sprintf(asciiTemp, "16:9"); + break; + } + + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; +#endif break; - case AR_16_9: - sprintf(asciiTemp, "16:9"); + + case MENUACTION_MUSICVOLUME: + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) + rightText = TheText.Get("FEA_NAH"); + break; - } + case MENUACTION_RADIO: + if (m_PrefsRadioStation > USERTRACK) + break; - AsciiToUnicode(asciiTemp, unicodeTemp); - rightText = unicodeTemp; + sprintf(gString, "FEA_FM%d", m_PrefsRadioStation); + rightText = TheText.Get(gString); + break; + case MENUACTION_LEGENDS: + rightText = TheText.Get(m_PrefsShowLegends ? "FEM_ON" : "FEM_OFF"); + break; + 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 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); + break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + if (m_nSelectedScreenMode == 0) + sprintf(asciiTemp, "FULLSCREEN"); + else + sprintf(asciiTemp, "WINDOWED"); + + AsciiToUnicode(asciiTemp, unicodeTemp); rightText = unicodeTemp; + break; +#endif + 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* 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"); + } + 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"); - break; - case 1: - rightText = TheText.Get("FEA_EAR"); + case MENUACTION_CTRLMETHOD: { + switch (m_ControlMethod) { + case CONTROL_STANDARD: + leftText = TheText.Get("FET_STI"); 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_TRIGGERFUNC: - FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { - leftText = (wchar*)option.leftText; - if (option.type == FEOPTION_SELECT) { - if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) - option.displayedValue = 0; + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { + leftText = (wchar*)option.leftText; + if (option.type == FEOPTION_SELECT) { + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) + option.displayedValue = 0; - rightText = (wchar*)option.rightTexts[option.displayedValue]; + rightText = (wchar*)option.rightTexts[option.displayedValue]; - } else if (option.type == FEOPTION_DYNAMIC) { - if (option.drawFunc) { - rightText = option.drawFunc(&isOptionDisabled); + } else if (option.type == FEOPTION_DYNAMIC) { + if (option.drawFunc) { + bool isOptionDisabled = false; + rightText = option.drawFunc(&isOptionDisabled); + if (isOptionDisabled) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } } + } else { + debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options is borked"); } - } else { - debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); - assert(0 && "Custom frontend options is borked"); - } - break; + break; #endif - } + } - float nextItemY = headerHeight + nextYToUse; - float bitAboveNextItemY = nextItemY - 2.0f; - int nextYToCheck = bitAboveNextItemY; - - if (!foundTheHoveringItem) { - for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) { - if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING) - break; + // Highlight trapezoid + if (drawCurrScreen && i == m_nCurrOption && itemsAreSelectable && section == 0) { - int extraOffset = 0; - if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO) - extraOffset = MENURADIO_ICON_SCALE; + int leftXMax, rightXMin; - // There were many unused codes in here to calculate how much space will texts gonna take. + // FIX: Let's don't scale those so GetStringWidth will give unscaled width, which will be handy to other calculations below that's done without scaling in mind. + // 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); + + 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); + } 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; + } + CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + + 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) { + rightXMin = 600; + leftXMax = 40; + } - // 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; + int topYMax = y; + uint32 bottomYMin = y + 22; + int transition = m_nOptionHighlightTransitionBlend; - 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 (transition == 0) { + if (m_menuTransitionProgress == 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 (transition < 255) { + menuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend); + if (m_menuTransitionProgress == 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_menuTransitionProgress == 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) + static PauseModeTime lastBlendChange = 0; + if (m_nOptionHighlightTransitionBlend <= 255) { + static uint32 blendChangeCounter = 0; + if (CTimer::GetTimeInMillisecondsPauseMode() - lastBlendChange > 20 +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack + || blendChangeCounter > 20 #endif - if (i == m_nCurrOption && itemsAreSelectable) { - // 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(100, 200, 50, FadeIn(50))); - } + ) { + m_nOptionHighlightTransitionBlend += 50; + lastBlendChange = CTimer::GetTimeInMillisecondsPauseMode(); + blendChangeCounter = 0; + } + ++blendChangeCounter; + } + } - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); + if (section != 0) { - // Button and it's shadow - for(int textLayer = 0; textLayer < 2; textLayer++) { - if (!CFont::Details.centre) - CFont::SetRightJustifyOff(); + 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), 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(600.0f), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y), 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 + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { + + 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 + && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + m_nDisplayVideoMode = m_nPrefsVideoMode; + SetHelperText(3); + } + } +#ifdef IMPROVED_VIDEOMODE + if (m_nSelectedScreenMode != m_nPrefsWindowed) { + if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_POS") != 0 + && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { + m_nSelectedScreenMode = m_nPrefsWindowed; + } + } +#endif #ifdef CUSTOM_FRONTEND_OPTIONS - || isOptionDisabled + static int lastOption = m_nCurrOption; + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_TRIGGERFUNC) { + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (option.onlyApplyOnEnter && m_nCurrOption != i) + option.displayedValue = *option.value; + + if (m_nCurrOption != lastOption && lastOption == i) { + FrontendOption& oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; + if (oldOption.type == FEOPTION_DYNAMIC) + oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + } + } + + if (i == MAX_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i + 1].m_EntryName[0] == '\0') + lastOption = m_nCurrOption; #endif - ) - CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); - CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); - } - if (i == m_nCurrOption && itemsAreSelectable){ - CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); - } else { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); - } - } + // TODO(Miami): check + // Sliders + int lastActiveBarX; + switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { + case MENUACTION_BRIGHTNESS: + ProcessSlider(m_PrefsBrightness / 384.0f, 70.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_DRAWDIST: + ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, 99.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_MUSICVOLUME: + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsMusicVolume / 64.0f, 70.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); + break; + case MENUACTION_SFXVOLUME: + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) + ProcessSlider(m_PrefsSfxVolume / 64.0f, 99.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, 170.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, MENU_X_LEFT_ALIGNED(200.0f), SCREEN_WIDTH); + break; + } - 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 - && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != -1) { + nextYToUse = MENU_Y(150.f); // TODO(Miami): Temp - 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 - && m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_nDisplayVideoMode = m_nPrefsVideoMode; - SetHelperText(3); - } - } + nextYToUse += MENU_DEFAULT_LINE_HEIGHT * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); -#ifdef CUSTOM_FRONTEND_OPTIONS - if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_TRIGGERFUNC) { - FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; - if (option.onlyApplyOnEnter && m_nCurrOption != i) - option.displayedValue = *option.value; - - if (m_nCurrOption != lastOption && lastOption == i) { - FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; - if (oldOption.type == FEOPTION_DYNAMIC) - oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); - } - } -#endif + // TODO(Miami): Remove here after audio page is done + // Radio icons + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WILDSTYLE], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FLASH], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_KCHAT], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FEVER], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VROCK], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VCPR], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_ESPANTOSO], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_EMOTION], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WAVE], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); - // 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; - } + if (DMAudio.IsMP3RadioChannelAvailable()) + ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_MP3], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); - // 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; + nextYToUse += 70.0f; + } + } } } + section++; } -#ifdef CUSTOM_FRONTEND_OPTIONS - lastOption = m_nCurrOption; -#endif - switch (m_nCurrScreen) { - case MENUPAGE_CONTROLLER_SETTINGS: - case MENUPAGE_SOUND_SETTINGS: - case MENUPAGE_GRAPHICS_SETTINGS: - case MENUPAGE_SKIN_SELECT: - case MENUPAGE_CONTROLLER_PC: - case MENUPAGE_MOUSE_CONTROLS: - DisplayHelperText(); - break; + case MENUPAGE_STATS: + case MENUPAGE_CONTROLLER_PC: + case MENUPAGE_SOUND_SETTINGS: + case MENUPAGE_GRAPHICS_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; } - 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"); + } else if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) { + SmallMessageScreen("FESZ_WR"); } - } int @@ -1441,12 +1487,14 @@ 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: @@ -1754,7 +1802,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::PrintString(nextX, nextY, seperator); nextX += CFont::GetStringWidth(seperator, true) + bindingMargin; } - static uint32 lastWaitingTextFlash = 0; + static PauseModeTime lastWaitingTextFlash = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastWaitingTextFlash > 150) { showWaitingText = !showWaitingText; lastWaitingTextFlash = CTimer::GetTimeInMillisecondsPauseMode(); @@ -1775,7 +1823,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); if (!m_bKeyIsOK) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); @@ -1788,7 +1836,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 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 CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); m_bKeyIsOK = false; m_bKeyChangeNotProcessed = false; } @@ -1800,7 +1848,7 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 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 CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); } } } @@ -1839,7 +1887,7 @@ CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeig CFont::PrintString(nextX, MENU_Y(yStart), TheText.Get("FEC_IBT")); nextX = CFont::GetStringWidth(TheText.Get("FEC_IBT"), true) + spacing + nextX; } - static uint32 lastStateChange = 0; + static PauseModeTime lastStateChange = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastStateChange > 150) { waitingTextVisible = !waitingTextVisible; lastStateChange = CTimer::GetTimeInMillisecondsPauseMode(); @@ -1883,18 +1931,28 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetJustifyOn(); CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); - - PREPARE_MENU_HEADER + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_UNK_X_MARGIN)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENU_UNK_WIDTH)); switch (m_ControlMethod) { case CONTROL_STANDARD: - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), + PREPARE_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(aScreens[m_nCurrScreen].m_ScreenName)); + + 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)); break; case CONTROL_CLASSIC: - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), + PREPARE_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_CTI")); + + 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_CTI")); break; default: @@ -1963,7 +2021,7 @@ CMenuManager::DrawControllerSetupScreen() CFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get("FET_CCR")); CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X_LEFT_ALIGNED(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); int yStart; if (m_ControlMethod == CONTROL_CLASSIC) yStart = CONTSETUP_LIST_HEADER_HEIGHT + 29; @@ -1981,7 +2039,7 @@ CMenuManager::DrawControllerSetupScreen() float curOptY = i * rowHeight + yStart; if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { if (m_nOptionMouseHovering != i && m_nCurrExLayer == HOVEROPTION_LIST) - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nOptionMouseHovering = i; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { @@ -1995,7 +2053,7 @@ CMenuManager::DrawControllerSetupScreen() 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); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN; #ifdef FIX_BUGS @@ -2004,7 +2062,7 @@ CMenuManager::DrawControllerSetupScreen() } 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); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; } @@ -2071,6 +2129,10 @@ void CMenuManager::DrawFrontEnd() { CFont::SetAlphaFade(255.0f); + CSprite2d::InitPerFrame(); + CFont::InitPerFrame(); + SetFrontEndRenderStates(); + m_NoEmptyBinding = true; #ifdef PS2_LIKE_MENU if (m_nCurrScreen == MENUPAGE_NONE) { @@ -2114,63 +2176,15 @@ CMenuManager::DrawFrontEnd() 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(); - - PrintErrorMessage(); -} - -#ifdef PS2_SAVE_DIALOG -void -CMenuManager::DrawFrontEndSaveZone() -{ - 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); + if (m_menuTransitionProgress == 255 && m_nMenuFadeAlpha == 255) + bMenuChangeOngoing = false; - 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)); - } - } + DrawBackground(false); } -#endif #ifdef PS2_LIKE_MENU void -CMenuManager::DrawFrontEndNormal() +CMenuManager::DrawBackground() { CSprite2d::InitPerFrame(); CFont::InitPerFrame(); @@ -2287,7 +2301,7 @@ CMenuManager::DrawFrontEndNormal() DrawControllerSetupScreen(); break; default: - Draw(); + DrawStandardMenus(); break; } @@ -2310,7 +2324,7 @@ CMenuManager::DrawFrontEndNormal() if (CheckHover(xStart, xStart + optionWidth, optionTop, optionBottom)) hoveredBottomBarOption = i; - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); CFont::SetScale(MENU_X(0.35f), MENU_Y(0.7f)); CFont::SetRightJustifyOff(); if (hoveredBottomBarOption == i && hoveredBottomBarOption != curBottomBarOption) @@ -2350,168 +2364,191 @@ CMenuManager::DrawFrontEndNormal() 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)); + m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); - m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); }else{ - m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); + m_aFrontEndSprites[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(mouse, CRGBA(255, 255, 255, 255)); } } } #else + +// --MIAMI: Done except commented things void -CMenuManager::DrawFrontEndNormal() +CMenuManager::DrawBackground(bool transitionCall) { - CSprite2d::InitPerFrame(); - CFont::InitPerFrame(); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + if (!m_bSpritesLoaded) + return; - LoadSplash(nil); - - eMenuSprites previousSprite; - if (m_nMenuFadeAlpha < 255) { - switch (m_nPrevScreen) { + SetFrontEndRenderStates(); + + if (m_menuTransitionProgress < 255) { + CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); + } + + if (m_nMenuFadeAlpha != 0) { + + if (m_nMenuFadeAlpha < 255) { + + 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(); + + // 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 { + m_nMenuFadeAlpha = 255; + m_menuTransitionProgress = 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 { + 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; + 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_MULTIPLAYER_CREATE: - previousSprite = MENUSPRITE_HOSTGAME; - break; - case MENUPAGE_SKIN_SELECT_OLD: - case MENUPAGE_OPTIONS: - previousSprite = MENUSPRITE_PLAYERSET; + case MENUPAGE_BRIEFS: + case MENUPAGE_GRAPHICS_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: - 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; + menuBg.UpdateMultipliers(); + if (m_menuTransitionProgress == 255) + m_nOptionHighlightTransitionBlend = 0; } - if (m_nMenuFadeAlpha < 255) { + static PauseModeTime LastFade = 0; + static uint8 forceFadeInCounter = 0; - // Famous transparent menu bug -#ifdef FIX_BUGS - static float fadeAlpha = 0.0f; - if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f; - - // +20 per every 33 ms (1000.f/30.f - original frame limiter fps) - fadeAlpha += (frameTime) * 20.f / 33.f; - m_nMenuFadeAlpha = fadeAlpha; -#else - static uint32 LastFade = 0; - - if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ + if (m_nMenuFadeAlpha >= 255) { + if (m_nMenuFadeAlpha > 255) + m_nMenuFadeAlpha = 255; + } else { + if (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 30 +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack + || forceFadeInCounter > 30 +#endif + ) { m_nMenuFadeAlpha += 20; + m_menuTransitionProgress = Min(m_menuTransitionProgress + 20, 255); LastFade = CTimer::GetTimeInMillisecondsPauseMode(); } -#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; - } + forceFadeInCounter++; } - // 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_menuTransitionProgress == 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: + CMenuManager::DrawPlayerSetupScreen(); + break; + case MENUPAGE_KEYBOARD_CONTROLS: + CMenuManager::DrawControllerSetupScreen(); + break; + case MENUPAGE_OUTRO: + CMenuManager::DrawQuitGameScreen(); + break; + default: + CMenuManager::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(); @@ -2519,35 +2556,47 @@ CMenuManager::DrawFrontEndNormal() case MENUPAGE_KEYBOARD_CONTROLS: DrawControllerSetupScreen(); break; + case MENUPAGE_OUTRO: + CMenuManager::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_menuTransitionProgress == 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 PauseModeTime 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(40.0f), MENU_Y(40.0f)); + CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(55.0f), MENU_Y(43.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 @@ -2562,12 +2611,12 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetJustifyOn(); CFont::SetRightJustifyOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_UNK_X_MARGIN)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENU_UNK_WIDTH)); PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -2680,7 +2729,7 @@ CMenuManager::DrawPlayerSetupScreen() // Skin list CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(PLAYERSETUP_ROW_TEXT_X_SCALE), MENU_Y(PLAYERSETUP_ROW_TEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); if (m_nSkinsTotal > 0) { for (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin->skinId != m_nFirstVisibleRowOnList; m_pSelectedSkin = m_pSelectedSkin->nextSkin); @@ -2708,7 +2757,7 @@ CMenuManager::DrawPlayerSetupScreen() SaveSettings(); } } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = rowIdx; m_nHoverOption = HOVEROPTION_NOT_HOVERING; @@ -2788,21 +2837,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 @@ -2810,21 +2859,21 @@ 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 @@ -2864,7 +2913,7 @@ CMenuManager::DrawPlayerSetupScreen() && 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); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nHoverOption = HOVEROPTION_BACK; @@ -2875,7 +2924,7 @@ CMenuManager::DrawPlayerSetupScreen() && 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); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_nHoverOption = HOVEROPTION_USESKIN; @@ -2966,16 +3015,11 @@ CMenuManager::DrawPlayerSetupScreen() 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) +CMenuManager::FilterOutColorMarkersFromString(wchar *str) { int newIdx = 0; wchar copy[256], *c; @@ -2984,16 +3028,6 @@ CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) 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; @@ -3007,12 +3041,14 @@ 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; @@ -3083,94 +3119,85 @@ CMenuManager::LoadAllTextures() if (m_bSpritesLoaded) return; - CentreMousePointer(); - DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0); - m_nCurrOption = 0; - m_PrefsRadioStation = DMAudio.GetRadioInCar(); - - if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % 10; - } else if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = CGeneral::GetRandomNumber() % 9; - - CFileMgr::SetDir(""); - //CFileMgr::SetDir(""); + field_F0 = SCREEN_STRETCH_X(178.0f); // TODO(Miami) 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); -#ifndef GTA3_1_1_PATCH - 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); } - int menuTxdSlot = CTxdStore::FindTxdSlot("menu"); + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); - if (menuTxdSlot == -1) - menuTxdSlot = CTxdStore::AddTxdSlot("menu"); + if (!m_OnlySaveMenu) { + CStreaming::MakeSpaceFor(692 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile + CStreaming::ImGonnaUseStreamingMemory(); + CTxdStore::PushCurrentTxd(); - printf("LOAD sprite\n"); - CTxdStore::LoadTxd(menuTxdSlot, "MODELS/MENU.TXD"); - CTxdStore::AddRef(menuTxdSlot); - CTxdStore::SetCurrentTxd(menuTxdSlot); + int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2"); - 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 - for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) { - m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); - m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + if (frontendTxdSlot2 == -1) + frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2"); + + printf("LOAD frontend2\n"); + CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD"); + CTxdStore::AddRef(frontendTxdSlot2); + CTxdStore::SetCurrentTxd(frontendTxdSlot2); + + for (int i = 3; i < NUM_MENU_SPRITES; i++) { + m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); + m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); + } + + CTxdStore::PopCurrentTxd(); + CStreaming::IHaveUsedStreamingMemory(); } -#endif -#ifdef GTA3_1_1_PATCH - CStreaming::IHaveUsedStreamingMemory(); - CTimer::Update(); -#endif + m_bSpritesLoaded = true; - CTxdStore::PopCurrentTxd(); + CTimer::Update(); } +// --MIAMI: Done void CMenuManager::LoadSettings() { CFileMgr::SetDirMyDocuments(); - int fileHandle = CFileMgr::OpenFile("gta3.set", "r"); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "r"); int32 prevLang = m_PrefsLanguage; -#ifdef GTA3_1_1_PATCH - 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)); @@ -3194,34 +3221,42 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, gString, 20); CFileMgr::Read(fileHandle, gString, 4); CFileMgr::Read(fileHandle, gString, 4); +#ifdef FREE_CAM + CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#else CFileMgr::Read(fileHandle, gString, 1); +#endif + +#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); -#ifdef FREE_CAM - CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowLegends, 1); #ifdef CUTSCENE_BORDERS_SWITCH CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); #endif @@ -3231,12 +3266,17 @@ CMenuManager::LoadSettings() CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); + CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#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 { @@ -3268,15 +3308,18 @@ CMenuManager::LoadSettings() } } +// --MIAMI: Done void CMenuManager::SaveSettings() { static char RubbishString[48] = "stuffmorestuffevenmorestuff etc"; + static int SomeVersion = 3; 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)); @@ -3290,48 +3333,54 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, RubbishString, 20); CFileMgr::Write(fileHandle, RubbishString, 4); CFileMgr::Write(fileHandle, RubbishString, 4); +#ifdef FREE_CAM + CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#else CFileMgr::Write(fileHandle, RubbishString, 1); +#endif + +#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); -#ifdef FREE_CAM - CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowLegends, 1); #ifdef CUTSCENE_BORDERS_SWITCH CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); #endif } + m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); } -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)) @@ -3341,54 +3390,60 @@ 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(); +} +// --MIAMI: Done +void +CMenuManager::SmallMessageScreen(const char* text) +{ CFont::SetBackgroundOff(); CFont::SetPropOn(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f)); - CFont::SetRightJustifyWrap(SCREEN_SCALE_FROM_RIGHT(170.0f)); - CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_SCALE_FROM_BOTTOM(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_STRETCH_X(430.0f)); CFont::SetCentreOn(); - CFont::SetColor(CRGBA(255, 217, 106, 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(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(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)); } +// --MIAMI: Done, but FilterOutColorMarkersFromString is actually in CFont void CMenuManager::PrintBriefs() { - CFont::SetColor(CRGBA(235, 170, 50, 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, @@ -3397,319 +3452,211 @@ 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); - -#ifdef PS2_LIKE_MENU - // This PS2 code was always here, but unused - bool rgSame = newColor.r == TEXT_COLOR.r && newColor.g == TEXT_COLOR.g; - bool bSame = rgSame && newColor.b == TEXT_COLOR.b; - bool colorNotChanged = bSame; /* && newColor.a == TEXT_COLOR.a; */ - - if (!colorNotChanged) { - newColor.r /= 2; - newColor.g /= 2; - newColor.b /= 2; - } - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // But this is from PS2 - CFont::SetDropShadowPosition(1); -#endif + FilterOutColorMarkersFromString(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 +// --MIAMI: Done void -CMenuManager::PrintErrorMessage() +CMenuManager::PrintStats() { - if (!CPad::bDisplayNoControllerMessage && !CPad::bObsoleteControllerMessage) - return; + static uint8 pirateCheck = 0; + 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 = 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(130))); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); CFont::SetPropOn(); - CFont::SetCentreOff(); - CFont::SetJustifyOn(); - CFont::SetRightJustifyOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f)); -#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); -#ifdef GTA3_1_1_PATCH - CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); -#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; + if (pirateCheck == 0) + // if not pirated game + pirateCheck = 46; + // else + // pirateCheck = 45; - // 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 PauseModeTime 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; -#endif + if (pirateCheck == 45) + return; + + 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) { + if (y > MENU_Y(STATS_VISIBLE_START_Y) && y < MENU_Y(STATS_VISIBLE_END_Y)) { 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; + } - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255.0f * alphaMult))); + // 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(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(235, 170, 50, 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. - /* - PREPARE_MENU_HEADER - CFont::PrintString(MENU_X_RIGHT_ALIGNED(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)); + CFont::SetScale(MENU_X(0.5f), MENU_Y(0.9f)); + 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); } +// --MIAMI: Done void CMenuManager::Process(void) { - m_bMenuStateChanged = false; - - 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(); - - SwitchMenuOnAndOff(); - - // Be able to re-open menu correctly. if (m_bMenuActive) { + ProcessButtonPresses(); + ProcessFileActions(); + DMAudio.Service(); - // Load frontend textures. - LoadAllTextures(); + // Game calls some texture pool cleanup functions in here + } - // Set save/delete game pages. - if (m_nCurrScreen == MENUPAGE_DELETING) { - bool SlotPopulated = false; + SwitchMenuOnAndOff(); +} - if (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) { - PcSaveHelper.PopulateSlotInfo(); - SlotPopulated = true; - } +// TODO(Miami) +void +CMenuManager::ProcessButtonPresses(void) +{ + if (m_nCurrScreen == MENUPAGE_OUTRO) + return; - 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_bWaitingForNewKeyBind) { + if (m_bStartWaitingForKeyBind) + m_bStartWaitingForKeyBind = false; + else { + pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); + JoyButtonJustClicked = false; + MouseButtonJustClicked = false; + + if (CPad::GetPad(0)->GetLeftMouseJustDown()) + MouseButtonJustClicked = 1; + else if (CPad::GetPad(0)->GetRightMouseJustUp()) + MouseButtonJustClicked = 3; + else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) + MouseButtonJustClicked = 2; + else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) + MouseButtonJustClicked = 4; + else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) + MouseButtonJustClicked = 5; + // TODO two more buttons + + 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; } -#endif - if (CheckSlotDataValid(m_nCurrSaveSlot)) { -#ifdef USE_DEBUG_SCRIPT_LOADER - scriptToLoad = 0; -#endif - TheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; - 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(); - } - - ProcessButtonPresses(); + else if (!m_bKeyChangeNotProcessed) { + if (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked) + CheckCodesForControls(TypeOfControl); - // Set binding keys. - if (pEditString && CPad::EditString(pEditString, 0) == nil) { - if (*pEditString == 0) - strcpy(pEditString, "NoName"); - pEditString = nil; - SaveSettings(); - } - - if (m_bWaitingForNewKeyBind) { - if (m_bStartWaitingForKeyBind) - m_bStartWaitingForKeyBind = false; + field_159 = true; + } else { - pControlEdit = CPad::EditCodesForControls(pControlEdit, 1); - JoyButtonJustClicked = false; - MouseButtonJustClicked = false; - - if (CPad::GetPad(0)->GetLeftMouseJustDown()) - MouseButtonJustClicked = 1; - else if (CPad::GetPad(0)->GetRightMouseJustUp()) - MouseButtonJustClicked = 3; - else if (CPad::GetPad(0)->GetMiddleMouseJustUp()) - MouseButtonJustClicked = 2; - else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) - MouseButtonJustClicked = 4; - else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) - MouseButtonJustClicked = 5; - // TODO two more buttons - - 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; - } + 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 ((m_nCurrScreen == MENUPAGE_NO_MEMORY_CARD || m_nCurrScreen == MENUPAGE_PS2_LOAD_FAILED) && CTimer::GetTimeInMillisecondsPauseMode() > field_558) { - m_nCurrScreen = m_nPrevScreen; - m_nCurrOption = 0; - } - - // Reset pad shaking. - if (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) { - CPad::StopPadsShaking(); - TimeToStopPadShaking = 0; - } - - } else { - UnloadTextures(); - m_bRenderGameInMenu = false; - // byte_5F33E4 = 1; // unused - ChangeScreen(MENUPAGE_NONE, 0, false, false); - pEditString = nil; - m_bWaitingForNewKeyBind = false; } - if (!m_bWantToRestart) { - if (m_bGameNotLoaded) - DMAudio.Service(); - } -} - -void -CMenuManager::ProcessButtonPresses(void) -{ if (pEditString || pControlEdit) return; @@ -3743,6 +3690,51 @@ CMenuManager::ProcessButtonPresses(void) m_bShowMouse = true; } + static int oldOption = -99; + oldOption = m_nCurrOption; + for (int rowToCheck = 0; rowToCheck < NUM_MENUROWS; ++rowToCheck) { + if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING || + aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_LABEL) + continue; + + int extraOffset = 0; + if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO) + extraOffset = MENURADIO_ICON_SCALE; + + if (m_nMousePosY > MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y) && + m_nMousePosY < MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y + MENU_DEFAULT_LINE_HEIGHT)) { + 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) + m_nHoverOption = HOVEROPTION_RANDOM_ITEM; + + break; + } + if (m_bShowMouse && m_nMenuFadeAlpha == 255) { + m_nOptionMouseHovering = oldOption; + m_nCurrOption = oldOption; + } + } + + 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_MENU_NEW_PAGE, 0); + } + } + m_nMouseOldPosX = m_nMousePosX; m_nMouseOldPosY = m_nMousePosY; m_nMousePosX = m_nMouseTempPosX; @@ -3753,8 +3745,7 @@ CMenuManager::ProcessButtonPresses(void) if (m_nMousePosY < 0) m_nMousePosY = 0; if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT; - if (m_nCurrScreen == MENUPAGE_MULTIPLAYER_FIND_GAME || m_nCurrScreen == MENUPAGE_SKIN_SELECT - || m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { + if (m_nCurrScreen == MENUPAGE_SKIN_SELECT || m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) { m_nTotalListRow = m_nSkinsTotal; @@ -3765,13 +3756,11 @@ CMenuManager::ProcessButtonPresses(void) m_nSelectedListRow = m_nTotalListRow - 1; } -#ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { m_bShowMouse = 0; optionSelected = true; } -#endif - if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) { + 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; @@ -3780,10 +3769,10 @@ CMenuManager::ProcessButtonPresses(void) pControlEdit = &m_KeyPressedCode; } } else { - field_535 = false; + field_159 = false; } - static uint32 lastTimeClickedScrollButton = 0; + static PauseModeTime lastTimeClickedScrollButton = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) { m_bPressedPgUpOnList = false; @@ -3795,7 +3784,7 @@ CMenuManager::ProcessButtonPresses(void) } if (CPad::GetPad(0)->GetTabJustDown()) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); m_bShowMouse = false; switch (m_nCurrExLayer) { case HOVEROPTION_BACK: @@ -3831,7 +3820,7 @@ CMenuManager::ProcessButtonPresses(void) if (!m_bPressedUpOnList) { m_bPressedUpOnList = true; lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); ScrollUpListByOne(); } } else { @@ -3853,7 +3842,7 @@ CMenuManager::ProcessButtonPresses(void) if (!m_bPressedDownOnList) { m_bPressedDownOnList = true; lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); ScrollDownListByOne(); } } else { @@ -3869,7 +3858,7 @@ CMenuManager::ProcessButtonPresses(void) m_bPressedPgUpOnList = true; lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); PageUpList(false); } } @@ -3881,14 +3870,14 @@ CMenuManager::ProcessButtonPresses(void) m_bPressedPgDnOnList = true; lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode(); m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); PageDownList(false); } } if (CPad::GetPad(0)->GetHome()) { m_nCurrExLayer = HOVEROPTION_LIST; m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) { m_nFirstVisibleRowOnList = 0; } @@ -3898,7 +3887,7 @@ CMenuManager::ProcessButtonPresses(void) if (CPad::GetPad(0)->GetEnd()) { m_nCurrExLayer = HOVEROPTION_LIST; m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) { m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; } @@ -3907,12 +3896,10 @@ CMenuManager::ProcessButtonPresses(void) } } -#ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) { m_bShowMouse = false; goBack = true; } -#endif if (CPad::GetPad(0)->GetLeftMouseJustDown()) { switch (m_nHoverOption) { @@ -3983,7 +3970,6 @@ CMenuManager::ProcessButtonPresses(void) } } } else if (isPlainTextScreen(m_nCurrScreen)) { -#ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) { optionSelected = true; } @@ -3992,19 +3978,19 @@ CMenuManager::ProcessButtonPresses(void) goBack = true; } } -#endif } else { if (CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); goDown = true; + m_nOptionHighlightTransitionBlend = 0; } else if (CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 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; @@ -4016,7 +4002,6 @@ CMenuManager::ProcessButtonPresses(void) optionSelected = true; } } -#endif if (CPad::GetPad(0)->GetLeftMouseJustUp()) { #ifndef TIDY_UP_PBP @@ -4211,16 +4196,14 @@ CMenuManager::ProcessButtonPresses(void) case HOVEROPTION_INCREASE_MOUSESENS: TheCamera.m_fMouseAccelHorzntl += (1.0f / 3000); TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; case HOVEROPTION_DECREASE_MOUSESENS: TheCamera.m_fMouseAccelHorzntl -= (1.0f / 3000); TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; - } + } #else switch (m_nHoverOption) { case HOVEROPTION_INCREASE_BRIGHTNESS: @@ -4239,7 +4222,7 @@ CMenuManager::ProcessButtonPresses(void) break; } #endif - } + } if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp() || CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp() @@ -4254,7 +4237,6 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } -#ifndef TIDY_UP_PBP if (CPad::GetPad(0)->GetBackJustDown()) { if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) { m_bShowMouse = false; @@ -4272,53 +4254,19 @@ 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())) { - - if (!isPlainTextScreen(m_nCurrScreen)) - m_bShowMouse = false; - - optionSelected = true; - } - } else { - if (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) { - m_bShowMouse = false; - optionSelected = true; - } } - 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; - } - } - } - } -#endif #ifdef PS2_LIKE_MENU if (CPad::GetPad(0)->GetLeftMouseJustDown() && hoveredBottomBarOption != -1) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); bottomBarActive = false; curBottomBarOption = hoveredBottomBarOption; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, false); return; } else if (bottomBarActive) { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); bottomBarActive = false; // If there's a menu change with fade ongoing, finish it now @@ -4328,7 +4276,7 @@ CMenuManager::ProcessButtonPresses(void) } 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()) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); if (curBottomBarOption > 0) curBottomBarOption--; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); @@ -4336,7 +4284,7 @@ CMenuManager::ProcessButtonPresses(void) } 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()) { m_bShowMouse = false; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); if (curBottomBarOption < bbTabCount-1) curBottomBarOption++; ChangeScreen(bbNames[curBottomBarOption].screenId, 0, true, true); @@ -4348,14 +4296,13 @@ CMenuManager::ProcessButtonPresses(void) } #endif - int prevOption = m_nCurrOption; - if (goDown && (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME)) { + if (goDown) { m_nCurrOption++; if (m_nCurrOption == NUM_MENUROWS || (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NOTHING)) { m_nCurrOption = 0; } } - if (goUp && (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME)) { + if (goUp) { 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) { @@ -4368,7 +4315,8 @@ CMenuManager::ProcessButtonPresses(void) if (optionSelected) { int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if ((option == MENUACTION_CHANGEMENU) || (option == MENUACTION_POPULATESLOTS_CHANGEMENU)) { + if (option == MENUACTION_CHANGEMENU || option == MENUACTION_POPULATESLOTS_CHANGEMENU || option == MENUACTION_GOBACK + || option == MENUACTION_YES || option == MENUACTION_NO) { if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) != 0 && strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FESZ_CA", 8) != 0) { @@ -4399,8 +4347,9 @@ CMenuManager::ProcessButtonPresses(void) } } 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) { + && option != MENUACTION_CHECKSAVE && option != MENUACTION_MOUSESENS + && option != MENUACTION_YES && option != MENUACTION_NO + && option != MENUACTION_SCREENRES) { DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } @@ -4444,14 +4393,9 @@ CMenuManager::ProcessButtonPresses(void) 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 + SwitchToNewScreen(-2); } - } else if (m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME) { + } else { option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; switch (option) { case MENUACTION_RADIO: @@ -4506,48 +4450,21 @@ CMenuManager::ProcessButtonPresses(void) // fall through case MENUACTION_CHANGEMENU: + case MENUACTION_YES: + case MENUACTION_NO: { - 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; - } +#ifdef CUSTOM_MAP + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { + bMapLoaded = false; } - if (changeMenu) { - if (strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 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; -#endif - } else { -#ifdef MENU_MAP - if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { - bMapLoaded = false; - } #endif - ChangeScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, 0, true, true); - } - } + SwitchToNewScreen(0); break; } + case MENUACTION_GOBACK: + goBack = true; + break; case MENUACTION_CHECKSAVE: { int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; @@ -4555,7 +4472,11 @@ CMenuManager::ProcessButtonPresses(void) 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); + 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); + } } } break; @@ -4566,43 +4487,11 @@ CMenuManager::ProcessButtonPresses(void) 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); + SwitchToNewScreen(MENUPAGE_KEYBOARD_CONTROLS); m_nSelectedListRow = 0; m_nCurrExLayer = HOVEROPTION_LIST; break; @@ -4615,41 +4504,50 @@ CMenuManager::ProcessButtonPresses(void) break; case MENUACTION_CANCELGAME: DMAudio.Service(); - RsEventHandler(rsQUITAPP, nil); + SwitchToNewScreen(MENUPAGE_OUTRO); break; case MENUACTION_RESUME: -#ifndef TIDY_UP_PBP +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) { m_PrefsVsync = m_PrefsVsyncDisp; } - RequestFrontEndShutDown(); -#else - goBack = true; #endif + RequestFrontEndShutDown(); break; case MENUACTION_DONTCANCEL: - ChangeScreen(!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0], - GetPreviousPageOption(), true, true); + SwitchToNewScreen(-2); break; case MENUACTION_SCREENRES: if (m_nDisplayVideoMode != m_nPrefsVideoMode) { m_nPrefsVideoMode = m_nDisplayVideoMode; _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); + DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); + DMAudio.Service(); + CentreMousePointer(); + m_bShowMouse = true; + // m_nCurrOption = 5; // Why? TODO(Miami) + m_nOptionHighlightTransitionBlend = 0; + SaveSettings(); + } + break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + if (m_nSelectedScreenMode != m_nPrefsWindowed) { + m_nPrefsWindowed = m_nSelectedScreenMode; + _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution SaveSettings(); } break; +#endif case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != -1) { + if (selectedProvider != NO_AUDIO_PROVIDER) { + if (selectedProvider == -1) + selectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); 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); + if (selectedProvider != m_nPrefsAudio3DProviderIndex) { + SetHelperText(5); } SaveSettings(); } @@ -4657,7 +4555,7 @@ CMenuManager::ProcessButtonPresses(void) } case MENUACTION_SPEAKERCONF: #ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { if (--m_PrefsSpeakers < 0) m_PrefsSpeakers = 2; DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -4669,46 +4567,44 @@ CMenuManager::ProcessButtonPresses(void) break; case MENUACTION_PLAYERSETUP: CPlayerSkin::BeginFrontendSkinEdit(); - ChangeScreen(MENUPAGE_SKIN_SELECT, 0, true, true); + SwitchToNewScreen(MENUPAGE_SKIN_SELECT); m_nCurrExLayer = HOVEROPTION_LIST; m_bSkinsEnumerated = false; break; case MENUACTION_RESTOREDEF: if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - m_PrefsSfxVolume = 102; + 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; - m_PrefsMusicVolume = 102; - m_PrefsStereoMono = 0; - m_PrefsRadioStation = HEAD_RADIO; - DMAudio.SetMusicMasterVolume(102); + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); // TODO(Miami) + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); SaveSettings(); } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_PrefsFrameLimiter = true; m_PrefsBrightness = 256; - m_PrefsVsyncDisp = true; m_PrefsLOD = 1.2f; +#ifdef LEGACY_MENU_OPTIONS m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; +#endif + CRenderer::ms_lodDistScale = m_PrefsLOD; + m_PrefsShowSubtitles = false; m_PrefsUseWideScreen = false; - m_PrefsShowSubtitles = true; + m_PrefsShowLegends = true; + m_PrefsVsyncDisp = true; + m_PrefsFrameLimiter = true; + m_PrefsRadarMode = 0; + m_PrefsShowHud = true; m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } - else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } -#else - CMBlur::BlurOn = true; -#endif + CMBlur::BlurOn = false; SaveSettings(); - } else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) { + } else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) { ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); @@ -4726,11 +4622,12 @@ CMenuManager::ProcessButtonPresses(void) ControlsManager.InitDefaultControlConfigJoyPad(count); } #endif - m_ControlMethod = CONTROL_STANDARD; - MousePointerStateHelper.bInvertVertically = false; + MousePointerStateHelper.bInvertVertically = true; + TheCamera.m_bHeadBob = false; TheCamera.m_fMouseAccelHorzntl = 0.0025f; CVehicle::m_bDisableMouseSteering = true; - TheCamera.m_bHeadBob = false; + m_ControlMethod = CONTROL_STANDARD; + TheCamera.m_bUseMouse3rdPerson = true; SaveSettings(); } SetHelperText(2); @@ -4750,22 +4647,20 @@ CMenuManager::ProcessButtonPresses(void) #endif break; case MENUACTION_LOADRADIO: - ChangeScreen(MENUPAGE_SOUND_SETTINGS, 0, true, true); + SwitchToNewScreen(MENUPAGE_SOUND_SETTINGS); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("STARTED PLAYING FRONTEND AUDIO TRACK"); break; -#ifdef MISSION_REPLAY - case MENUACTION_REJECT_RETRY: - doingMissionRetry = false; - AllowMissionReplay = 0; - RequestFrontEndShutDown(); + case MENUACTION_SAVEGAME: + { + int saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot; + + if (saveSlot >= 2 && saveSlot <= 9) { + m_nCurrSaveSlot = m_nCurrOption; + SwitchToNewScreen(MENUPAGE_SAVE_OVERWRITE_CONFIRM); + } break; - case MENUACTION_UNK114: - doingMissionRetry = false; - RequestFrontEndShutDown(); - RetryMission(2, 0); - return; -#endif + } #ifdef CUSTOM_FRONTEND_OPTIONS case MENUACTION_TRIGGERFUNC: FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; @@ -4806,10 +4701,12 @@ CMenuManager::ProcessButtonPresses(void) #else if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) { #endif - if (!m_bGameNotLoaded && !m_bMenuStateChanged) { + if (!m_bGameNotLoaded) { +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) { m_PrefsVsync = m_PrefsVsyncDisp; } +#endif RequestFrontEndShutDown(); } @@ -4825,7 +4722,7 @@ CMenuManager::ProcessButtonPresses(void) #endif RequestFrontEndShutDown(); } - // It's now in ThingsToDoBeforeGoingBack() + // It's now in ThingsToDoBeforeLeavingPage() #ifndef TIDY_UP_PBP else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { DMAudio.StopFrontEndTrack(); @@ -4833,11 +4730,13 @@ CMenuManager::ProcessButtonPresses(void) } #endif - int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; - int oldOption = GetPreviousPageOption(); + int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; if (oldScreen != -1) { - ThingsToDoBeforeGoingBack(); + ThingsToDoBeforeLeavingPage(); + if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { + m_nTotalListRow = 0; + } #ifdef PS2_LIKE_MENU if (!bottomBarActive && @@ -4846,7 +4745,7 @@ CMenuManager::ProcessButtonPresses(void) } else #endif { - ChangeScreen(oldScreen, oldOption, true, true); + SwitchToNewScreen(-2); } // We will go back for sure at this point, why process other things?! @@ -4869,13 +4768,13 @@ CMenuManager::ProcessButtonPresses(void) bool increase = false; #endif if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetPedWalkLeftRight() < 0 || CPad::GetPad(0)->GetDPadLeft()) { - static uint32 lastSliderDecrease = 0; + static PauseModeTime 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; + static PauseModeTime lastSliderIncrease = 0; if (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) { CheckSliderMovement(1); lastSliderIncrease = CTimer::GetTimeInMillisecondsPauseMode(); @@ -4915,15 +4814,15 @@ CMenuManager::ProcessButtonPresses(void) m_PrefsRadioStation += changeValueBy; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); if (DMAudio.IsMP3RadioChannelAvailable()) { - if (m_PrefsRadioStation < HEAD_RADIO) + if (m_PrefsRadioStation < WILDSTYLE) m_PrefsRadioStation = USERTRACK; if (m_PrefsRadioStation > USERTRACK) - m_PrefsRadioStation = HEAD_RADIO; + m_PrefsRadioStation = WILDSTYLE; } else { - if (m_PrefsRadioStation < HEAD_RADIO) - m_PrefsRadioStation = CHATTERBOX; - if (m_PrefsRadioStation > CHATTERBOX) - m_PrefsRadioStation = HEAD_RADIO; + if (m_PrefsRadioStation < WILDSTYLE) + m_PrefsRadioStation = WAVE; + if (m_PrefsRadioStation > WAVE) + m_PrefsRadioStation = WILDSTYLE; } SaveSettings(); DMAudio.SetRadioInCar(m_PrefsRadioStation); @@ -4948,7 +4847,7 @@ CMenuManager::ProcessButtonPresses(void) case MENUACTION_SCREENRES: if (m_bGameNotLoaded) { RwChar** videoMods = _psGetVideoModeList(); - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); if (changeValueBy > 0) { do { ++m_nDisplayVideoMode; @@ -4966,15 +4865,21 @@ CMenuManager::ProcessButtonPresses(void) } } break; +#ifdef IMPROVED_VIDEOMODE + case MENUACTION_SCREENMODE: + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); + m_nSelectedScreenMode = !m_nSelectedScreenMode; + break; +#endif case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex += changeValueBy; m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); break; case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != -1) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { m_PrefsSpeakers -= changeValueBy; m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -5026,7 +4931,7 @@ CMenuManager::ProcessButtonPresses(void) } else { m_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN; } - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); } } } @@ -5035,13 +4940,9 @@ void CMenuManager::ProcessOnOffMenuOptions() { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { +#ifdef LEGACY_MENU_OPTIONS 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); break; case MENUACTION_CTRLCONFIG: @@ -5050,10 +4951,7 @@ CMenuManager::ProcessOnOffMenuOptions() CPad::GetPad(0)->Mode = 0; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); break; - case MENUACTION_CTRLDISPLAY: - m_DisplayControllerOnFoot = !m_DisplayControllerOnFoot; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - break; +#endif case MENUACTION_FRAMESYNC: m_PrefsVsyncDisp = !m_PrefsVsyncDisp; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); @@ -5093,23 +4991,10 @@ CMenuManager::ProcessOnOffMenuOptions() 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; case MENUACTION_SHOWHEADBOB: TheCamera.m_bHeadBob = !TheCamera.m_bHeadBob; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); @@ -5138,7 +5023,6 @@ void CMenuManager::RequestFrontEndShutDown() { m_bShutDownFrontEndRequested = true; - DMAudio.ChangeMusicMode(MUSICMODE_GAME); } void @@ -5155,45 +5039,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() -{ - m_bMenuActive = false; - CTimer::EndUserPause(); -} - float CMenuManager::StretchX(float x) { @@ -5214,80 +5065,171 @@ float CMenuManager::StretchY(float y) } void -CMenuManager::SwitchMenuOnAndOff() +CMenuManager::ProcessFileActions() { - bool menuWasActive = GetIsMenuActive(); - - // Reminder: You need REGISTER_START_BUTTON defined to make it work. - if (CPad::GetPad(0)->GetStartJustDown() -#ifdef FIX_BUGS - && !m_bGameNotLoaded + switch (m_nCurrScreen) { + case MENUPAGE_LOADING_IN_PROGRESS: + if (CheckSlotDataValid(m_nCurrSaveSlot)) { +#ifdef USE_DEBUG_SCRIPT_LOADER + scriptToLoad = 0; #endif - || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { + if (!m_bGameNotLoaded) + MessageScreen("FELD_WR", true); - m_bMenuActive = !m_bMenuActive; + DoSettingsBeforeStartingAGame(); + m_bWantToLoad = true; + } else + SwitchToNewScreen(MENUPAGE_NEW_GAME); - if (m_bShutDownFrontEndRequested) - m_bMenuActive = false; - if (m_bStartUpFrontEndRequested) - m_bMenuActive = true; + 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: + { + 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; + + break; + } + } +} + +// --MIAMI: Done +void +CMenuManager::SwitchMenuOnAndOff() +{ + if (!TheCamera.m_WideScreenOn) { + + // 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) { + + if (m_nCurrScreen != MENUPAGE_LOADING_IN_PROGRESS) { + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DoRWStuffEndOfFrame(); + } + + if (m_bShutDownFrontEndRequested) + m_bMenuActive = false; + else if (m_bStartUpFrontEndRequested) + m_bMenuActive = true; + else + m_bMenuActive = !m_bMenuActive; + + if (m_bMenuActive) { + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + Initialise(); + LoadAllTextures(); + } else { + 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); + } - if (m_bMenuActive) { - CTimer::StartUserPause(); - } else { #ifdef PS2_LIKE_MENU - bottomBarActive = false; -#endif -#ifdef FIX_BUGS - ThingsToDoBeforeGoingBack(); + bottomBarActive = false; #endif - ShutdownJustMenu(); - SaveSettings(); - m_bStartUpFrontEndRequested = false; - pControlEdit = nil; - m_bShutDownFrontEndRequested = false; - DisplayComboButtonErrMsg = false; + + m_StatsScrollSpeed = 150.0f; + SaveSettings(); + 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; + 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; + 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_OnlySaveMenu = true; + + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } + + Initialise(); + LoadAllTextures(); + + // TODO(Miami): Cheat warning 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; + m_nCurrOption = 8; } -*/ - if (m_bMenuActive != menuWasActive) - m_bMenuStateChanged = true; m_bStartUpFrontEndRequested = false; m_bShutDownFrontEndRequested = false; @@ -5296,27 +5238,31 @@ CMenuManager::SwitchMenuOnAndOff() 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); - 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(); -#endif - int menu = CTxdStore::FindTxdSlot("menu"); - CTxdStore::RemoveTxd(menu); + if (!m_OnlySaveMenu) { + int frontend2 = CTxdStore::FindTxdSlot("frontend2"); + for (int i = 3; i < NUM_MENU_SPRITES; ++i) + m_aFrontEndSprites[i].Delete(); + + CTxdStore::RemoveTxd(frontend2); + } - m_bSpritesLoaded = false; + m_bSpritesLoaded = false; + } + m_OnlySaveMenu = false; + // TODO(Miami): Place name thing } void @@ -5339,7 +5285,7 @@ CMenuManager::WaitForUserCD() HandleExit(); CPad::UpdatePads(); - MessageScreen("NO_PCCD"); + MessageScreen("NO_PCCD", true); if (CPad::GetPad(0)->GetEscapeJustDown()) { m_bQuitGameNoCD = true; @@ -5348,328 +5294,143 @@ CMenuManager::WaitForUserCD() } void -CMenuManager::PrintController(void) +CMenuManager::DrawQuitGameScreen(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) { - 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")); - 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")); - 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")); - 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")); - 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")); - 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")); - 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")); - 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")); - break; - default: - return; - } + static int32 exitSignalTimer = 0; +#ifndef MUCH_SHORTER_OUTRO_SCREEN + static PauseModeTime lastTickIncrease = 0; + if (m_nMenuFadeAlpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) { + exitSignalTimer++; + lastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode(); } +#else + static PauseModeTime sincePress = 0; + sincePress += frameTime; + if (sincePress > 500) + exitSignalTimer = 150; +#endif + static CSprite2d *splash = nil; + + if (splash == nil) + splash = LoadSplash("OUTRO"); + + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(28.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, -(m_nMenuFadeAlpha + 1))); + + // 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, m_nMenuFadeAlpha)); + CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, m_nMenuFadeAlpha)); +#endif + + splash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); + if (m_nMenuFadeAlpha == 255 && exitSignalTimer == 150) + RsEventHandler(rsQUITAPP, nil); - CFont::SetDropShadowPosition(0); // X + m_bShowMouse = false; + m_AllowNavigation = false; } -#ifdef MENU_MAP +#ifdef CUSTOM_MAP #define ZOOM(x, y, in) \ do { \ - if(fMapSize > SCREEN_HEIGHT * 3.0f && in) \ + if(m_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); \ + m_fMapCenterX += (x - m_fMapCenterX) * (1.0f - z2); \ + m_fMapCenterY += (y - m_fMapCenterY) * (1.0f - z2); \ \ - if (fMapSize < SCREEN_HEIGHT / 2 && !in) \ + if (m_fMapSize < SCREEN_HEIGHT / 2 && !in) \ break; \ \ - fMapSize *= z2; \ - } while(0) \ + m_fMapSize *= z2; \ + } while(0) + +#endif void CMenuManager::PrintMap(void) { - CFont::SetJustifyOn(); - bMenuMapActive = true; + m_bMenuMapActive = true; CRadar::InitFrontEndMap(); +#ifdef CUSTOM_MAP // Just entered to map if (!bMapLoaded) { - fMapSize = SCREEN_HEIGHT * 2.0f; - fMapCenterX = 0.0f; - fMapCenterY = 0.0f; + m_fMapSize = SCREEN_HEIGHT * 2.0f; + m_fMapCenterX = 0.0f; + m_fMapCenterY = 0.0f; 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; + m_fMapCenterX = (-screenSpacePlayer.x) + SCREEN_WIDTH / 2; + m_fMapCenterY = (-screenSpacePlayer.y) + SCREEN_HEIGHT / 2; bMapMouseShownOnce = false; bMapLoaded = true; // Let's wait for a frame to not toggle the waypoint if (CPad::GetPad(0)->NewState.Cross) { - bMenuMapActive = false; + m_bMenuMapActive = false; return; } } +#endif - // 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))); + // Because m_fMapSize is half of the map length, and map consists of 3x3 tiles. + float halfTile = m_fMapSize / 3.0f; 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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 >= 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))); + 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(); +#ifdef CUSTOM_MAP CVector2D mapPoint; mapPoint.x = m_nMousePosX; mapPoint.y = m_nMousePosY; @@ -5689,34 +5450,35 @@ CMenuManager::PrintMap(void) CRGBA(0, 0, 0, 150)); if (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { - if (mapPoint.y > fMapCenterY - fMapSize && mapPoint.y < fMapCenterY + fMapSize && - mapPoint.x > fMapCenterX - fMapSize && mapPoint.x < fMapCenterX + fMapSize) { + if (mapPoint.y > m_fMapCenterY - m_fMapSize && mapPoint.y < m_fMapCenterY + m_fMapSize && + mapPoint.x > m_fMapCenterX - m_fMapSize && mapPoint.x < m_fMapCenterX + m_fMapSize) { - float diffX = fMapCenterX - fMapSize, diffY = fMapCenterY - fMapSize; - float x = ((mapPoint.x - diffX) / (fMapSize * 2)) * 4000.0f - 2000.0f; - float y = 2000.0f - ((mapPoint.y - diffY) / (fMapSize * 2)) * 4000.0f; + // 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 = ((mapPoint.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) - ((mapPoint.y - diffY) / (m_fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE); 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; + m_fMapCenterX += m_nMousePosX - m_nMouseOldPosX; + m_fMapCenterY += m_nMousePosY - m_nMouseOldPosY; } else if (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetDPadLeft()) { - fMapCenterX += 15.0f; + m_fMapCenterX += 15.0f; } else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetDPadRight()) { - fMapCenterX -= 15.0f; + m_fMapCenterX -= 15.0f; } else if (CPad::GetPad(0)->GetLeftStickX()) { - fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; + m_fMapCenterX -= CPad::GetPad(0)->GetLeftStickX() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetDPadUp()) { - fMapCenterY += 15.0f; + m_fMapCenterY += 15.0f; } else if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetDPadDown()) { - fMapCenterY -= 15.0f; + m_fMapCenterY -= 15.0f; } else if (CPad::GetPad(0)->GetLeftStickY()) { - fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; + m_fMapCenterY -= CPad::GetPad(0)->GetLeftStickY() / 128.0f * 20.0f; } if (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) { @@ -5731,66 +5493,26 @@ CMenuManager::PrintMap(void) ZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true); } - if (fMapCenterX - fMapSize > SCREEN_WIDTH / 2) - fMapCenterX = fMapSize + SCREEN_WIDTH / 2; + if (m_fMapCenterX - m_fMapSize > SCREEN_WIDTH / 2) + m_fMapCenterX = m_fMapSize + SCREEN_WIDTH / 2; - if (fMapCenterX + fMapSize < SCREEN_WIDTH / 2) - fMapCenterX = SCREEN_WIDTH / 2 - fMapSize; + if (m_fMapCenterX + m_fMapSize < SCREEN_WIDTH / 2) + m_fMapCenterX = SCREEN_WIDTH / 2 - m_fMapSize; - if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) - fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; + if (m_fMapCenterY + m_fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) + m_fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - m_fMapSize; - fMapCenterY = Min(fMapCenterY, fMapSize); // To not show beyond north border - - bMenuMapActive = false; - - // CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); // From VC - // CFont::SetRightJustifyWrap(10.0f); - - 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(0, 0, 0, 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); + if (m_fMapCenterY - m_fMapSize > SCREEN_HEIGHT / 2) + m_fMapCenterY = SCREEN_HEIGHT / 2 + m_fMapSize; #endif + m_bMenuMapActive = false; - 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("FEC_TAR")); -#undef TEXT_PIECE + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(10.0f)); + DisplayHelperText("FEH_MPH"); } +#ifdef CUSTOM_MAP #undef ZOOM #endif @@ -5810,9 +5532,7 @@ CMenuManager::ConstructStatLine(int rowIdx) STAT_LINE("PL_STAT", nil, false, nil); - int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : - CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1)); - percentCompleted = Min(percentCompleted, 100); + int percentCompleted = CStats::GetPercentageProgress(); STAT_LINE("PER_COM", &percentCompleted, false, nil); STAT_LINE("NMISON", &CStats::MissionsGiven, false, nil); @@ -5863,13 +5583,9 @@ CMenuManager::ConstructStatLine(int rowIdx) if (CStats::Record4x4Mayhem > 0) { STAT_LINE("FEST_RM", &CStats::Record4x4Mayhem, false, nil); } - if (CStats::LongestFlightInDodo > 0) { - STAT_LINE("FEST_LF", &CStats::LongestFlightInDodo, false, nil); - } if (CStats::TimeTakenDefuseMission > 0) { STAT_LINE("FEST_BD", &CStats::TimeTakenDefuseMission, false, nil); } - STAT_LINE("CAR_CRU", &CStats::CarsCrushed, false, nil); if (CStats::HighestScores[0] > 0) { STAT_LINE("FEST_BB", nil, false, nil); @@ -5897,7 +5613,6 @@ CMenuManager::ConstructStatLine(int rowIdx) float fTemp; STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); break; @@ -5913,7 +5628,6 @@ CMenuManager::ConstructStatLine(int rowIdx) #endif STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); break; @@ -5986,6 +5700,5 @@ uint8 CMenuManager::GetNumberOfMenuOptions() #undef GetBackJustUp #undef GetBackJustDown -#undef ChangeScreen #endif
\ No newline at end of file diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 7b0e2f4b..83d86d5b 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -10,30 +10,43 @@ #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 +#define MENUHEADER_POS_X 10.0f +#define MENUHEADER_POS_Y 10.0f +#define MENUHEADER_HEIGHT 2.0f #endif -#define MENUHEADER_WIDTH 0.84f +#define MENUHEADER_WIDTH 1.0f + +#define MENU_UNK_X_MARGIN 10.0f +#define MENU_UNK_WIDTH 10.0f -#define MENU_X_MARGIN 40.0f -#define MENUACTION_POS_Y 60.0f -#define MENUACTION_WIDTH 38.0f #define MENUACTION_SCALE_MULT 0.9f -#define MENURADIO_ICON_SCALE 60.0f +#define MENULABEL_X_MARGIN 80.0f +#define MENULABEL_WIDTH 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 MENUSLIDER_X 256.0f -#define MENUSLIDER_UNK 256.0f +#define MENURADIO_ICON_SCALE 60.0f -#define BIGTEXT_X_SCALE 0.75f -#define BIGTEXT_Y_SCALE 0.9f -#define MEDIUMTEXT_X_SCALE 0.55f -#define MEDIUMTEXT_Y_SCALE 0.8f -#define SMALLTEXT_X_SCALE 0.45f -#define SMALLTEXT_Y_SCALE 0.7f -#define SMALLESTTEXT_X_SCALE 0.4f -#define SMALLESTTEXT_Y_SCALE 0.6f +#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 +#define BIGTEXT2_Y_SCALE 1.2f +#define BIGTEXT_X_SCALE 0.6f +#define BIGTEXT_Y_SCALE 1.0f +#define MEDIUMTEXT_X_SCALE 0.48f +#define MEDIUMTEXT_Y_SCALE 1.0f +#define SMALLTEXT_X_SCALE 0.42f +#define SMALLTEXT_Y_SCALE 0.9f +#define SMALLESTTEXT_X_SCALE 0.3f +#define SMALLESTTEXT_Y_SCALE 0.7f #define PLAYERSETUP_LIST_TOP 28.0f #define PLAYERSETUP_LIST_BOTTOM 125.0f @@ -53,20 +66,23 @@ #define PLAYERSETUP_LIST_BODY_TOP 47 #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 @@ -84,62 +100,41 @@ #define CONTSETUP_BACK_BOTTOM 122.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, NUM_MENU_SPRITES }; @@ -158,86 +153,52 @@ enum eSaveSlot SAVESLOT_LABEL = 36 }; -#ifdef MENU_MAP -enum MapSprites -{ - MAPMID1, - MAPMID2, - MAPMID3, - MAPBOT1, - MAPBOT2, - MAPBOT3, - MAPTOP1, - MAPTOP2, - MAPTOP3, - NUM_MAP_SPRITES -}; -#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_GRAPHICS_SETTINGS = 6, - MENUPAGE_LANGUAGE_SETTINGS = 7, + MENUPAGE_STATS = 0, + MENUPAGE_NEW_GAME = 1, + MENUPAGE_BRIEFS = 2, + MENUPAGE_SOUND_SETTINGS = 3, + MENUPAGE_GRAPHICS_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_58 = 58, -#ifdef MENU_MAP - MENUPAGE_MAP = 59, + 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 + MENUPAGE_OUTRO = 34, +#ifdef LEGACY_MENU_OPTIONS + MENUPAGE_CONTROLLER_SETTINGS, + MENUPAGE_DEBUG_MENU, + MENUPAGE_CONTROLLER_PC_OLD1, + MENUPAGE_CONTROLLER_PC_OLD2, + MENUPAGE_CONTROLLER_PC_OLD3, + MENUPAGE_CONTROLLER_PC_OLD4, + MENUPAGE_CONTROLLER_DEBUG, #endif MENUPAGES }; @@ -246,20 +207,19 @@ enum eMenuAction { MENUACTION_NOTHING, MENUACTION_LABEL, + MENUACTION_YES, + MENUACTION_NO, MENUACTION_CHANGEMENU, - MENUACTION_CTRLVIBRATION, - MENUACTION_CTRLCONFIG, - MENUACTION_CTRLDISPLAY, + MENUACTION_UNK5, + MENUACTION_INVERTPADY, MENUACTION_FRAMESYNC, MENUACTION_FRAMELIMIT, MENUACTION_TRAILS, MENUACTION_SUBTITLES, MENUACTION_WIDESCREEN, MENUACTION_BRIGHTNESS, - MENUACTION_DRAWDIST, MENUACTION_MUSICVOLUME, MENUACTION_SFXVOLUME, - MENUACTION_UNK15, MENUACTION_RADIO, MENUACTION_LANG_ENG, MENUACTION_LANG_FRE, @@ -268,74 +228,32 @@ 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, + + // Below this is TODO(Miami) + MENUACTION_DRAWDIST, 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_LEGENDS, + MENUACTION_RADARMODE, + MENUACTION_HUD, + MENUACTION_GOBACK, + MENUACTION_KEYBOARDCTRLS, MENUACTION_PARSEHEAP, - MENUACTION_SHOWCULL, - MENUACTION_MEMCARDSAVECONFIRM, - MENUACTION_RESUME_FROM_SAVEZONE, - MENUACTION_UNK50, + // MENUACTION_MEMCARDSAVECONFIRM is that on VC enum?? 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_KEYBOARDCTRLS, - MENUACTION_UNK73, - MENUACTION_INITMP, - MENUACTION_MP_PLAYERCOLOR, - MENUACTION_MP_PLAYERNAME, - MENUACTION_MP_GAMENAME, MENUACTION_GETKEY, MENUACTION_SHOWHEADBOB, MENUACTION_UNK80, 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_MP3VOLUMEBOOST, MENUACTION_RESUME, MENUACTION_DONTCANCEL, MENUACTION_SCREENRES, @@ -345,22 +263,14 @@ 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_REJECT_RETRY, - MENUACTION_UNK114, -#ifdef CUSTOM_FRONTEND_OPTIONS - MENUACTION_TRIGGERFUNC +#ifdef IMPROVED_VIDEOMODE + MENUACTION_SCREENMODE, +#endif +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_CTRLVIBRATION, + MENUACTION_CTRLCONFIG, #endif }; @@ -413,7 +323,11 @@ enum eCheckHover enum { - NUM_MENUROWS = 18, +#ifdef LEGACY_MENU_OPTIONS + NUM_MENUROWS = 14, +#else + NUM_MENUROWS = 12, +#endif }; enum eControlMethod @@ -447,82 +361,210 @@ struct BottomBarOption struct CMenuScreen { char m_ScreenName[8]; - int32 unk; // 2 on MENUPAGE_MULTIPLAYER_START, 1 on everywhere else - int32 m_PreviousPage[2]; // eMenuScreen - int32 m_ParentEntry[2]; // row + int32 m_PreviousPage; // eMenuScreen + int32 m_ParentEntry; // row struct CMenuEntry { int32 m_Action; // eMenuAction char m_EntryName[8]; int32 m_SaveSlot; // eSaveSlot - int32 m_TargetMenu; // eMenuScreen // FrontendOption ID if it's a custom option + int32 m_TargetMenu; // eMenuScreen + uint16 m_X; + uint16 m_Y; + uint8 m_Align; } m_aEntries[NUM_MENUROWS]; }; +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; + uint8 field_10; + 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; // TODO(Miami): Are we sure? + 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; + uint8 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; + uint8 m_PrefsMP3BoostVolume; + uint8 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_menuTransitionProgress; + 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 field_F0; + int32 m_LastRadioScrollDir; + 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; @@ -546,42 +588,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 @@ -591,70 +599,59 @@ public: static bool m_PrefsDisableTutorials; #endif // !MASTER -#ifdef MENU_MAP - static bool bMenuMapActive; - static bool bMapMouseShownOnce; - static bool bMapLoaded; - static float fMapSize; - static float fMapCenterY; - static float fMapCenterX; - static CSprite2d m_aMapSprites[NUM_MAP_SPRITES]; + CMenuManager(void); + ~CMenuManager(void) { UnloadTextures(); } + + void Initialise(); void PrintMap(); -#endif - -public: + void SetFrontEndRenderStates(); static void BuildStatLine(Const char *text, void *stat, bool itsFloat, void *stat2); 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 DrawBackground(bool transitionCall); void DrawPlayerSetupScreen(); int FadeIn(int alpha); - void FilterOutColorMarkersFromString(wchar*, CRGBA &); + void FilterOutColorMarkersFromString(wchar*); 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 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); - // 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); @@ -665,7 +662,7 @@ public: }; #ifndef IMPROVED_VIDEOMODE -VALIDATE_SIZE(CMenuManager, 0x564); +VALIDATE_SIZE(CMenuManager, 0x688); #endif extern CMenuManager FrontEndMenuManager; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 82e6992d..7700d321 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -65,6 +65,7 @@ #include "Script.h" #include "Shadows.h" #include "Skidmarks.h" +#include "SetPieces.h" #include "SpecialFX.h" #include "Sprite2d.h" #include "Stats.h" @@ -85,10 +86,12 @@ #include "World.h" #include "ZoneCull.h" #include "Zones.h" +#include "Occlusion.h" #include "debugmenu.h" -#include "frontendoption.h" +#include "Ropes.h" eLevelName CGame::currLevel; +int32 CGame::currArea; bool CGame::bDemoMode = true; bool CGame::nastyGame = true; bool CGame::frenchGame; @@ -259,33 +262,30 @@ void CGame::ShutdownRenderWare(void) bool CGame::InitialiseOnceAfterRW(void) { TheText.Load(); - DMAudio.Initialise(); CTimer::Initialise(); CTempColModels::Initialise(); mod_HandlingManager.Initialise(); CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); CPedStats::Initialise(); CTimeCycle::Initialise(); - + DMAudio.Initialise(); if ( DMAudio.GetNum3DProvidersAvailable() == 0 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1; + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = NO_AUDIO_PROVIDER; - if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) + if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == AUDIO_PROVIDER_NOT_DETERMINED || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) { - CMenuManager::m_PrefsSpeakers = 0; - int8 provider = DMAudio.AutoDetect3DProviders(); - if ( provider != -1 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = provider; + 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); - CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile); + CWorld::Players[0].SetPlayerSkin(FrontEndMenuManager.m_PrefsSkinFile); #ifdef CUSTOM_FRONTEND_OPTIONS CustomFrontendOptionsPopulate(); @@ -307,7 +307,7 @@ bool CGame::Initialise(const char* datFile) strcpy(aDatFile, datFile); CPools::Initialise(); CIniFile::LoadIniFile(); - currLevel = LEVEL_INDUSTRIAL; + currLevel = LEVEL_BEACH; LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen()); gameTxdSlot = CTxdStore::AddTxdSlot("generic"); CTxdStore::Create(gameTxdSlot); @@ -327,10 +327,9 @@ bool CGame::Initialise(const char* datFile) ThePaths.AllocatePathFindInfoMem(4500); CWeather::Init(); CCullZones::Init(); + COcclusion::Init(); CCollision::Init(); -#ifdef PS2_MENU - TheText.Load(); -#endif + CSetPieces::Init(); CTheZones::Init(); CUserDisplay::Init(); CMessages::Init(); @@ -365,12 +364,11 @@ bool CGame::Initialise(const char* datFile) CWorld::Players[0].LoadPlayerSkin(); TestModelIndices(); LoadingScreen("Loading the Game", "Setup water", nil); - CWaterLevel::Initialise("DATA\\WATER.DAT"); + WaterLevelInitialise("DATA\\WATER.DAT"); TheConsole.Init(); 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); @@ -378,6 +376,7 @@ bool CGame::Initialise(const char* datFile) printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen()); CAnimManager::LoadAnimFiles(); + CStreaming::LoadInitialWeapons(); CPed::Initialise(); CRouteNode::Initialise(); CEventList::Initialise(); @@ -415,13 +414,12 @@ bool CGame::Initialise(const char* datFile) CRubbish::Init(); CClouds::Init(); CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CBridge::Init(); CGarages::Init(); LoadingScreen("Loading the Game", "Position dynamic objects", nil); - CWorld::RepositionCertainDynamicObjects(); LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); - CCullZones::ResolveVisibilities(); CTrain::InitTrains(); CPlane::InitPlanes(); CCredits::Init(); @@ -431,6 +429,7 @@ bool CGame::Initialise(const char* datFile) if ( !TheMemoryCard.m_bWantToLoad ) { #endif + LoadingScreen("Loading the Game", "Start script", nil); CTheScripts::StartTestScript(); CTheScripts::Process(); TheCamera.Process(); @@ -438,10 +437,12 @@ bool CGame::Initialise(const char* datFile) } #endif 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); + // TODO(Miami) + // DMAudio.SetStartingTrackPositions(1); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); return true; } @@ -562,9 +563,9 @@ void CGame::ReInitGameObjectVariables(void) CRemote::Init(); #endif CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CParticle::ReloadConfig(); - CCullZones::ResolveVisibilities(); #ifdef PS2_MENU if ( !TheMemoryCard.m_bWantToLoad ) @@ -586,24 +587,7 @@ 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) @@ -619,6 +603,7 @@ void CGame::ShutDownForRestart(void) CTheScripts::UndoBuildingSwaps(); CTheScripts::UndoEntityInvisibilitySettings(); CWorld::ClearForRestart(); + CGameLogic::ClearShortCut(); CTimer::Shutdown(); CStreaming::FlushRequestList(); CStreaming::DeleteAllRwObjects(); @@ -626,11 +611,11 @@ void CGame::ShutDownForRestart(void) CStreaming::ms_disableStreaming = false; CRadar::RemoveRadarSections(); FrontEndMenuManager.UnloadTextures(); - CParticleObject::RemoveAllParticleObjects(); -#ifndef PS2 + CParticleObject::RemoveAllExpireableParticleObjects(); + //CWaterCreatures::RemoveAll(); //TODO VC + CSetPieces::Init(); CPedType::Shutdown(); CSpecialFX::Shutdown(); -#endif TidyUpMemory(true, false); } @@ -642,101 +627,25 @@ 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"); + 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 ) { 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); - 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(?); - CFont::SetBackgroundOff(); - CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f - CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f)); - CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 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(); - CFont::PrintString(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(130.0f), TheText.Get("MC_LDFL")); // Load Failed! - CFont::PrintString(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(170.0f), TheText.Get("FES_NOC")); // No Memory Card (PS2) in MEMORY CARD slot 1. - CFont::PrintString(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(240.0f), TheText.Get("MC_NWRE")); // Now Restarting Game. - 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 ) { if ( GenericLoad() == true ) @@ -750,7 +659,7 @@ 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. } ShutDownForRestart(); @@ -758,11 +667,10 @@ void CGame::InitialiseWhenRestarting(void) CTimer::Initialise(); FrontEndMenuManager.m_bWantToLoad = false; ReInitGameObjectVariables(); - currLevel = LEVEL_INDUSTRIAL; + currLevel = LEVEL_GENERIC; CCollision::SortOutCollisionAfterLoad(); } } -#endif CTimer::Update(); @@ -806,6 +714,7 @@ void CGame::Process(void) CAntennas::Update(); CGlass::Update(); CSceneEdit::Update(); + CSetPieces::Update(); CEventList::Update(); CParticle::Update(); gFireManager.Update(); @@ -827,6 +736,7 @@ void CGame::Process(void) CGarages::Update(); CRubbish::Update(); CSpecialFX::Update(); + CRopes::Update(); CTimeCycle::Update(); if (CReplay::ShouldStandardCameraBeProcessed()) TheCamera.Process(); @@ -846,9 +756,30 @@ void CGame::Process(void) CCarCtrl::RemoveDistantCars(); } } -#ifdef PS2 - CMemCheck::DoTest(); -#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; } void CGame::DrasticTidyUpMemory(bool) diff --git a/src/core/Game.h b/src/core/Game.h index 46e8fc68..67d83c00 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -3,15 +3,37 @@ 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 +}; + +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; @@ -36,9 +58,17 @@ public: 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 dde43c0f..7ab444a4 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -134,6 +134,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; } @@ -145,4 +157,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/MenuScreens.cpp b/src/core/MenuScreens.cpp index 4685918e..6fbf597b 100644 --- a/src/core/MenuScreens.cpp +++ b/src/core/MenuScreens.cpp @@ -5,447 +5,343 @@ // If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp. CMenuScreen aScreens[] = { - // 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_STATS = 0 + { "FEH_STA", MENUPAGE_NONE, 3, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT, }, - // 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_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_BRIEFS = 3 - { "FET_BRE", 1, MENUPAGE_NONE, MENUPAGE_NONE, 6, 3, - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, + // MENUPAGE_BRIEFS = 2 + { "FEH_BRI", MENUPAGE_NONE, 4, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT, }, - // 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_GRAPHICS_SETTINGS = 6 - { "FET_DIS", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 2, 2, - MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, - MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_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, + // 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_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_GRAPHICS_SETTINGS = 4 +#ifdef LEGACY_MENU_OPTIONS + #define Y_OFFSET 50 +#else + #define Y_OFFSET 0 +#endif - // 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, + { "FEH_DIS", MENUPAGE_OPTIONS, 2, + MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 78, MENUALIGN_LEFT, + MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 103, MENUALIGN_LEFT, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 128, MENUALIGN_LEFT, +#endif + MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 128 + Y_OFFSET/2, MENUALIGN_LEFT, +#ifdef LEGACY_MENU_OPTIONS + MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 178, MENUALIGN_LEFT, +#endif + MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 153 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 178 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_LEGENDS, "MAP_LEG", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 202 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_RADARMODE, "FED_RDR", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 228 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_HUD, "FED_HUD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 253 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 278 + Y_OFFSET, MENUALIGN_LEFT, +#ifdef IMPROVED_VIDEOMODE + MENUACTION_SCREENMODE, "FED_POS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 40, 303 + Y_OFFSET, MENUALIGN_LEFT, + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 320, 328 + Y_OFFSET, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 320, 353 + Y_OFFSET, MENUALIGN_CENTER, +#else + MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS, 320, 303 + Y_OFFSET, MENUALIGN_CENTER, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 320, 328 + Y_OFFSET, MENUALIGN_CENTER, +#endif }, - // 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, - }, +#undef Y_OFFSET - // 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_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_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, + // MENUPAGE_MAP = 6 + { "FEH_MAP", MENUPAGE_NONE, 2, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 70, 380, MENUALIGN_CENTER, }, - // MENUPAGE_NO_MEMORY_CARD = 13 - { "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - // hud adjustment page in mobile + // 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_LOADING_IN_PROGRESS = 14 - { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM, + // 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_DELETING_IN_PROGRESS = 15 - { "FET_DG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE, + // 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_PS2_LOAD_FAILED = 16 - { "FET_LG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - MENUACTION_LABEL, "FES_LOE", 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_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_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_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_LOADING_IN_PROGRESS = 12 + { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, 0, }, - // 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_DELETING_IN_PROGRESS = 13 + { "FES_DEL", MENUPAGE_CHOOSE_DELETE_SLOT, 0, }, - // MENUPAGE_MEMORY_CARD_TEST = 20 - { "FEM_MC2", 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_MULTIPLAYER_MAIN = 21 - { "FET_MP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - + // 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, - }, -#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_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, }, -#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_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, }, - // 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_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_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_SKIN_SELECT = 21 + { "FET_PS", MENUPAGE_OPTIONS, 4, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_MAP = 28 - { "FET_MAP", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, - + // 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_CONNECTION = 29 - { "FET_CON", 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_MULTIPLAYER_FIND_GAME = 30 - { "FET_FG", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 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_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_MULTIPLAYER_MODE = 31 - { "FET_GT", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_CONTROLLER_PC = 26 + { "FET_CTL", MENUPAGE_OPTIONS, 0, + 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, + 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_GRAPHICS_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_CREATE = 32 - { "FET_HG", 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, + }, + + // TODO(Miami) + // MENUPAGE_KEYBOARD_CONTROLS = 30 + { "FET_STI", MENUPAGE_CONTROLLER_PC, 1, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 0, 0, 0, }, - // MENUPAGE_MULTIPLAYER_START = 33 - { "FEN_STA", 2, 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_SKIN_SELECT_OLD = 34 - { "FET_PS", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, + // MENUPAGE_NONE = 33 + { "", 0, 0, }, - }, + // MENUPAGE_OUTRO = 34 + { "", 0, 0, }, - // MENUPAGE_CONTROLLER_PC = 35 - { "FET_CTL", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, - MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, - 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, +#ifdef LEGACY_MENU_OPTIONS + // MENUPAGE_CONTROLLER_SETTINGS = 4 + { "FET_CON", MENUPAGE_OPTIONS, 0, + MENUACTION_CTRLCONFIG, "FEC_CCF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, 0, 0, 0, + MENUACTION_CTRLVIBRATION, "FEC_VIB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, }, + // MENUPAGE_DEBUG_MENU = 18 + { "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_PARSEHEAP, "FED_PAH", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_DEBUGSTREAM, "FED_DSR", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + }, + // 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, + { "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 = 37 - { "FET_CTL", 1, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, 1, 1, + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 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_GRAPHICS_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 - - { "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 - }, -#endif + { "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_58 = 58 - { "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0, + // MENUPAGE_CONTROLLER_PC_OLD4 = 39 + { "FET_CTL", MENUPAGE_CONTROLLER_PC, 3, - }, + }, -#ifdef MENU_MAP - // MENUPAGE_MAP = 59 - { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2, - MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back - MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, - }, + // MENUPAGE_CONTROLLER_DEBUG = 40 + { "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 }; -#endif
\ No newline at end of file +#endif diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 7df548aa..c1016bdd 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -36,7 +36,11 @@ #include "Streaming.h" #include "PathFind.h" #include "Wanted.h" +#include "WaterLevel.h" #include "General.h" +#include "Fluff.h" +#include "Gangs.h" +#include "platform.h" #ifdef GTA_PS2 #include "eetypes.h" @@ -64,7 +68,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,58 +81,151 @@ bool CPad::IsAffectedByController = false; _TODO("gbFastTime"); extern bool gbFastTime; -void WeaponCheat() +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); +} + +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); + + FindPlayerPed()->GiveWeapon(WEAPONTYPE_KATANA, 0); + 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); +} + +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); + + FindPlayerPed()->GiveWeapon(WEAPONTYPE_CHAINSAW, 0); + 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); } 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() +void VehicleCheat(bool something, int model) { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); - CStreaming::RequestModel(MI_RHINO, 0); - CStreaming::LoadAllRequestedModels(false); - if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) { + CStreaming::RequestModel(model, 0); + CStreaming::LoadAllRequestedModels(something); + 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 (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(MI_RHINO, 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); } } } @@ -155,9 +252,9 @@ void ChangePlayerCheat() do { do - modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1); + modelId = CGeneral::GetRandomNumberInRange(0, MI_WFYG2+1); while (!CModelInfo::GetModelInfo(modelId)); - } while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D); + } while (modelId == MI_TAXI_D); uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags; ped->DeleteRwObject(); @@ -173,6 +270,14 @@ void ChangePlayerCheat() } } +void ChangePlayerModel(const char* name) { + if (!FindPlayerVehicle()) { + FindPlayerPed()->Undress(name); + CStreaming::LoadAllRequestedModels(0); + FindPlayerPed()->Dress(); + } +} + void MayhemCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); @@ -220,19 +325,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->m_nWantedLevel + 2, 6)); + FindPlayerPed()->m_pWanted->CheatWantedLevel(Min(FindPlayerPed()->m_pWanted->m_nWantedLevel + 2, 6)); } void WantedLevelDownCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT5"), true); - FindPlayerPed()->SetWantedLevel(0); + FindPlayerPed()->m_pWanted->CheatWantedLevel(0); } void SunnyWeatherCheat() @@ -247,6 +352,12 @@ void CloudyWeatherCheat() CWeather::ForceWeatherNow(WEATHER_CLOUDY); } +void StormyWeatherCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); + CWeather::ForceWeatherNow(WEATHER_HURRICANE); +} + void RainyWeatherCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT7"), true); @@ -288,6 +399,62 @@ void NastyLimbsCheat() { CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat; } + +void FannyMagnetCheat() +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CPed::bFannyMagnetCheat = !CPed::bFannyMagnetCheat; +} + +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 NoSeaBedCheat(void) +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CWaterLevel::m_bRenderSeaBed = !CWaterLevel::m_bRenderSeaBed; +} + +void RenderWaterLayersCheat(void) +{ + 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; +} + +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); +} + ////////////////////////////////////////////////////////////////////////// #ifdef KANGAROO_CHEAT @@ -344,6 +511,12 @@ void AltDodoCheat(void) } #endif +void FlyingFishCheat(void) +{ + CHud::SetHelpMessage(TheText.Get("CHEAT1"), true); + CVehicle::bCheat8 = !CVehicle::bCheat8; +} + bool CControllerState::CheckForInput(void) { @@ -457,6 +630,11 @@ void CPad::Clear(bool bResetPlayerControls) AverageEntries = 0; } +uint32 CPad::InputHowLongAgo() +{ + return CTimer::GetTimeInMilliseconds() - LastTimeTouched; +} + void CPad::ClearMouseHistory() { PCTempMouseControllerState.Clear(); @@ -495,7 +673,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 +727,7 @@ void CPad::UpdateMouse() if ( IsForegroundApp() ) { if ( PSGLOBAL(mouse) == nil ) - _InputInitialiseMouse(); + _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); DIMOUSESTATE2 state; @@ -693,7 +871,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 +893,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 +920,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 +954,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 +994,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(true, MI_RHINO); // "CCCSSSSS1TCT" - CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE else if ( !_CHEATCMP("TCT1SSSSSCCC") ) @@ -869,111 +1047,302 @@ void CPad::AddToCheatString(char c) } #endif +int Cheat_strncmp(char* sourceStr, char* origCheatStr) +{ + char cheatCodeVals[] = { 3,5,7,1,13,27,3,7,1,11,13,8,7,32,13,6,28,19,10,3,3,5,7,1,13,27,3,7 }; + + for (uint32 i = 0; i < strlen(origCheatStr); i++) { + if ((sourceStr[i] != origCheatStr[i] - cheatCodeVals[i]) || i >= ARRAY_SIZE(cheatCodeVals)) { + return 1; + } + } + return 0; +} + 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(); +#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1) - // "IFIWEREARICHMAN" - if ( !_CHEATCMP("NAMHCIRAEREWIFI") ) - MoneyCheat(); - - // "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(); + } + // "APLEASANTDAY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKU[\\VHFW]I")) { + KeyBoardCheatString[0] = ' '; + CloudyWeatherCheat(); + } + // "ALOVELYDAY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\FKZY`YVML")) { + KeyBoardCheatString[0] = ' '; + SunnyWeatherCheat(); + } + // "ABITDRIEG" - // "GIVEUSATANK" - if ( !_CHEATCMP("KNATASUEVIG") ) - TankCheat(); + // "CATSANDDOGS" + else if (!Cheat_strncmp(KeyBoardCheatString, "VLVEQiDZULP")) { + KeyBoardCheatString[0] = ' '; + StormyWeatherCheat(); + } + // "CANTSEEATHING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIa\\HLT_[IJ")) { + KeyBoardCheatString[0] = ' '; + FoggyWeatherCheat(); + } + // "PANZER" + else if (!Cheat_strncmp(KeyBoardCheatString, "UJaONk")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_RHINO); + } + // "LIFEISPASSINGMEBY" - // "BANGBANGBANG" - if ( !_CHEATCMP("GNABGNABGNAB") ) + // "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(); - -#ifndef GTA3_1_1_PATCH - // "TURTOISE" - if ( !_CHEATCMP("ESIOTRUT") ) - ArmourCheat(); -#else - // "TORTOISE" - if ( !_CHEATCMP("ESIOTROT") ) - ArmourCheat(); -#endif - - // "SKINCANCERFORME" - if ( !_CHEATCMP("EMROFRECNACNIKS") ) - SunnyWeatherCheat(); - - // "ILIKESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEKILI") ) - CloudyWeatherCheat(); - + } + // "WHEELSAREALLINEED" + else if (!Cheat_strncmp(KeyBoardCheatString, "GJLOVgOHF]N[SeRNs")) { + KeyBoardCheatString[0] = ' '; + OnlyRenderWheelsCheat(); + } + //COMEFLYWITHME + else if (!Cheat_strncmp(KeyBoardCheatString, "HROUVr\\SGPZWJ")) { + KeyBoardCheatString[0] = ' '; + ChittyChittyBangBangCheat(); + } + // "GRIPISEVERYTHING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPIatULWP`QWi_M")) { + KeyBoardCheatString[0] = ' '; + StrongGripCheat(); + } + // "CHASESTAT" + else if (!Cheat_strncmp(KeyBoardCheatString, "WF[TRnDOD")) { + KeyBoardCheatString[0] = ' '; + } + // "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] = ' '; + } + // "MIAMITRAFFIC" + else if (!Cheat_strncmp(KeyBoardCheatString, "FNMGNmWPNLVU")) { + KeyBoardCheatString[0] = ' '; + } + // "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(true, MI_BLOODRA); + } + // "THELASTRIDE" + else if (!Cheat_strncmp(KeyBoardCheatString, "HIPSanDSFSa")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_ROMERO); + } + // "ROCKANDROLLCAR" + else if (!Cheat_strncmp(KeyBoardCheatString, "UFJMYjUKOLXKVr")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_LOVEFIST); + } + // "RUBBISHCAR" + else if (!Cheat_strncmp(KeyBoardCheatString, "UFJI`dEIV]")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_TRASH); + } + // "GETTHEREQUICKLY" + else if (!Cheat_strncmp(KeyBoardCheatString, "\\QRDVpTLSPU\\[eT")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_BLOODRB); + } + // "GETTHEREFAST" + else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGRmHOU_RO")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_SABRETUR); + } + // "BETTERTHANWALKING" + else if (!Cheat_strncmp(KeyBoardCheatString, "JSPLY\\ZUBSaZLtaK^")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_CADDY); + } + // "GETTHEREFASTINDEED" + else if (!Cheat_strncmp(KeyBoardCheatString, "GJLE[dWZBQfZLvRXa[^WHL")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, MI_HOTRINA); + } + // "GETTHEREAMAZINGLYFAST" + else if (!Cheat_strncmp(KeyBoardCheatString, "WXHGfgJUJeNUHe_Kdg^HJ")) { + KeyBoardCheatString[0] = ' '; + VehicleCheat(true, 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"); + } + // SEAWAYS + else if (!Cheat_strncmp(KeyBoardCheatString, "V^HXN`V")) { + KeyBoardCheatString[0] = ' '; + BackToTheFuture(); + } + //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(); + } // "ILOVESCOTLAND" - if ( !_CHEATCMP("DNALTOCSEVOLI") ) + if (!_CHEATCMP("DNALTOCSEVOLI")) RainyWeatherCheat(); - // "PEASOUP" - if ( !_CHEATCMP("PUOSAEP") ) - FoggyWeatherCheat(); - // "MADWEATHER" - if ( !_CHEATCMP("REHTAEWDAM") ) + if (!_CHEATCMP("REHTAEWDAM")) FastWeatherCheat(); - // "ANICESETOFWHEELS" - if ( !_CHEATCMP("SLEEHWFOTESECINA") ) - OnlyRenderWheelsCheat(); - // "CHITTYCHITTYBB" - if ( !_CHEATCMP("BBYTTIHCYTTIHC") ) + if (!_CHEATCMP("BBYTTIHCYTTIHC")) ChittyChittyBangBangCheat(); - // "CORNERSLIKEMAD" - if ( !_CHEATCMP("DAMEKILSRENROC") ) - StrongGripCheat(); - // "NASTYLIMBSCHEAT" - if ( !_CHEATCMP("TAEHCSBMILYTSAN") ) + if (!_CHEATCMP("TAEHCSBMILYTSAN")) NastyLimbsCheat(); #ifdef KANGAROO_CHEAT @@ -1000,7 +1369,17 @@ void CPad::AddToPCCheatString(char c) AltDodoCheat(); #endif - #undef _CHEATCMP +#if !defined(PC_WATER) && defined(WATER_CHEATS) + // SEABEDCHEAT + if (!_CHEATCMP("TAEHCDEBAESON")) + NoSeaBedCheat(); + + // WATERLAYERSCHEAT + if (!_CHEATCMP("TAEHCSREYALRETAW")) + RenderWaterLayersCheat(); +#endif + +#undef _CHEATCMP } #ifdef XINPUT @@ -1098,13 +1477,13 @@ void CPad::UpdatePads(void) IsAffectedByController = false; #endif - if ( CReplay::IsPlayingBackFromFile() ) + if ( CReplay::IsPlayingBackFromFile() && !FrontEndMenuManager.m_bMenuActive ) bUpdate = false; if ( bUpdate ) { GetPad(0)->Update(0); - GetPad(1)->Update(0); + // GetPad(1)->Update(0); // not in VC } #if defined(MASTER) && !defined(XINPUT) @@ -1399,6 +1778,9 @@ void CPad::Update(int16 pad) ProcessPCSpecificStuff(); + if (NewState.CheckForInput()) + LastTimeTouched = CTimer::GetTimeInMilliseconds(); + if ( ++iCurrHornHistory >= HORNHISTORY_SIZE ) iCurrHornHistory = 0; @@ -1536,7 +1918,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; @@ -2262,6 +2644,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() ) @@ -2591,7 +3013,7 @@ 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, @@ -2608,7 +3030,7 @@ 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, @@ -2633,6 +3055,7 @@ void CPad::ResetCheats(void) CPopulation::ms_bGivePedsWeapons = false; CPed::bNastyLimbsCheat = false; + CPed::bFannyMagnetCheat = false; CPed::bPedCheat2 = false; CPed::bPedCheat3 = false; @@ -2641,6 +3064,9 @@ void CPad::ResetCheats(void) CVehicle::bCheat3 = false; CVehicle::bCheat4 = false; CVehicle::bCheat5 = false; + CVehicle::bCheat8 = false; + gbBlackCars = false; + gbPinkCars = false; gbFastTime = false; CTimer::SetTimeScale(1.0f); diff --git a/src/core/Pad.h b/src/core/Pad.h index 8c3bc752..2a0bb7d3 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 @@ -150,10 +151,10 @@ public: int16 Phase; int16 Mode; int16 ShakeDur; + uint16 DisablePlayerControls; uint8 ShakeFreq; bool bHornHistory[HORNHISTORY_SIZE]; uint8 iCurrHornHistory; - uint8 DisablePlayerControls; int8 bApplyBrakes; char CheatString[12]; int32 LastTimeTouched; @@ -174,7 +175,7 @@ public: 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; @@ -236,6 +237,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); @@ -258,6 +261,7 @@ public: static void ResetCheats(void); static char *EditString(char *pStr, int32 nSize); static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize); + uint32 InputHowLongAgo(void); #ifdef XINPUT void AffectFromXinput(uint32 pad); @@ -449,9 +453,9 @@ public: 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; } diff --git a/src/core/Placeable.cpp b/src/core/Placeable.cpp index 69b3d3ea..6efc1540 100644 --- a/src/core/Placeable.cpp +++ b/src/core/Placeable.cpp @@ -7,8 +7,6 @@ CPlaceable::CPlaceable(void) m_matrix.SetScale(1.0f); } -CPlaceable::~CPlaceable(void) = default; - void CPlaceable::SetHeading(float angle) { diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 970c0d48..22f7583c 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -9,7 +9,6 @@ public: CMatrix m_matrix; 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; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 09b3a499..3c01a176 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -140,20 +140,27 @@ CPlayerInfo::Clear(void) m_nUpsideDownCounter = 0; m_bInfiniteSprint = false; m_bFastReload = 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; + m_nCurrentBustedAudio = 1; + m_nBustedAudioStatus = BUSTEDAUDIO_NONE; } void -CPlayerInfo::BlowUpRCBuggy(void) +CPlayerInfo::BlowUpRCBuggy(bool actually) { if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld) return; CRemote::TakeRemoteControlledCarFromPlayer(); - m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); + if (actually) + m_pRemoteVehicle->BlowUpCar(FindPlayerPed()); } void @@ -171,7 +178,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); @@ -192,7 +198,8 @@ 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; @@ -348,7 +355,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; diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 94410753..11f51ac0 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -10,6 +10,13 @@ enum eWastedBustedState WBSTATE_FAILED_CRITICAL_MISSION, }; +enum eBustedAudioState : uint8 +{ + BUSTEDAUDIO_NONE, + BUSTEDAUDIO_LOADING, + BUSTEDAUDIO_DONE +}; + class CEntity; class CPed; class CVehicle; @@ -42,6 +49,7 @@ public: uint32 m_nTimeLastHealthLoss; uint32 m_nTimeLastArmourLoss; uint32 m_nTimeTankShotGun; + int32 m_nTimeNotFullyOnGround; int32 m_nUpsideDownCounter; int32 field_248; int16 m_nTrafficMultiplier; @@ -50,10 +58,18 @@ public: int32 m_nExplosionsSinceLastReward; int32 field_268; int32 field_272; + 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; + eBustedAudioState m_nBustedAudioStatus; + int16 m_nCurrentBustedAudio; char m_aSkinName[32]; RwTexture *m_pSkinTexture; @@ -69,7 +85,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); @@ -80,5 +96,3 @@ public: ~CPlayerInfo() { }; }; - -VALIDATE_SIZE(CPlayerInfo, 0x13C); diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index bd0814d0..6e3799f4 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -542,8 +542,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); + } + } if (pedtype == PEDTYPE_PLAYER1) { pPed->m_wepAccuracy = 100; diff --git a/src/core/Pools.h b/src/core/Pools.h index b0ba6598..2f0537ff 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,7 +16,7 @@ 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; diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 05002a3f..559a8cd6 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -21,49 +21,87 @@ 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 @@ -83,16 +121,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; uint16 CRadar::MapLegendCounter; -uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; +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; @@ -226,10 +263,9 @@ int LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D & uint8 CRadar::CalculateBlipAlpha(float dist) { -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) + if (FrontEndMenuManager.m_bMenuMapActive) return 255; -#endif + if (dist <= 1.0f) return 255; @@ -273,12 +309,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 } } @@ -378,9 +411,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; @@ -398,7 +430,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), 1, pos, 2.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, CARBLIP_MARKER_COLOR_R, CARBLIP_MARKER_COLOR_G, CARBLIP_MARKER_COLOR_B, CARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -412,7 +444,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), 1, pos, 1.5f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, CHARBLIP_MARKER_COLOR_R, CHARBLIP_MARKER_COLOR_G, CHARBLIP_MARKER_COLOR_B, CHARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -422,7 +454,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), 1, pos, 1.0f, 0, 128, 255, 255, 1024, 0.2f, 5); + C3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, OBJECTBLIP_MARKER_COLOR_R, OBJECTBLIP_MARKER_COLOR_G, OBJECTBLIP_MARKER_COLOR_B, OBJECTBLIP_MARKER_COLOR_A, 1024, 0.2f, 5); } break; } @@ -431,7 +463,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), 4, ms_RadarTrace[i].m_vecPos, 2.0f, 0, 128, 255, 128, 2048, 0.2f, 0); + C3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, 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; } @@ -453,9 +485,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(); @@ -475,17 +505,10 @@ 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; @@ -493,8 +516,8 @@ 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_SAVE + || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN) { switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_CAR: @@ -527,21 +550,24 @@ void CRadar::DrawBlips() 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; + 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)); } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); + 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); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); #endif + } } } } @@ -549,8 +575,8 @@ void CRadar::DrawBlips() 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) + if ((ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SAVE + || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_SPRAY || ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_GUN) && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); @@ -566,21 +592,24 @@ void CRadar::DrawBlips() 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; + 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)); } - ShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode); + 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); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); #endif + } } } } @@ -597,8 +626,8 @@ 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_SAVE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN) { switch (ms_RadarTrace[blipId].m_eBlipType) { case BLIP_CAR: @@ -632,23 +661,25 @@ void CRadar::DrawBlips() 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 + 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 #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; + { + 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); } - 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); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); #endif + } } } } @@ -664,8 +695,8 @@ 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 + if (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE + && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN && (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission())) { uint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim); @@ -681,23 +712,25 @@ void CRadar::DrawBlips() 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 + 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 #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; + { + 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); } - 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); + ShowRadarTrace(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255); #endif + } } } break; @@ -705,14 +738,12 @@ void CRadar::DrawBlips() break; } } -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { CVector2D in, out; TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); TransformRadarPointToScreenSpace(out, in); DrawYouAreHereSprite(out.x, out.y); } -#endif } } @@ -735,7 +766,8 @@ void CRadar::DrawMap() m_radarRange = RADAR_MIN_RANGE; vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); - DrawRadarMap(); + if (FrontEndMenuManager.m_PrefsRadarMode != 1) + DrawRadarMap(); } } @@ -860,8 +892,8 @@ 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)); -#ifdef MENU_MAP - if (CMenuManager::bMenuMapActive) { + + if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; for (int i = 0; i < NUM_MAP_LEGENDS; i++) { if (MapLegendList[i] == sprite) @@ -872,7 +904,6 @@ void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) MapLegendCounter++; } } -#endif } void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) @@ -992,6 +1023,7 @@ CRadar::Initialise() 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; @@ -1007,10 +1039,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; @@ -1036,26 +1068,45 @@ 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(); } @@ -1072,7 +1123,7 @@ void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size) INITSAVEBUF WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE); -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS if (TargetMarkerId != -1) { ClearBlip(TargetMarkerId); TargetMarkerId = -1; @@ -1102,8 +1153,9 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay } 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_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; @@ -1114,6 +1166,15 @@ int CRadar::SetCoordBlip(eBlipType type, CVector pos, int32 color, eBlipDisplay return CRadar::GetNewUniqueBlipIndex(nextBlip); } +int CRadar::SetShortRangeCoordBlip(eBlipType type, CVector pos, int32 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, int32 color, eBlipDisplay display) { int nextBlip; @@ -1123,8 +1184,9 @@ int CRadar::SetEntityBlip(eBlipType type, int32 handle, int32 color, eBlipDispla } 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_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; @@ -1207,9 +1269,10 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); break; } -#ifdef MENU_MAP + + // TODO(Miami): Map // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips - if (CMenuManager::bMenuMapActive) { + if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; for (int i = 0; i < NUM_MAP_LEGENDS; i++) { if (MapLegendList[i] == -1) @@ -1221,31 +1284,49 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, ArrowBlipColour1 = CRGBA(red, green, blue, alpha); } } -#endif } 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(); } @@ -1314,14 +1395,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 @@ -1375,10 +1452,7 @@ 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 - ) { + || FrontEndMenuManager.m_bMenuMapActive ) { cachedSin = 0.0f; cachedCos = 1.0f; } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { @@ -1399,14 +1473,13 @@ 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; } @@ -1443,6 +1516,7 @@ CRadar::DrawYouAreHereSprite(float x, float y) MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE; } +#ifdef MAP_ENHANCEMENTS void CRadar::ToggleTargetMarker(float x, float y) { diff --git a/src/core/Radar.h b/src/core/Radar.h index ec2bacd0..a36faaea 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -1,6 +1,35 @@ #pragma once #include "Sprite2d.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 255 + +#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, @@ -21,31 +50,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 }; @@ -66,16 +113,16 @@ struct sRadarTrace uint16 m_BlipIndex; bool m_bDim; bool m_bInUse; + bool m_bShortRange; float m_Radius; int16 m_wScale; uint16 m_eBlipDisplay; // eBlipDisplay uint16 m_eRadarSprite; // eRadarSprite }; -VALIDATE_SIZE(sRadarTrace, 0x30); // Values for screen space #define RADAR_LEFT (40.0f) -#define RADAR_BOTTOM (47.0f) +#define RADAR_BOTTOM (40.0f) #define RADAR_WIDTH (94.0f) #define RADAR_HEIGHT (76.0f) @@ -84,40 +131,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 -#define NUM_MAP_LEGENDS 75 static CRGBA ArrowBlipColour1; static CRGBA ArrowBlipColour2; - static uint16 MapLegendList[NUM_MAP_LEGENDS]; + static int16 MapLegendList[NUM_MAP_LEGENDS]; static uint16 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); @@ -149,6 +217,7 @@ public: 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 SetShortRangeCoordBlip(eBlipType type, CVector pos, int32, 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); diff --git a/src/core/Ropes.cpp b/src/core/Ropes.cpp new file mode 100644 index 00000000..dbae9ee3 --- /dev/null +++ b/src/core/Ropes.cpp @@ -0,0 +1,173 @@ +#include "common.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; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive) + aRopes[i].Render(); +} + +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(CRope::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(CRope::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_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..2e3a27b2 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -4,6 +4,11 @@ #include "Text.h" #include "World.h" +#include <climits> + +//TODO +int32 CStats::SeagullsKilled; + int32 CStats::DaysPassed; int32 CStats::HeadsPopped; int32 CStats::CommercialPassed; @@ -44,7 +49,6 @@ int32 CStats::LivesSavedWithAmbulance; int32 CStats::CriminalsCaught; int32 CStats::HighestLevelAmbulanceMission; int32 CStats::FiresExtinguished; -int32 CStats::LongestFlightInDodo; int32 CStats::TimeTakenDefuseMission; int32 CStats::TotalNumberKillFrenzies; int32 CStats::TotalNumberMissions; @@ -53,10 +57,17 @@ int32 CStats::KgsOfExplosivesUsed; int32 CStats::InstantHitsFiredByPlayer; int32 CStats::InstantHitsHitByPlayer; 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]; +int32 CStats::PropertyDestroyed; + +int32 CStats::Sprayings; +float CStats::AutoPaintingBudget; +int32 CStats::NoMoreHurricanes; +float CStats::FashionBudget; +int32 CStats::SafeHouseVisits; +int32 CStats::TyresPopped; void CStats::Init() { @@ -69,13 +80,11 @@ void CStats::Init() KgsOfExplosivesUsed = 0; InstantHitsFiredByPlayer = 0; InstantHitsHitByPlayer = 0; - CarsCrushed = 0; HeadsPopped = 0; TimesArrested = 0; TimesDied = 0; DaysPassed = 0; NumberOfUniqueJumpsFound = 0; - mmRain = 0; MaximumJumpFlips = 0; MaximumJumpSpins = 0; MaximumJumpDistance = 0; @@ -83,7 +92,6 @@ void CStats::Init() BestStuntJump = 0; TotalNumberOfUniqueJumps = 0; Record4x4One = 0; - LongestFlightInDodo = 0; Record4x4Two = 0; PassengersDroppedOffWithTaxi = 0; Record4x4Three = 0; @@ -108,11 +116,18 @@ void CStats::Init() FastestTimes[i] = 0; for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++) HighestScores[i] = 0; + for (int i = 0; i < TOTAL_BEST_POSITIONS; i++) + BestPositions[i] = INT_MAX; for (int i = 0; i < NUM_PEDTYPES; i++) PedsKilledOfThisType[i] = 0; IndustrialPassed = 0; CommercialPassed = 0; SuburbanPassed = 0; + + Sprayings = 0; + AutoPaintingBudget = 0.0f; + NoMoreHurricanes = 0; + SafeHouseVisits = 0; } void CStats::RegisterFastestTime(int32 index, int32 time) @@ -130,6 +145,12 @@ void CStats::RegisterHighestScore(int32 index, int32 score) HighestScores[index] = Max(HighestScores[index], score); } +void CStats::RegisterBestPosition(int32 index, int32 position) +{ + assert(index >= 0 && index < TOTAL_BEST_POSITIONS); + BestPositions[index] = Min(BestPositions[index], position); +} + void CStats::RegisterElBurroTime(int32 time) { ElBurroTime = (ElBurroTime && ElBurroTime < time) ? ElBurroTime : time; @@ -175,11 +196,6 @@ void CStats::AnotherFireExtinguished() ++FiresExtinguished; } -void CStats::RegisterLongestFlightInDodo(int32 time) -{ - LongestFlightInDodo = Max(LongestFlightInDodo, time); -} - void CStats::RegisterTimeTakenDefuseMission(int32 time) { TimeTakenDefuseMission = (TimeTakenDefuseMission && TimeTakenDefuseMission < time) ? TimeTakenDefuseMission : time; @@ -241,6 +257,19 @@ int32 CStats::FindCriminalRatingNumber() return rating; } +float CStats::GetPercentageProgress() +{ + float percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : + CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1.0f)); + + return Min(percentCompleted, 100.0f); +} + +void CStats::MoneySpentOnFashion(int32 money) +{ + FashionBudget += money; +} + void CStats::SaveStats(uint8 *buf, uint32 *size) { CheckPointReachedSuccessfully(); @@ -256,12 +285,10 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) sizeof(KgsOfExplosivesUsed) + sizeof(InstantHitsFiredByPlayer) + sizeof(InstantHitsHitByPlayer) + - sizeof(CarsCrushed) + sizeof(HeadsPopped) + sizeof(TimesArrested) + sizeof(TimesDied) + sizeof(DaysPassed) + - sizeof(mmRain) + sizeof(MaximumJumpDistance) + sizeof(MaximumJumpHeight) + sizeof(MaximumJumpFlips) + @@ -287,13 +314,13 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) sizeof(CriminalsCaught) + sizeof(HighestLevelAmbulanceMission) + sizeof(FiresExtinguished) + - sizeof(LongestFlightInDodo) + sizeof(TimeTakenDefuseMission) + sizeof(NumberKillFrenziesPassed) + sizeof(TotalNumberKillFrenzies) + sizeof(TotalNumberMissions) + sizeof(FastestTimes) + sizeof(HighestScores) + + sizeof(BestPositions) + sizeof(KillsSinceLastCheckpoint) + sizeof(TotalLegitimateKills) + sizeof(LastMissionPassedName); @@ -310,12 +337,10 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) CopyToBuf(buf, KgsOfExplosivesUsed); CopyToBuf(buf, InstantHitsFiredByPlayer); CopyToBuf(buf, InstantHitsHitByPlayer); - CopyToBuf(buf, CarsCrushed); CopyToBuf(buf, HeadsPopped); CopyToBuf(buf, TimesArrested); CopyToBuf(buf, TimesDied); CopyToBuf(buf, DaysPassed); - CopyToBuf(buf, mmRain); CopyToBuf(buf, MaximumJumpDistance); CopyToBuf(buf, MaximumJumpHeight); CopyToBuf(buf, MaximumJumpFlips); @@ -341,13 +366,13 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) CopyToBuf(buf, CriminalsCaught); CopyToBuf(buf, HighestLevelAmbulanceMission); CopyToBuf(buf, FiresExtinguished); - CopyToBuf(buf, LongestFlightInDodo); CopyToBuf(buf, TimeTakenDefuseMission); CopyToBuf(buf, NumberKillFrenziesPassed); CopyToBuf(buf, TotalNumberKillFrenzies); CopyToBuf(buf, TotalNumberMissions); CopyToBuf(buf, FastestTimes); CopyToBuf(buf, HighestScores); + CopyToBuf(buf, BestPositions); CopyToBuf(buf, KillsSinceLastCheckpoint); CopyToBuf(buf, TotalLegitimateKills); CopyToBuf(buf, LastMissionPassedName); @@ -373,12 +398,10 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, KgsOfExplosivesUsed); CopyFromBuf(buf, InstantHitsFiredByPlayer); CopyFromBuf(buf, InstantHitsHitByPlayer); - CopyFromBuf(buf, CarsCrushed); CopyFromBuf(buf, HeadsPopped); CopyFromBuf(buf, TimesArrested); CopyFromBuf(buf, TimesDied); CopyFromBuf(buf, DaysPassed); - CopyFromBuf(buf, mmRain); CopyFromBuf(buf, MaximumJumpDistance); CopyFromBuf(buf, MaximumJumpHeight); CopyFromBuf(buf, MaximumJumpFlips); @@ -404,13 +427,13 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, CriminalsCaught); CopyFromBuf(buf, HighestLevelAmbulanceMission); CopyFromBuf(buf, FiresExtinguished); - CopyFromBuf(buf, LongestFlightInDodo); CopyFromBuf(buf, TimeTakenDefuseMission); CopyFromBuf(buf, NumberKillFrenziesPassed); CopyFromBuf(buf, TotalNumberKillFrenzies); CopyFromBuf(buf, TotalNumberMissions); CopyFromBuf(buf, FastestTimes); CopyFromBuf(buf, HighestScores); + CopyFromBuf(buf, BestPositions); CopyFromBuf(buf, KillsSinceLastCheckpoint); CopyFromBuf(buf, TotalLegitimateKills); CopyFromBuf(buf, LastMissionPassedName); diff --git a/src/core/Stats.h b/src/core/Stats.h index 5dfcf803..7dd527ea 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -6,9 +6,13 @@ class CStats { public: enum { - TOTAL_FASTEST_TIMES = 16, - TOTAL_HIGHEST_SCORES = 16 + TOTAL_FASTEST_TIMES = 23, + TOTAL_HIGHEST_SCORES = 5, + TOTAL_BEST_POSITIONS = 1 }; + //TODO + static int32 SeagullsKilled; + static int32 DaysPassed; static int32 HeadsPopped; static int32 CommercialPassed; @@ -49,7 +53,6 @@ public: static int32 CriminalsCaught; static int32 HighestLevelAmbulanceMission; static int32 FiresExtinguished; - static int32 LongestFlightInDodo; static int32 TimeTakenDefuseMission; static int32 TotalNumberKillFrenzies; static int32 TotalNumberMissions; @@ -58,15 +61,22 @@ public: static int32 InstantHitsFiredByPlayer; static int32 InstantHitsHitByPlayer; 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 int32 PropertyDestroyed; + static int32 Sprayings; + static float AutoPaintingBudget; + static int32 NoMoreHurricanes; + static float FashionBudget; + static int32 SafeHouseVisits; + static int32 TyresPopped; public: static void Init(void); static void RegisterFastestTime(int32, int32); static void RegisterHighestScore(int32, int32); + static void RegisterBestPosition(int32, int32); static void RegisterElBurroTime(int32); static void Register4x4OneTime(int32); static void Register4x4TwoTime(int32); @@ -77,7 +87,6 @@ public: static void RegisterLevelAmbulanceMission(int32); static void AnotherFireExtinguished(); static wchar *FindCriminalRatingString(); - static void RegisterLongestFlightInDodo(int32); static void RegisterTimeTakenDefuseMission(int32); static void AnotherKillFrenzyPassed(); static void SetTotalNumberKillFrenzies(int32); @@ -87,4 +96,7 @@ public: static int32 FindCriminalRatingNumber(); static void SaveStats(uint8 *buf, uint32 *size); static void LoadStats(uint8 *buf, uint32 size); + static float GetPercentageProgress(); + + static void MoneySpentOnFashion(int32); }; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 40189844..3c32b856 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,10 +27,10 @@ #include "CutsceneMgr.h" #include "CdStream.h" #include "Streaming.h" -#ifdef FIX_BUGS #include "Replay.h" -#endif #include "main.h" +#include "ColStore.h" +#include "DMAudio.h" bool CStreaming::ms_disableStreaming; bool CStreaming::ms_bLoadingBigModel; @@ -51,9 +50,9 @@ int32 CStreaming::ms_channelError; int32 CStreaming::ms_numVehiclesLoaded; 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; @@ -66,17 +65,12 @@ 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; +//--MIAMI: done bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) { @@ -87,6 +81,7 @@ CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) return true; } +//--MIAMI: done void CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size) { @@ -94,6 +89,7 @@ CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size) m_size = size; } +//--MIAMI: done void CStreamingInfo::AddToList(CStreamingInfo *link) { @@ -104,6 +100,7 @@ CStreamingInfo::AddToList(CStreamingInfo *link) m_next->m_prev = this; } +//--MIAMI: done void CStreamingInfo::RemoveFromList(void) { @@ -113,6 +110,7 @@ CStreamingInfo::RemoveFromList(void) m_prev = nil; } +//--MIAMI: done void CStreaming::Init2(void) { @@ -182,13 +180,15 @@ CStreaming::Init2(void) ms_vehiclesLoaded[i] = -1; ms_numVehiclesLoaded = 0; + 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(); @@ -199,49 +199,20 @@ CStreaming::Init2(void) ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); - // PC only, figure out how much memory we got -#ifdef GTA_PC #define MB (1024*1024) - - 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(desiredNumVehiclesLoaded > MAXVEHICLESLOADED) - desiredNumVehiclesLoaded = MAXVEHICLESLOADED; - debug("Memory allocated to Streaming is %zuMB", ms_memoryAvailable/MB); // original modifier was %d + ms_memoryAvailable = 65 * MB; + desiredNumVehiclesLoaded = 25; + debug("Memory allocated to Streaming is %dMB", ms_memoryAvailable / MB); #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); - - 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; - } + pIslandLODmainlandEntity = nil; + pIslandLODbeachEntity = nil; + islandLODmainland = -1; + islandLODbeach = -1; + CModelInfo::GetModelInfo("IslandLODmainland", &islandLODmainland); + CModelInfo::GetModelInfo("IslandLODbeach", &islandLODbeach); } void @@ -267,6 +238,7 @@ CStreaming::Init(void) #endif } +//--MIAMI: done void CStreaming::Shutdown(void) { @@ -276,10 +248,10 @@ CStreaming::Shutdown(void) delete ms_pExtraObjectsDir; } +//--MIAMI: done void CStreaming::Update(void) { - CEntity *train; CStreamingInfo *si, *prev; bool requestedSubway = false; @@ -293,31 +265,32 @@ CStreaming::Update(void) if(CTimer::GetIsPaused()) return; - train = FindPlayerTrain(); - if(train && train->GetPosition().z < 0.0f){ - RequestSubway(); - requestedSubway = true; - }else if(!ms_disableStreaming) + LoadBigBuildingsWhenNeeded(); + if(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f) AddModelsToRequestList(TheCamera.GetPosition()); 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(); + 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()); + } for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){ prev = si->m_prev; @@ -326,6 +299,7 @@ CStreaming::Update(void) } } +//--MIAMI: done void CStreaming::LoadCdDirectory(void) { @@ -339,12 +313,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 @@ -360,12 +328,12 @@ CStreaming::LoadCdDirectory(void) ms_imageSize /= CDSTREAM_SECTOR_SIZE; } +//--MIAMI: done 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; @@ -376,23 +344,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, '.'); - 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; + } - if(!CGeneral::faststrcmp(dot+1, "DFF") || !CGeneral::faststrcmp(dot+1, "dff")){ + *dot = '\0'; + + 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 @@ -402,27 +370,63 @@ 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)->GetName()); + 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; +} + + +//--MIAMI: done bool CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) { @@ -444,22 +448,25 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) // Model mi = CModelInfo::GetModelInfo(streamId); - // Txd has to be loaded - if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil){ - debug("failed to load %s because TXD %s is not in memory\n", mi->GetName(), CTxdStore::GetTxdName(mi->GetTxdSlot())); + // Txd and anim have to be loaded + int animId = mi->GetAnimFileIndex(); + if(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil || + animId != -1 && !CAnimManager::GetAnimationBlock(animId)->isLoaded){ RemoveModel(streamId); - RemoveTxd(mi->GetTxdSlot()); ReRequestModel(streamId); RwStreamClose(stream, &mem); return false; } - // Set Txd to use + // Set Txd and anims to use CTxdStore::AddRef(mi->GetTxdSlot()); + if(animId != -1) + CAnimManager::AddAnimBlockRef(animId); CTxdStore::SetCurrentTxd(mi->GetTxdSlot()); if(mi->IsSimple()){ success = CFileLoader::LoadAtomicFile(stream, streamId); + // 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(); @@ -471,9 +478,12 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) } 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(animId != -1) + CAnimManager::RemoveAnimBlockRefWithoutDelete(animId); + } if(!success){ debug("Failed to load %s\n", CModelInfo::GetModelInfo(streamId)->GetName()); @@ -482,9 +492,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); @@ -507,20 +516,28 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) RwStreamClose(stream, &mem); return false; } + }else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){ + if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){ + 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; + } + CAnimManager::LoadAnimFile(stream, true, nil); + CAnimManager::CreateAnimAssocGroups(); } 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->GetName()); - 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 @@ -535,12 +552,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); } @@ -552,17 +571,13 @@ 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)->GetName(), 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; } - +//--MIAMI: done bool CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) { @@ -593,11 +608,15 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) success = AddToLoadedVehiclesList(streamId); mi->RemoveRef(); CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot()); - }else{ + if(mi->GetAnimFileIndex() != -1) + CAnimManager::RemoveAnimBlockRefWithoutDelete(mi->GetAnimFileIndex()); + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ // Txd CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD); success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream); CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD); + }else{ + assert(0 && "invalid streamId"); } RwStreamClose(stream, &mem); @@ -615,16 +634,13 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId) 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)->GetName(), 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; } +//--MIAMI: done void CStreaming::RequestModel(int32 id, int32 flags) { @@ -653,15 +669,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) @@ -673,52 +694,28 @@ CStreaming::RequestModel(int32 id, int32 flags) } } +#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE + +//--MIAMI: done 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 && b->m_level == level) + if(!b->bStreamBIGBuilding) + RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); } + RequestIslands(level); } -#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY - +//--MIAMI: done void -CStreaming::RequestBigBuildings(eLevelName level) +CStreaming::RequestBigBuildings(eLevelName level, const CVector &pos) { int i, n; CBuilding *b; @@ -731,34 +728,93 @@ CStreaming::RequestBigBuildings(eLevelName 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; } +//--MIAMI: done +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(); + } +} + +//--MIAMI: done +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(); + } +} + +//--MIAMI: done +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]); + } + } +} + +//--MIAMI: done void CStreaming::RequestIslands(eLevelName level) { #ifndef NO_ISLAND_LOADING switch(level){ - case LEVEL_INDUSTRIAL: - RequestModel(islandLODcomInd, BIGBUILDINGFLAGS); - RequestModel(islandLODsubInd, BIGBUILDINGFLAGS); - break; - case LEVEL_COMMERCIAL: - RequestModel(islandLODindust, BIGBUILDINGFLAGS); - RequestModel(islandLODsubCom, BIGBUILDINGFLAGS); + case LEVEL_MAINLAND: + if(islandLODbeach != -1) + RequestModel(islandLODbeach, BIGBUILDINGFLAGS); break; - case LEVEL_SUBURBAN: - RequestModel(islandLODindust, BIGBUILDINGFLAGS); - RequestModel(islandLODcomSub, BIGBUILDINGFLAGS); + case LEVEL_BEACH: + if(islandLODmainland != -1) + RequestModel(islandLODmainland, BIGBUILDINGFLAGS); break; default: break; } #endif } +//--MIAMI: TODO void CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flags) { @@ -800,24 +856,28 @@ CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flag RequestModel(modelId, flags); } +//--MIAMI: done void CStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags) { RequestSpecialModel(charId + MI_SPECIAL01, modelName, flags); } +//--MIAMI: done bool CStreaming::HasSpecialCharLoaded(int32 id) { return HasModelLoaded(id + MI_SPECIAL01); } +//--MIAMI: done void CStreaming::SetMissionDoesntRequireSpecialChar(int32 id) { return SetMissionDoesntRequireModel(id + MI_SPECIAL01); } +//--MIAMI: done void CStreaming::DecrementRef(int32 id) { @@ -828,6 +888,7 @@ CStreaming::DecrementRef(int32 id) } } +//--MIAMI: done void CStreaming::RemoveModel(int32 id) { @@ -839,8 +900,14 @@ 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); + 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; } @@ -861,24 +928,30 @@ 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); + 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; } +//--MIAMI: done 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); } +//--MIAMI: done void CStreaming::RemoveBuildings(eLevelName level) { @@ -939,20 +1012,20 @@ CStreaming::RemoveBuildings(eLevelName level) } } +//--MIAMI: done void CStreaming::RemoveUnusedBigBuildings(eLevelName level) { #ifndef NO_ISLAND_LOADING - 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); #endif RemoveIslandsNotUsed(level); } +//--MIAMI: done void DeleteIsland(CEntity *island) { @@ -966,39 +1039,36 @@ DeleteIsland(CEntity *island) } } +//--MIAMI: done void CStreaming::RemoveIslandsNotUsed(eLevelName level) { #ifndef NO_ISLAND_LOADING + 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; + } + switch(level){ - case LEVEL_INDUSTRIAL: - DeleteIsland(pIslandLODindustEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubComEntity); + case LEVEL_MAINLAND: + DeleteIsland(pIslandLODmainlandEntity); break; - case LEVEL_COMMERCIAL: - DeleteIsland(pIslandLODcomIndEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubIndEntity); - break; - case LEVEL_SUBURBAN: - DeleteIsland(pIslandLODsubIndEntity); - DeleteIsland(pIslandLODsubComEntity); - DeleteIsland(pIslandLODcomIndEntity); - break; - default: -#endif // !NO_ISLAND_LOADING - DeleteIsland(pIslandLODindustEntity); - DeleteIsland(pIslandLODcomIndEntity); - DeleteIsland(pIslandLODcomSubEntity); - DeleteIsland(pIslandLODsubIndEntity); - DeleteIsland(pIslandLODsubComEntity); -#ifndef NO_ISLAND_LOADING + case LEVEL_BEACH: + DeleteIsland(pIslandLODbeachEntity); + break; } #endif // !NO_ISLAND_LOADING } +//--MIAMI: done void CStreaming::RemoveBigBuildings(eLevelName level) { @@ -1030,8 +1100,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; } @@ -1040,33 +1109,47 @@ 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; } +//--MIAMI: done 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(); } +//--MIAMI: done void CStreaming::RemoveAllUnusedModels(void) { @@ -1077,7 +1160,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; @@ -1085,30 +1167,14 @@ CStreaming::RemoveAllUnusedModels(void) } } -bool -CStreaming::RemoveReferencedTxds(size_t mem) -{ - CStreamingInfo *si; - int streamId; - - 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; - } - } - return false; -} - +//--MIAMI: done void CStreaming::RemoveUnusedModelsInLoadedList(void) { // empty } +//--MIAMI: done bool CStreaming::IsTxdUsedByRequestedModels(int32 txdId) { @@ -1137,6 +1203,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) { @@ -1168,8 +1262,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) @@ -1185,13 +1279,21 @@ found: ms_lastVehicleDeleted = id; // this is more that 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; } @@ -1203,41 +1305,6 @@ 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; @@ -1256,6 +1323,7 @@ CStreaming::SetModelTxdIsDeletable(int32 id) SetModelIsDeletable(CModelInfo::GetModelInfo(id)->GetTxdSlot() + STREAM_OFFSET_TXD); } +//--MIAMI: done void CStreaming::SetMissionDoesntRequireModel(int32 id) { @@ -1278,6 +1346,13 @@ CStreaming::LoadInitialPeds(void) } void +CStreaming::LoadInitialWeapons(void) +{ + CStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE); + CStreaming::RequestModel(MI_MISSILE, STREAMFLAGS_DONT_REMOVE); +} + +void CStreaming::LoadInitialVehicles(void) { int id; @@ -1316,11 +1391,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); } @@ -1340,28 +1415,73 @@ 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); + 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; + } + RequestModel(MI_VICECHEE, STREAMFLAGS_DONT_REMOVE); + } + 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) || + (i != 0 && zone.carThreshold[i] != zone.carThreshold[i-1]))) { + 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; } } +//--MIAMI: TODO void CStreaming::StreamZoneModels(const CVector &pos) { @@ -1387,58 +1507,54 @@ CStreaming::StreamZoneModels(const CVector &pos) for(i = 0; i < NUMMODELSPERPEDGROUP; i++){ if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1) break; - RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DONT_REMOVE); + RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DEPENDENCY); } } RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE); + //RequestModel(MI_HMOCA, 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); + RequestModel(CGangs::GetGangPedModel1(i), STREAMFLAGS_DEPENDENCY); + RequestModel(CGangs::GetGangPedModel2(i), STREAMFLAGS_DEPENDENCY); 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); + 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); + // TODO(MIAMI): check this + if(CGangs::GetGangVehicleModel(i) < 0) + continue; + + if((gangCarsToLoad & bit) && (ms_loadedGangCars & bit) == 0){ + RequestModel(CGangs::GetGangVehicleModel(i), STREAMFLAGS_DEPENDENCY); }else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){ - SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); - SetModelTxdIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI); + SetModelIsDeletable(CGangs::GetGangVehicleModel(i)); + SetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i)); } } ms_loadedGangCars = gangCarsToLoad; @@ -1449,19 +1565,32 @@ CStreaming::RemoveCurrentZonesModels(void) { int i; - if(ms_currentPedGrp != -1) - for(i = 0; i < 8; i++){ - if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1) + if (ms_currentPedGrp != -1) + for (i = 0; i < NUMMODELSPERPEDGROUP; i++) { + if (CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1) break; - if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01) + if (CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01) { 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; @@ -1469,6 +1598,42 @@ 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; + DMAudio.SetEffectsFadeVol(0); + CPad::StopPadsShaking(); + CCollision::LoadCollisionScreen(CGame::currLevel); + DMAudio.Service(); + + // CPopulation::DealWithZoneChange is unused in VC + RemoveUnusedBigBuildings(CGame::currLevel); + RemoveUnusedBuildings(CGame::currLevel); + RemoveUnusedModelsInLoadedList(); + CGame::TidyUpMemory(true, true); + + CReplay::EmptyReplayBuffer(); + if(CGame::currLevel != LEVEL_GENERIC) + LoadSplash(GetLevelSplashScreen(CGame::currLevel)); + + CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition()); + CStreaming::LoadAllRequestedModels(true); + + CGame::TidyUpMemory(true, true); + CTimer::Resume(); + DMAudio.SetEffectsFadeVol(127); +} + // Find starting offset of the cdimage we next want to read // Not useful at all on PC... @@ -1515,6 +1680,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 @@ -1539,14 +1705,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){ @@ -1589,6 +1761,7 @@ CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) * TODO: two-part files */ +//--MIAMI: done // Make channel read from disc void CStreaming::RequestModelStream(int32 ch) @@ -1603,13 +1776,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 @@ -1646,7 +1824,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) @@ -1693,6 +1872,7 @@ CStreaming::RequestModelStream(int32 ch) ms_channel[ch].numTries = 0; } +//--MIAMI: done // Load data previously read from disc bool CStreaming::ProcessLoadingChannel(int32 ch) @@ -1727,10 +1907,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()); @@ -1762,6 +1942,7 @@ CStreaming::ProcessLoadingChannel(int32 ch) return true; } +//--MIAMI: done void CStreaming::RetryLoadFile(int32 ch) { @@ -1798,6 +1979,7 @@ CStreaming::RetryLoadFile(int32 ch) } } +//--MIAMI: done void CStreaming::LoadRequestedModels(void) { @@ -1822,6 +2004,7 @@ CStreaming::LoadRequestedModels(void) } } +//--MIAMI: done void CStreaming::LoadAllRequestedModels(bool priority) { @@ -1875,6 +2058,7 @@ CStreaming::LoadAllRequestedModels(bool priority) bInsideLoadAll = false; } +//--MIAMI: done void CStreaming::FlushChannels(void) { @@ -1896,6 +2080,7 @@ CStreaming::FlushChannels(void) ProcessLoadingChannel(1); } +//--MIAMI: done void CStreaming::FlushRequestList(void) { @@ -2004,8 +2189,7 @@ 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(), 0); } } } @@ -2028,8 +2212,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list) (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){ 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(), 0); } } } @@ -2267,9 +2450,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){ @@ -2331,9 +2511,6 @@ CStreaming::DeleteRwObjectsBehindCamera(size_t mem) } } - if(RemoveReferencedTxds(mem)) - return; - // As last resort, delete objects from the last step more aggressively for(x = xmin; x <= xmax; x++){ for(y = ymax; y != ymin; y -= inc){ @@ -2432,12 +2609,13 @@ CStreaming::MakeSpaceFor(int32 size) // but it's not nice.... while(ms_memoryUsed >= ms_memoryAvailable - size) - if(!RemoveLeastUsedModel()){ + if(!RemoveLeastUsedModel(STREAMFLAGS_20)){ DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); return; } } +//--MIAMI: done void CStreaming::LoadScene(const CVector &pos) { @@ -2452,16 +2630,44 @@ CStreaming::LoadScene(const CVector &pos) RemoveModel(si - ms_aInfoForModel); } CRenderer::m_loadingPriority = false; - CCullZones::ForceCullZoneCoors(pos); DeleteAllRwObjects(); + if(level == LEVEL_GENERIC) + level = CGame::currLevel; + CGame::currLevel = level; + RemoveUnusedBigBuildings(level); + RequestBigBuildings(level, pos); + RequestBigBuildings(LEVEL_GENERIC, pos); + RemoveIslandsNotUsed(level); + LoadAllRequestedModels(false); + InstanceBigBuildings(level, pos); + InstanceBigBuildings(LEVEL_GENERIC, pos); AddModelsToRequestList(pos); CRadar::StreamRadarSections(pos); - RemoveUnusedBigBuildings(level); - RequestBigBuildings(level); + + 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"); } +//--MIAMI: done +void +CStreaming::LoadSceneCollision(const CVector &pos) +{ + CColStore::LoadCollision(pos); + CStreaming::LoadAllRequestedModels(false); +} + void CStreaming::MemoryCardSave(uint8 *buf, uint32 *size) { @@ -2493,7 +2699,8 @@ CStreaming::UpdateForAnimViewer(void) if (CStreaming::ms_channelError == -1) { CStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f)); 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 0b2ff124..569c06d8 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, @@ -92,9 +95,9 @@ public: static int32 ms_numVehiclesLoaded; 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; @@ -115,14 +118,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); @@ -131,29 +145,32 @@ 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 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); 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); @@ -183,6 +200,7 @@ public: static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem); 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..9076a9a6 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; } diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 1f16843d..359ebd5c 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,6 +59,31 @@ IsSeeThrough(uint8 surfType) switch(surfType) case SURFACE_GLASS: case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_SCAFFOLD_POLE: + 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_METAL_CHAIN_FENCE: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_SCAFFOLD_POLE: return true; return false; } diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index ab73631d..e12b48dd 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -16,6 +16,7 @@ CColModel CTempColModels::ms_colModelPedGroundHit; CColModel CTempColModels::ms_colModelBoot1; CColModel CTempColModels::ms_colModelDoor1; CColModel CTempColModels::ms_colModelBonnet1; +CColModel CTempColModels::ms_colModelWeapon; CColSphere s_aPedSpheres[3]; @@ -41,13 +42,13 @@ CTempColModels::Initialise(void) int i; - ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); + ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f)); ms_colModelBBox.level = LEVEL_GENERIC; for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { - ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); + ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f)); ms_colModelCutObj[i].level = LEVEL_GENERIC; } @@ -69,8 +70,8 @@ CTempColModels::Initialise(void) s_aPedSpheres[i].piece = 0; } - ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f), SURFACE_DEFAULT, 0); + ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f)); SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres); // Ped 2 Spheres @@ -88,8 +89,8 @@ CTempColModels::Initialise(void) s_aPed2Spheres[i].piece = 0; } - ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f), SURFACE_DEFAULT, 0); + ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f)); SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres); @@ -114,8 +115,8 @@ CTempColModels::Initialise(void) s_aPedGSpheres[2].piece = 0; s_aPedGSpheres[3].piece = 6; - ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f), SURFACE_DEFAULT, 0); + ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f)); SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres); @@ -134,8 +135,8 @@ CTempColModels::Initialise(void) s_aDoorSpheres[i].piece = 0; } - ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f), SURFACE_DEFAULT, 0); + ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f)); + ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f)); SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres); @@ -154,8 +155,8 @@ CTempColModels::Initialise(void) s_aBumperSpheres[i].piece = 0; } - ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f), SURFACE_DEFAULT, 0); + ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f)); + ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f)); SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres); @@ -174,8 +175,8 @@ CTempColModels::Initialise(void) s_aPanelSpheres[i].piece = 0; } - ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f), SURFACE_DEFAULT, 0); + ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f)); SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres); @@ -194,8 +195,8 @@ CTempColModels::Initialise(void) s_aBonnetSpheres[i].piece = 0; } - ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f), SURFACE_DEFAULT, 0); + ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f)); + ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f)); SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres); @@ -214,8 +215,8 @@ CTempColModels::Initialise(void) s_aBootSpheres[i].piece = 0; } - ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f), SURFACE_DEFAULT, 0); + ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f)); + ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f)); SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres); @@ -236,8 +237,8 @@ CTempColModels::Initialise(void) s_aWheelSpheres[i].piece = 0; } - ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f), SURFACE_DEFAULT, 0); + ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f)); SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres); @@ -258,8 +259,8 @@ CTempColModels::Initialise(void) s_aBodyPartSpheres1[i].piece = 0; } - ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f), SURFACE_DEFAULT, 0); + ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f)); + ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f)); SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1); @@ -280,10 +281,14 @@ CTempColModels::Initialise(void) s_aBodyPartSpheres2[i].piece = 0; } - ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); - ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f), SURFACE_DEFAULT, 0); + ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f)); + ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f)); SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2); + + ms_colModelWeapon.boundingSphere.Set(0.25f, CVector(0.0f, 0.0f, 0.0f)); + ms_colModelWeapon.boundingBox.Set(CVector(-0.25f, -0.25, -0.25f), CVector(0.25f, 0.25, 0.25f)); + #undef SET_COLMODEL_SPHERES } diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h index 3e1dd5e1..0c936d6f 100644 --- a/src/core/TempColModels.h +++ b/src/core/TempColModels.h @@ -18,6 +18,7 @@ public: static CColModel ms_colModelBoot1; static CColModel ms_colModelDoor1; static CColModel ms_colModelBonnet1; + static CColModel ms_colModelWeapon; static void Initialise(void); }; diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index ed5580fd..f60adf07 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -7,7 +7,8 @@ #include "Timer.h" uint32 CTimer::m_snTimeInMilliseconds; -uint32 CTimer::m_snTimeInMillisecondsPauseMode = 1; +PauseModeTime CTimer::m_snTimeInMillisecondsPauseMode = 1; + uint32 CTimer::m_snTimeInMillisecondsNonClipped; uint32 CTimer::m_snPreviousTimeInMilliseconds; uint32 CTimer::m_FrameCounter; @@ -33,7 +34,7 @@ RsTimerType suspendPcTimer; uint32 suspendDepth; -#ifdef FIX_BUGS +#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND double frameTime; #endif @@ -97,7 +98,7 @@ void CTimer::Update(void) float updInCyclesScaled = updInCycles * ms_fTimeScale; // We need that real frame time to fix transparent menu bug. -#ifndef FIX_BUGS +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND double #endif frameTime = updInCyclesScaled / (double)_nCyclesPerMS; @@ -121,7 +122,7 @@ void CTimer::Update(void) RsTimerType updInMs = timer - oldPcTimer; // We need that real frame time to fix transparent menu bug. -#ifndef FIX_BUGS +#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND double #endif frameTime = (double)updInMs * ms_fTimeScale; diff --git a/src/core/Timer.h b/src/core/Timer.h index 393242dd..53591c4f 100644 --- a/src/core/Timer.h +++ b/src/core/Timer.h @@ -1,10 +1,16 @@ #pragma once +#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND +#define PauseModeTime double +#else +#define PauseModeTime uint32 +#endif + class CTimer { static uint32 m_snTimeInMilliseconds; - static uint32 m_snTimeInMillisecondsPauseMode; + static PauseModeTime m_snTimeInMillisecondsPauseMode; static uint32 m_snTimeInMillisecondsNonClipped; static uint32 m_snPreviousTimeInMilliseconds; static uint32 m_FrameCounter; @@ -29,7 +35,7 @@ public: static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; } static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; } static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; } - static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; } + static PauseModeTime GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; } static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; } static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; } static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } @@ -64,6 +70,6 @@ public: #endif }; -#ifdef FIX_BUGS +#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND extern double frameTime; #endif 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..c70a3ab5 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -12,14 +12,18 @@ #include "General.h" int32 CWanted::MaximumWantedLevel = 6; -int32 CWanted::nMaximumWantedLevel = 6400; +int32 CWanted::nMaximumWantedLevel = 9600; + +// --MIAMI: File done except stats 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 +35,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 +45,12 @@ CWanted::Initialise() } bool +CWanted::AreMiamiViceRequired() +{ + return m_nWantedLevel >= 3; +} + +bool CWanted::AreSwatRequired() { return m_nWantedLevel == 4 || m_bSwatRequired; @@ -69,7 +80,7 @@ CWanted::NumOfHelisRequired() return 1; case 5: case 6: - return 2; + return 1; default: return 0; } @@ -87,22 +98,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 +124,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 +147,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 +182,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 +244,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,14 +290,25 @@ 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(); } +// TODO(Miami): Stats void CWanted::UpdateWantedLevel() { @@ -288,47 +317,41 @@ CWanted::UpdateWantedLevel() if (m_nChaos > nMaximumWantedLevel) m_nChaos = nMaximumWantedLevel; - if (m_nChaos >= 0 && m_nChaos < 40) { + if (m_nChaos >= 0 && m_nChaos < 50) { 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) { 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) { 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) { 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) { 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) { 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) { m_nWantedLevel = 6; m_MaximumLawEnforcerVehicles = 3; m_MaxCops = 10; - m_RoadblockDensity = 12; + m_RoadblockDensity = 30; } if (CurrWantedLevel != m_nWantedLevel) @@ -370,6 +393,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 +474,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 +481,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 +490,16 @@ CWanted::UpdateCrimesQ(void) } } } + +void +CWanted::Suspend(void) +{ + // TODO(Miami): Stats + // dwStarsEvaded += 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 de36c442..057b5407 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,12 +34,14 @@ public: public: void Initialise(); + bool AreMiamiViceRequired(); bool AreSwatRequired(); bool AreFbiRequired(); bool AreArmyRequired(); int32 NumOfHelisRequired(); void SetWantedLevel(int32); void SetWantedLevelNoDrop(int32 level); + 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(); @@ -48,6 +53,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 9f384048..7126b26f 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -50,6 +50,8 @@ bool CWorld::bProcessCutsceneOnly; bool CWorld::bDoingCarCollisions; bool CWorld::bIncludeCarTyres; +CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS]; + void CWorld::Initialise() { @@ -165,7 +167,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; @@ -184,7 +186,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 @@ -266,7 +268,7 @@ 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; @@ -274,39 +276,39 @@ CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoin 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; 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; } 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; @@ -320,7 +322,7 @@ 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; float mindist = dist; @@ -339,31 +341,15 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP 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 + 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, dist, - ignoreSeeThrough)) + ignoreSeeThrough, ignoreShootThrough)) entity = e; } } @@ -382,7 +368,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); } @@ -448,7 +438,7 @@ CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CCol colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, - ignoreSeeThrough, poly)) + ignoreSeeThrough, false, poly)) entity = e; } } @@ -649,7 +639,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; } } @@ -920,6 +910,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad bool ignoreSomeObjects) { static CColModel sphereCol; + CColSphere sphere; sphereCol.boundingSphere.center.x = 0.0f; sphereCol.boundingSphere.center.y = 0.0f; @@ -932,7 +923,8 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad sphereCol.boundingBox.max.y = radius; sphereCol.boundingBox.max.z = radius; sphereCol.numSpheres = 1; - sphereCol.spheres = &sphereCol.boundingSphere; + sphere.Set(radius, CVector(0.0f, 0.0f, 0.0f)); + sphereCol.spheres = &sphere; sphereCol.numLines = 0; sphereCol.numBoxes = 0; sphereCol.numTriangles = 0; @@ -949,11 +941,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) { @@ -1205,7 +1193,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, @@ -1265,7 +1253,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) @@ -1827,18 +1815,21 @@ 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) { + 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) || + IsLightThatNeedsRepositioning(modelId) + ) { CVector &position = pEntity->GetMatrix().GetPosition(); - float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; + 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 = CWorld::FindGroundZFor3DCoord(position.x, position.y, - position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - + position.z + fHeight, nil) - fBoundingBoxMinZ; pEntity->m_matrix.UpdateRW(); pEntity->UpdateRwFrame(); @@ -1925,6 +1916,7 @@ CWorld::Process(void) if(csObj && csObj->m_entryInfoList.first) { if(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP && RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) { +// TODO(MIAMI): doRender argument RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), 0.02f * (csObj->IsObject() ? CTimer::GetTimeStepNonClipped() @@ -1943,6 +1935,7 @@ CWorld::Process(void) CEntity *movingEnt = (CEntity *)node->item; if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { +// TODO(MIAMI): doRender argument RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), 0.02f * (movingEnt->IsObject() ? CTimer::GetTimeStepNonClipped() @@ -2045,9 +2038,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; @@ -2068,6 +2064,10 @@ CWorld::Process(void) movingPed->bInVehicle = false; movingPed->QuitEnteringCar(); } + } else if (movingPed->m_attachedTo) { + movingPed->PositionAttachedPed(); + movingPed->GetMatrix().UpdateRW(); + movingPed->UpdateRwFrame(); } } } @@ -2232,4 +2232,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 9465a914..8d539061 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -4,19 +4,19 @@ #include "Lists.h" #include "PlayerInfo.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) @@ -71,6 +71,7 @@ public: static bool bProcessCutsceneOnly; static bool bDoingCarCollisions; static bool bIncludeCarTyres; + static CColPoint m_aTempColPts[MAX_COLLISION_POINTS]; static void Remove(CEntity *entity); static void Add(CEntity *entity); @@ -90,9 +91,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); @@ -114,8 +115,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); @@ -125,6 +126,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); } diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index c376e11f..729cc35d 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -11,207 +11,22 @@ #include "ZoneCull.h" #include "Zones.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; - 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; -} - -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); -} - - -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{ -#if 0 - // TODO: implement code from mobile to generate data here - EntityIndicesUsed = 0; - BuildListForBigBuildings(); - pTempArrayIndices = new uint16[140000]; - TempEntityIndicesUsed = 0; - - for (int i = 0; i < NumCullZones; i++) { - DoVisibilityTestCullZone(i, true); - } - - CompressIndicesArray(); - delete[] pTempArrayIndices; - - 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 - } -} - -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*)((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->m_atomics[2]; - if (nonlod == nil) continue; - - for (int j = i; 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 doIt) -{ - 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 (!doIt) 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 *building2 = nil; - if (aPointersToBigBuildingsForBuildings[i] != -1) - building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]); - - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) { - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[0]++; - } - } - } - - for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CTreadable* building = CPools::GetTreadablePool()->GetSlot(i); - if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) { - CTreadable* building2 = nil; - if (aPointersToBigBuildingsForTreadables[i] != -1) - building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) { - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[1]++; - } - } - } - - for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) { - CTreadable *building = CPools::GetTreadablePool()->GetSlot(i); - if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < 40000.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++) { - if (aIndices[k] == i) - alreadyAdded = true; - } - - if (!alreadyAdded) { - CBuilding *building2 = nil; - if (aPointersToBigBuildingsForTreadables[i] != -1) - building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]); - if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) { - pTempArrayIndices[TempEntityIndicesUsed++] = i; - aZones[zoneId].m_groupIndexCount[2]++; - } - } - } - } } void @@ -219,14 +34,9 @@ CCullZones::Update(void) { bool invisible; - if(bCullZonesDisabled) - return; - switch(CTimer::GetFrameCounter() & 7){ case 0: case 4: - /* Update Cull zone */ - ForceCullZoneCoors(TheCamera.GetGameCamPosition()); break; case 2: @@ -250,28 +60,6 @@ CCullZones::Update(void) void CCullZones::ForceCullZoneCoors(CVector coors) { - int32 z; - z = FindCullZoneForCoors(coors); - if(z != OldCullZone){ - if(OldCullZone >= 0) - aZones[OldCullZone].DoStuffLeavingZone(); - if(z >= 0) - aZones[z].DoStuffEnteringZone(); - OldCullZone = z; - } -} - -int32 -CCullZones::FindCullZoneForCoors(CVector coors) -{ - int i; - - 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; } int32 @@ -346,219 +134,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; - // WTF is this? - 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; - } -} - - -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 < 6000){ - CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false; - bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; - }else{ - i -= 6000; - for(j = 0; j < 3; j++) - DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i) -{ - int16 bb; - int j; - - if(i < 6000){ - 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 -= 6000; - 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 < 6000){ - CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true; - bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; - }else{ - i -= 6000; - for(j = 0; j < 3; j++) - DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i) -{ - int16 bb; - int j; - - if(i < 6000){ - 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 -= 6000; - for(j = 0; j < 3; j++) - DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]); - } -} - -void -CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i) -{ - int16 bb; - int j; - - if(i < 6000){ - CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true; - bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; - if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; - }else{ - i -= 6000; - 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::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_isSubway) - lodDist = minfo->GetLargestLodDistance() + 30.0f; - else - lodDist = minfo->GetLargestLodDistance() + 50.0f; - - if (lodDist > distToZone) return true; - if (!checkLevel) return false; - CVector tempPos(minx, miny, minz); - return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&tempPos); -} - -bool -CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) -{ - int32 curCount; - int32 start; - int32 size; - - for (int i = 0; i < NumCullZones; i++) { - curCount = 0; - for (int group = 0; group < 3; group++) { - aZones[i].GetGroupStartAndSize(group, start, size); - - int unk = 0; // TODO: figure out - for (int j = 0; j < size; j++) { - for (int k = 0; k < 3; k++) { - if (set[k] == pTempArrayIndices[start+j]) - unk++; - } - } - if (unk == 3 && ++curCount >= count) - 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 9bc07b8c..aae06ca0 100644 --- a/src/core/ZoneCull.h +++ b/src/core/ZoneCull.h @@ -1,57 +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]; - 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 a1, CVector a2); - float CalcDistToCullZoneSquared(float x, float y); - float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); }; - bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel); - - void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) { - switch (groupid) { - case 1: - start = m_groupIndexCount[0] + m_indexStart; - size = m_groupIndexCount[1]; - break; - case 2: - start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart; - size = m_groupIndexCount[2]; - break; - default: - start = m_indexStart; - size = m_groupIndexCount[0]; - break; - } - } - - void FindTestPoints() {}; // todo - bool TestEntityVisibilityFromCullZone(CEntity*, float, CEntity*) { return false; }; // todo -}; - enum eZoneAttribs { ATTRZONE_CAMCLOSEIN = 1, @@ -62,6 +10,8 @@ enum eZoneAttribs ATTRZONE_NOTCULLZONE = 0x20, ATTRZONE_DOINEEDCOLLISION = 0x40, ATTRZONE_SUBWAYVISIBLE = 0x80, + + ATTRZONE_WATERFUDGE = 0x400, }; struct CAttributeZone @@ -79,27 +29,17 @@ 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 void Init(void); - static void ResolveVisibilities(void); static void Update(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); @@ -115,11 +55,9 @@ 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 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() {};// todo + //--MIAMI: TODO + static bool PoliceAbandonCars(void) { return false; } }; diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 1556731b..3095b36d 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -9,133 +9,138 @@ #include "World.h" 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]; +CZoneInfo CTheZones::ZoneInfoArray[2*NUMINFOZONES]; -#define SWAPF(a, b) { float t; t = a; a = b; b = t; } - -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; } +//--MIAMI: done wchar* CZone::GetTranslatedName(void) { return TheText.Get(name); } +//--MIAMI: done 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; } +//--MIAMI: done void CTheZones::Update(void) { CVector pos; pos = FindPlayerCoors(); - m_pPlayersZone = FindSmallestZonePosition(&pos); m_CurrLevel = GetLevelFromPosition(&pos); } +//--MIAMI: done void CTheZones::CreateZone(char *name, eZoneType type, float minx, float miny, float minz, 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); @@ -144,73 +149,94 @@ 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; + } } +//--MIAMI: done 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(); } +//--MIAMI: done, but does nothing +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); + } +} + +//--MIAMI: done void CTheZones::InsertZoneIntoZoneHierarchy(CZone *zone) { zone->child = nil; zone->parent = nil; zone->next = nil; - InsertZoneIntoZoneHierRecursive(zone, &ZoneArray[0]); + InsertZoneIntoZoneHierRecursive(zone, &NavigationZoneArray[0]); } +//--MIAMI: done bool CTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer) { @@ -254,6 +280,7 @@ CTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer) return true; } +//--MIAMI: done bool CTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer) { @@ -278,6 +305,7 @@ CTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer) return true; } +//--MIAMI: done bool CTheZones::PointLiesWithinZone(const CVector *v, CZone *zone) { @@ -286,6 +314,7 @@ CTheZones::PointLiesWithinZone(const CVector *v, CZone *zone) zone->minz <= v->z && v->z <= zone->maxz; } +//--MIAMI: done eLevelName CTheZones::GetLevelFromPosition(CVector const *v) { @@ -299,35 +328,35 @@ CTheZones::GetLevelFromPosition(CVector const *v) return MapZoneArray[0].level; } +//--MIAMI: done 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]; } +//--MIAMI: done 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 @@ -336,43 +365,73 @@ CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type) return best; } -CZone* -CTheZones::FindSmallestZonePositionILN(const CVector *v) +//--MIAMI: done +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; } +//--MIAMI: done 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; } +//--MIAMI: done 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]; @@ -383,6 +442,7 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info) { CZoneInfo *day, *night; float d, n; + int i; day = GetZoneInfo(pos, 1); night = GetZoneInfo(pos, 0); @@ -402,109 +462,60 @@ CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info) n = 1.0f - d; } 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; } 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 @@ -515,48 +526,59 @@ 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]; } +//--MIAMI: done, 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; } +//--MIAMI: done, 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; } +//--MIAMI: done 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; } +//--MIAMI: done int16 CTheZones::FindAudioZone(CVector *pos) { @@ -568,18 +590,7 @@ 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; -} - +//--MIAMI: done void CTheZones::AddZoneToAudioZoneArray(CZone *zone) { @@ -590,12 +601,14 @@ 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; } +//--MIAMI: done void CTheZones::InitialiseAudioZoneArray(void) { @@ -603,7 +616,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) @@ -627,6 +640,7 @@ CTheZones::InitialiseAudioZoneArray(void) } } +//--MIAMI: TODO void CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) { @@ -634,32 +648,39 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) int i; *size = SAVE_HEADER_SIZE - + sizeof(int32) // GetIndexForZonePointer + sizeof(m_CurrLevel) + sizeof(FindIndex) + sizeof(int16) // padding - + sizeof(ZoneArray) + sizeof(ZoneInfoArray) - + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray) + + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos) + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); - WriteSaveBuf(buffer, GetIndexForZonePointer(m_pPlayersZone)); WriteSaveBuf(buffer, m_CurrLevel); WriteSaveBuf(buffer, FindIndex); WriteSaveBuf(buffer, (int16)0); // padding - for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ - 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); +// TODO(MIAMI): implement SaveOneZone + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ + CZone *zone = WriteSaveBuf(buffer, NavigationZoneArray[i]); + zone->child = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].child); + zone->parent = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].parent); + zone->next = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].next); + } + + for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ + CZone *zone = WriteSaveBuf(buffer, InfoZoneArray[i]); + zone->child = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].child); + zone->parent = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].parent); + zone->next = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].next); } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) WriteSaveBuf(buffer, ZoneInfoArray[i]); - WriteSaveBuf(buffer, TotalNumberOfZones); + WriteSaveBuf(buffer, TotalNumberOfNavigationZones); + WriteSaveBuf(buffer, TotalNumberOfInfoZones); WriteSaveBuf(buffer, TotalNumberOfZoneInfos); for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { @@ -687,6 +708,7 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) VALIDATESAVEBUF(*size) } +//--MIAMI: TODO void CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { @@ -695,23 +717,32 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - m_pPlayersZone = GetPointerForZoneIndex(ReadSaveBuf<int32>(buffer)); m_CurrLevel = ReadSaveBuf<eLevelName>(buffer); FindIndex = ReadSaveBuf<int16>(buffer); ReadSaveBuf<int16>(buffer); - for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ - ZoneArray[i] = ReadSaveBuf<CZone>(buffer); +// TODO(MIAMI): implement LoadOneZone + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ + NavigationZoneArray[i] = ReadSaveBuf<CZone>(buffer); + + NavigationZoneArray[i].child = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].child); + NavigationZoneArray[i].parent = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].parent); + NavigationZoneArray[i].next = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].next); + } + + for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ + InfoZoneArray[i] = ReadSaveBuf<CZone>(buffer); - ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child); - ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent); - ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next); + InfoZoneArray[i].child = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].child); + InfoZoneArray[i].parent = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].parent); + InfoZoneArray[i].next = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].next); } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer); - TotalNumberOfZones = ReadSaveBuf<int16>(buffer); + TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer); + TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer); TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer); for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ diff --git a/src/core/Zones.h b/src/core/Zones.h index 6549dad5..8d5af182 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 &InfoZoneArray[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,9 +103,8 @@ 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(int32 i) { return i == -1 ? nil : &ZoneArray[i]; } - static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - ZoneArray; } + static CZone *GetPointerForZoneIndex(int32 i) { return i == -1 ? nil : &InfoZoneArray[i]; } + static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - InfoZoneArray; } static void AddZoneToAudioZoneArray(CZone *zone); static void InitialiseAudioZoneArray(void); static void SaveAllZones(uint8 *buffer, uint32 *length); diff --git a/src/core/common.h b/src/core/common.h index ebb3acb0..d22c1715 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -204,6 +204,7 @@ 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 #define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v)) diff --git a/src/core/config.h b/src/core/config.h index 94a35782..28dbe65d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -3,71 +3,75 @@ enum Config { 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, - TXDSTORESIZE = 850, - EXTRADIRSIZE = 128, + MODELINFOSIZE = 6500, + TXDSTORESIZE = 1385, + COLSTORESIZE = 31, + EXTRADIRSIZE = 256, CUTSCENEDIRSIZE = 512, - SIMPLEMODELSIZE = 5000, - MLOMODELSIZE = 1, - MLOINSTANCESIZE = 1, - TIMEMODELSIZE = 30, + SIMPLEMODELSIZE = 3885, + TIMEMODELSIZE = 385, CLUMPMODELSIZE = 5, - PEDMODELSIZE = 90, - VEHICLEMODELSIZE = 120, - XTRACOMPSMODELSIZE = 2, - TWODFXSIZE = 2000, + WEAPONMODELSIZE = 37, + PEDMODELSIZE = 130, + VEHICLEMODELSIZE = 110, + TWODFXSIZE = 1210, MAXVEHICLESLOADED = 50, // 70 on mobile - NUMOBJECTINFO = 168, // object.dat + NUMOBJECTINFO = 400, // TODO(MIAMI): fantasy // object.dat // 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 = 5400, // only 3200 in VC??? + NUMPEDS = 140, + NUMVEHICLES = 110, + NUMBUILDINGS = 7000, + NUMTREADABLES = 1214, // 1 in VC + NUMOBJECTS = 460, + NUMDUMMIES = 2802, // 2340 in VC + NUMAUDIOSCRIPTOBJECTS = 256, // 192 in VC + NUMCUTSCENEOBJECTS = 50, // does not exist in VC + // TODO(MIAMI): colmodel pool + + 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, @@ -84,7 +88,7 @@ enum Config { NUMSKIDMARKS = 32, NUMONSCREENTIMERENTRIES = 1, - NUMRADARBLIPS = 32, + NUMRADARBLIPS = 75, NUMGENERALPICKUPS = 320, NUMSCRIPTEDPICKUPS = 16, NUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS, @@ -92,7 +96,7 @@ enum Config { NUMPACMANPICKUPS = 256, NUMEVENTS = 64, - NUM_CARGENS = 160, + NUM_CARGENS = 185, NUM_PATH_NODES_IN_AUTOPILOT = 8, @@ -107,11 +111,12 @@ enum Config { NUMPEDROUTES = 200, NUMPHONES = 50, - NUMPEDGROUPS = 31, - NUMMODELSPERPEDGROUP = 8, + NUMPEDGROUPS = 67, + NUMMODELSPERPEDGROUP = 16, NUMSHOTINFOS = 100, - NUMROADBLOCKS = 600, + NUMROADBLOCKS = 300, + NUM_SCRIPT_ROADBLOCKS = 16, NUMVISIBLEENTITIES = 2000, NUMINVISIBLEENTITIES = 150, @@ -122,16 +127,19 @@ enum Config { NUM_SOUNDS_SAMPLES_BANKS = 2, NUM_SOUNDS_SAMPLES_SLOTS = 27, - 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_EXPLOSIONS = 48, + + NUM_SETPIECES = 96, + NUM_SHORTCUT_START_POINTS = 16 }; // We'll use this once we're ready to become independent of the game @@ -162,6 +170,7 @@ enum Config { #elif defined GTA_PC # define GTA3_1_1_PATCH //# define GTA3_STEAM_PATCH +//# define GTAVC_JP_PATCH # ifdef GTA_PS2_STUFF # define USE_PS2_RAND # define RANDOMSPLASH // use random splash as on PS2 @@ -191,8 +200,15 @@ enum Config { #endif #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more -#define MORE_LANGUAGES // Add more translations to the game +//#define MORE_LANGUAGES // Add more translations to the game #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible +#define FIX_HIGH_FPS_BUGS_ON_FRONTEND + +// 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 ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios @@ -200,14 +216,16 @@ enum Config { #define USE_TXD_CDIMAGE // generate and load textures from txd.img #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 +//#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time //#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL #define CUTSCENE_BORDERS_SWITCH -// Particle -//#define PC_PARTICLE +// Water & Particle +#define PC_PARTICLE //#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 +// #define PC_WATER +#define WATER_CHEATS // Pad #if !defined(RW_GL3) && defined(_WIN32) @@ -229,21 +247,19 @@ enum Config { # define PS2_MENU //# define PS2_MENU_USEALLPAGEICONS #else -# define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box //# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. -# define MENU_MAP // VC-like menu map. Make sure you have new menu.txd -# define SCROLLABLE_STATS_PAGE // only draggable by mouse atm +# define MAP_ENHANCEMENTS // Adding waypoint etc. # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON -# define CUSTOM_FRONTEND_OPTIONS -#endif +//#define CUSTOM_FRONTEND_OPTIONS +#define LEGACY_MENU_OPTIONS +#define MUCH_SHORTER_OUTRO_SCREEN // Script #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 -#ifdef PC_MENU -# define MISSION_REPLAY // mobile feature +//#define MISSION_REPLAY // mobile feature #endif //#define SIMPLIER_MISSIONS // apply simplifications from mobile #define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT @@ -259,7 +275,7 @@ enum Config { // 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 @@ -268,13 +284,11 @@ enum Config { // Peds #define PED_SKIN // support for skinned geometry on peds #define ANIMATE_PED_COL_MODEL -// #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle +#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 // 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 diff --git a/src/core/main.cpp b/src/core/main.cpp index a1c64a6d..d4ef8c4b 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -61,6 +61,8 @@ #include "MemoryCard.h" #include "SceneEdit.h" #include "debugmenu.h" +#include "Occlusion.h" +#include "Ropes.h" GlobalScene Scene; @@ -85,7 +87,7 @@ RwRGBA gColourTop; bool gameAlreadyInitialised; float NumberOfChunksLoaded; -#define TOTALNUMCHUNKS 73.0f +#define TOTALNUMCHUNKS 95.0f bool g_SlowMode = false; char version_name[64]; @@ -140,11 +142,8 @@ 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, rwCAMERACLEARZ); @@ -162,11 +161,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, rwCAMERACLEARZ); @@ -223,13 +219,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) @@ -254,22 +250,17 @@ DoFade(void) fadeColor.a = alpha; } + // This is CCamera::GetScreenRect in VC 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 + rect.top = y - SCREEN_SCALE_Y(22.0f); + rect.bottom = SCREEN_HEIGHT - y - SCREEN_SCALE_Y(14.0f); }else{ rect.left = 0.0f; rect.right = SCREEN_WIDTH; @@ -314,7 +305,12 @@ PluginAttach(void) return FALSE; } - +#ifndef LIBRW + if (!RtAnimInitialize()) + { + return FALSE; + } +#endif if( !RpHAnimPluginAttach() ) { printf("Couldn't attach RpHAnim plugin\n"); @@ -384,6 +380,7 @@ Terminate3D(void) CSprite2d splash; int splashTxdId = -1; +//--MIAMI: done CSprite2d* LoadSplash(const char *name) { @@ -429,22 +426,23 @@ DestroySplashScreen(void) splashTxdId = -1; } +//--MIAMI: done Const char* 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; @@ -471,6 +469,7 @@ ResetLoadingScreenBar() NumberOfChunksLoaded = 0.0f; } +//--MIAMI: done void LoadingScreen(const char *str1, const char *str2, const char *splashscreen) { @@ -482,10 +481,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); @@ -506,36 +502,50 @@ 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; AsciiToUnicode(str2, tmpstr); - CFont::PrintString(hpos, vpos, tmpstr); + CFont::PrintString(hpos, top, tmpstr); #endif } @@ -708,11 +718,13 @@ DisplayGameDebugText() { static bool bDisplayPosn = false; static bool bDisplayRate = false; + static bool bDisplayCheatStr = false; { SETTWEAKPATH("GameDebugText"); TWEAKBOOL(bDisplayPosn); TWEAKBOOL(bDisplayRate); + TWEAKBOOL(bDisplayCheatStr); } @@ -724,7 +736,7 @@ DisplayGameDebugText() CFont::SetPropOn(); CFont::SetBackgroundOff(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_STANDARD); CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.5f)); CFont::SetCentreOff(); CFont::SetRightJustifyOff(); @@ -800,6 +812,26 @@ DisplayGameDebugText() CFont::SetColor(CRGBA(255, 108, 0, 255)); CFont::PrintString(40.0f, 40.0f, ustr); } + + if (bDisplayCheatStr) + { + sprintf(str, "%s", CPad::KeyBoardCheatString); + AsciiToUnicode(str, ustr); + + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(0.7f, 1.5f); + CFont::SetCentreOn(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetWrapx(640.0f); + CFont::SetFontStyle(FONT_HEADING); + + 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 @@ -810,14 +842,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(); - CRenderer::RenderVehiclesButNotBoats(); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); CWeather::RenderRainStreaks(); + // CCoronas::RenderSunReflection } void @@ -839,6 +874,7 @@ RenderEffects(void) CGlass::Render(); CWaterCannons::Render(); CSpecialFX::Render(); + CRopes::Render(); CShadows::RenderStaticShadows(); CShadows::RenderStoredShadows(); CSkidmarks::Render(); @@ -915,6 +951,7 @@ Render2dStuff(void) CGarages::PrintMessages(); CPad::PrintErrorMessage(); CFont::DrawFonts(); + COcclusion::Render(); #ifdef DEBUGMENU DebugMenuRender(); @@ -945,15 +982,12 @@ Render2dStuffAfterFade(void) CHud::DrawAfterFade(); CFont::DrawFonts(); + CCredits::Render(); } void Idle(void *arg) { -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif - CTimer::Update(); #ifdef TIMEBARS @@ -963,35 +997,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 { - CPointLights::InitPerFrame(); -#ifdef TIMEBARS - tbStartTimer(0, "CGame::Process"); -#endif - CGame::Process(); -#ifdef TIMEBARS - tbEndTimer("CGame::Process"); - tbStartTimer(0, "DMAudio.Service"); -#endif - DMAudio.Service(); - -#ifdef TIMEBARS - tbEndTimer("DMAudio.Service"); -#endif - } - - if (RsGlobal.quit) - return; -#else CPointLights::InitPerFrame(); #ifdef TIMEBARS tbStartTimer(0, "CGame::Process"); @@ -1007,7 +1012,6 @@ Idle(void *arg) #ifdef TIMEBARS tbEndTimer("DMAudio.Service"); #endif -#endif if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ #ifdef PS2_MENU @@ -1034,21 +1038,23 @@ Idle(void *arg) if(arg == nil) return; - if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && + // m_bRenderGameInMenu is there in III PS2 but I don't know about VC PS2. + if((!FrontEndMenuManager.m_bMenuActive/* || FrontEndMenuManager.m_bRenderGameInMenu*/) && TheCamera.GetScreenFadeStatus() != FADE_2) { #ifdef GTA_PC - if (!FrontEndMenuManager.m_bRenderGameInMenu) { // This is from SA, but it's nice for windowed mode RwV2d pos; pos.x = SCREEN_WIDTH / 2.0f; pos.y = SCREEN_HEIGHT / 2.0f; RsMouseSetPos(&pos); - } #endif #ifdef TIMEBARS tbStartTimer(0, "CnstrRenderList"); #endif +#ifdef PC_WATER + CWaterLevel::PreCalcWaterGeometry(); +#endif CRenderer::ConstructRenderList(); #ifdef TIMEBARS tbEndTimer("CnstrRenderList"); @@ -1101,6 +1107,7 @@ Idle(void *arg) tbEndTimer("Render2dStuff"); #endif }else{ + CDraw::CalculateAspectRatio(); #ifdef ASPECT_RATIO_SCALE CameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO); #else @@ -1112,10 +1119,6 @@ Idle(void *arg) return; } -#ifdef PS2_SAVE_DIALOG - if (FrontEndMenuManager.m_bMenuActive) - DefinedState(); -#endif #ifdef TIMEBARS tbStartTimer(0, "RenderMenus"); #endif @@ -1138,7 +1141,7 @@ Idle(void *arg) #ifdef TIMEBARS tbEndTimer("Render2dStuff-Fade"); #endif - CCredits::Render(); + // CCredits::Render(); // They added it to function above and also forgot it here #ifdef TIMEBARS @@ -1155,10 +1158,7 @@ Idle(void *arg) 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(); @@ -1169,11 +1169,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, rwCAMERACLEARZ); if(!RsCameraBeginUpdate(Scene.camera)) @@ -1183,7 +1179,7 @@ FrontendIdle(void) RenderMenus(); DoFade(); Render2dStuffAfterFade(); -// CFont::DrawFonts(); // redundant + CFont::DrawFonts(); DoRWStuffEndOfFrame(); } @@ -1191,7 +1187,7 @@ void InitialiseGame(void) { LoadingScreen(nil, nil, "loadsc0"); - CGame::Initialise("DATA\\GTA3.DAT"); + CGame::Initialise("DATA\\GTA_VC.DAT"); } RsEventStatus @@ -1254,11 +1250,7 @@ AppEventHandler(RsEvent event, void *param) case rsFRONTENDIDLE: { -#ifdef PS2_SAVE_DIALOG - Idle((void*)1); -#else FrontendIdle(); -#endif return rsEVENTPROCESSED; } @@ -1293,14 +1285,13 @@ TheModelViewer(void) #if (defined(GTA_PS2) || defined(GTA_XBOX)) //TODO #else -#ifdef ASPECT_RATIO_SCALE - CDraw::SetAspectRatio(CDraw::FindAspectRatio()); -#endif + + CDraw::CalculateAspectRatio(); 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); @@ -1345,9 +1336,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(); } @@ -1421,7 +1412,8 @@ void TheGame(void) gMainHeap.PushMemId(_TODOCONST(15)); #endif - if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 ) + // m_bRenderGameInMenu is there in III PS2 but I don't know about VC PS2. + if (!FrontEndMenuManager.m_bMenuActive || /*FrontEndMenuManager.m_bRenderGameInMenu == true && */TheCamera.GetScreenFadeStatus() != FADE_2 ) { #ifdef GTA_PS2 gMainHeap.PushMemId(_TODOCONST(11)); @@ -1628,30 +1620,30 @@ void SystemInit() CGame::frenchGame = false; CGame::germanGame = false; CGame::nastyGame = true; - CMenuManager::m_PrefsAllowNastyGame = true; + FrontEndMenuManager.m_PrefsAllowNastyGame = true; #ifdef GTA_PS2 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 diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 8c0020d0..81b2bfc0 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -3,6 +3,7 @@ #include "common.h" #include "crossplatform.h" #include "Renderer.h" +#include "Occlusion.h" #include "Credits.h" #include "Camera.h" #include "Weather.h" @@ -15,6 +16,7 @@ #include "Boat.h" #include "Heli.h" #include "Automobile.h" +#include "Bike.h" #include "Ped.h" #include "Particle.h" #include "Console.h" @@ -29,6 +31,7 @@ #include "Text.h" #include "WaterLevel.h" #include "main.h" +#include "Script.h" #ifndef _WIN32 #include "assert.h" @@ -158,11 +161,6 @@ CustomFrontendOptionsPopulate(void) FrontendOptionAddSelect(TheText.Get("SCRFOR"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); #endif -#ifdef MENU_MAP - FrontendOptionSetPosition(MENUPAGE_PAUSE_MENU, 2); - FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP); -#endif - #ifdef FREE_CAM static const wchar *text = (wchar*)L"TOGGLE FREE CAM"; FrontendOptionSetPosition(MENUPAGE_CONTROLLER_PC, 1); @@ -178,9 +176,11 @@ CustomFrontendOptionsPopulate(void) #endif #ifdef DEBUGMENU -void WeaponCheat(); +void WeaponCheat1(); +void WeaponCheat2(); +void WeaponCheat3(); void HealthCheat(); -void TankCheat(); +void VehicleCheat(bool something, int model); void BlowUpCarsCheat(); void ChangePlayerCheat(); void MayhemCheat(); @@ -223,6 +223,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); @@ -252,13 +254,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) { @@ -316,12 +320,27 @@ ResetCamStatics(void) TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; } +#ifdef MISSION_SWITCHER +int8 nextMissionToSwitch = 0; +static void +SwitchToMission(void) +{ + CTheScripts::SwitchToMission(nextMissionToSwitch); +} +#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" }; static CTweakVar** TweakVarsList; @@ -385,7 +404,7 @@ DebugMenuPopulate(void) { if(1){ static const char *weathers[] = { - "Sunny", "Cloudy", "Rainy", "Foggy" + "Sunny", "Cloudy", "Rainy", "Foggy", "Extrasunny", "Stormy" }; DebugMenuEntry *e; e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil); @@ -393,19 +412,21 @@ 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, nil, 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, nil, 1, 0, 5, weathers); DebugMenuEntrySetWrap(e, true); DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f); 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(true, MI_TAXI); }); DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat); DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat); DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat); @@ -425,14 +446,12 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Cheats", "Nasty limbs", NastyLimbsCheat); 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); }); @@ -442,32 +461,44 @@ 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); + DebugMenuAddVarBool8("Render", "Backface Culling", &gBackfaceCulling, nil); #ifdef LIBRW DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil); #endif DebugMenuAddVarBool8("Render", "Frame limiter", &FrontEndMenuManager.m_PrefsFrameLimiter, nil); DebugMenuAddVarBool8("Render", "VSynch", &FrontEndMenuManager.m_PrefsVsync, nil); DebugMenuAddVar("Render", "Max FPS", &RsGlobal.maxFPS, nil, 1, 1, 1000, nil); + DebugMenuAddVarBool8("Render", "Occlusion debug", &bDisplayOccDebugStuff, nil); DebugMenuAddVarBool8("Render", "Show Ped Paths", &gbShowPedPaths, nil); DebugMenuAddVarBool8("Render", "Show Car Paths", &gbShowCarPaths, nil); DebugMenuAddVarBool8("Render", "Show Car Path Links", &gbShowCarPathsLinks, nil); - DebugMenuAddVarBool8("Render", "Show Ped Road Groups", &gbShowPedRoadGroups, nil); - DebugMenuAddVarBool8("Render", "Show Car Road Groups", &gbShowCarRoadGroups, nil); DebugMenuAddVarBool8("Render", "Show Collision Lines", &gbShowCollisionLines, nil); DebugMenuAddVarBool8("Render", "Show Collision Polys", &gbShowCollisionPolys, nil); DebugMenuAddVarBool8("Render", "Don't render Buildings", &gbDontRenderBuildings, nil); @@ -479,7 +510,7 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil); DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); #endif DebugMenuAddCmd("Debug", "Switch car collision", SwitchCarCollision); @@ -489,24 +520,25 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Toggle Comedy Controls", ToggleComedy); DebugMenuAddCmd("Debug", "Place Car on Road", PlaceOnRoad); - DebugMenuAddVarBool8("Debug", "Catalina Heli On", &CHeli::CatalinaHeliOn, nil); - DebugMenuAddCmd("Debug", "Catalina Fly By", CHeli::StartCatalinaFlyBy); - DebugMenuAddCmd("Debug", "Catalina Take Off", CHeli::CatalinaTakeOff); - DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil); #ifdef CUSTOM_FRONTEND_OPTIONS DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions); #endif - DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); +#ifdef RELOADABLES + DebugMenuAddCmd("Reload", "HUD.TXD", CHud::ReloadTXD); +#endif DebugMenuAddVarBool8("Debug", "Show DebugStuffInRelease", &gbDebugStuffInRelease, nil); #ifdef TIMEBARS DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil); #endif - +#ifdef MISSION_SWITCHER + DebugMenuAddInt8("Debug", "Select mission no", &nextMissionToSwitch, nil, 1, 0, 96, nil); + DebugMenuAddCmd("Debug", "Start selected mission ", SwitchToMission); +#endif extern bool PrintDebugCode; extern int16 DebugCamMode; DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil); @@ -516,9 +548,6 @@ DebugMenuPopulate(void) 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"); diff --git a/src/core/templates.h b/src/core/templates.h index 4f7b8490..465e3bef 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -44,18 +44,20 @@ class CPool int m_allocPtr; public: + // TODO(MIAMI): remove ctor without name argument CPool(int size){ // TODO: use new here m_entries = (U*)malloc(sizeof(U)*size); m_flags = (Flags*)malloc(sizeof(Flags)*size); m_size = size; - m_allocPtr = 0; + m_allocPtr = -1; for(int i = 0; i < size; i++){ m_flags[i].id = 0; m_flags[i].free = 1; } } - + CPool(int size, const char *name) + : CPool(size) {} ~CPool() { Flush(); } @@ -131,7 +133,7 @@ public: // TODO: the cast is unsafe return (int)((U*)entry - m_entries); } - int GetNoOfUsedSpaces(void) const{ + int GetNoOfUsedSpaces(void) const { int i; int n = 0; for(i = 0; i < m_size; i++) @@ -162,6 +164,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 6b841a5c..884feffd 100644 --- a/src/core/timebars.cpp +++ b/src/core/timebars.cpp @@ -92,7 +92,7 @@ void tbDisplay() CFont::SetWrapx(640.0f); 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)); |