#include "common.h" #include "main.h" #include "Draw.h" #include "World.h" #include "Vehicle.h" #include "Train.h" #include "Automobile.h" #include "Ped.h" #include "PlayerPed.h" #include "Wanted.h" #include "Pad.h" #include "ControllerConfig.h" #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" #include "DMAudio.h" #include "FileMgr.h" #include "Frontend.h" #include "SceneEdit.h" #include "Pools.h" #include "Debug.h" #include "GenericGameStorage.h" #include "Camera.h" enum { // car OBBE_WHEEL, OBBE_1, OBBE_2, OBBE_3, OBBE_1STPERSON, // unused OBBE_5, OBBE_ONSTRING, OBBE_COPCAR, OBBE_COPCAR_WHEEL, // ped OBBE_9, OBBE_10, OBBE_11, OBBE_12, OBBE_13, // heli OBBE_14, OBBE_15, OBBE_16, OBBE_17, OBBE_18, OBBE_19, OBBE_ONSTRING_HELI, OBBE_INVALID }; // abbreviate a few things #define PLAYER (CWorld::Players[CWorld::PlayerInFocus].m_pPed) // NB: removed explicit TheCamera from all functions CCamera TheCamera; #ifdef PC_PLAYER_CONTROLS bool CCamera::m_bUseMouse3rdPerson = true; #else bool CCamera::m_bUseMouse3rdPerson = false; #endif bool bDidWeProcessAnyCinemaCam; static bool bSwitchedToObbeCam; float CCamera::m_fMouseAccelHorzntl; float CCamera::m_fMouseAccelVertical; float CCamera::m_f3rdPersonCHairMultX; float CCamera::m_f3rdPersonCHairMultY; #ifdef IMPROVED_CAMERA #define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) #define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k) #define CTRLJUSTDOWN(key) \ ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \ (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) #define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) #endif 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 CCamera::CCamera(void) { Init(); } void CCamera::Init(void) { 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; m_bFreezePedZoomSwitch = false; Cams[0].Init(); Cams[1].Init(); Cams[2].Init(); Cams[0].Mode = CCam::MODE_FOLLOWPED; Cams[1].Mode = CCam::MODE_FOLLOWPED; 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; Cams[0].CamTargetEntity = nil; Cams[1].CamTargetEntity = nil; Cams[2].CamTargetEntity = nil; Cams[0].m_fCamBufferedHeight = 0.0f; Cams[0].m_fCamBufferedHeightSpeed = 0.0f; Cams[1].m_fCamBufferedHeight = 0.0f; Cams[1].m_fCamBufferedHeightSpeed = 0.0f; Cams[0].m_bCamLookingAtVector = false; Cams[1].m_bCamLookingAtVector = false; Cams[2].m_bCamLookingAtVector = false; Cams[0].m_fPlayerVelocity = 0.0f; Cams[1].m_fPlayerVelocity = 0.0f; Cams[2].m_fPlayerVelocity = 0.0f; m_bHeadBob = false; m_fFractionInterToStopMoving = 0.25f; m_fFractionInterToStopCatchUp = 0.75f; m_fGaitSwayBuffer = 0.85f; m_bScriptParametersSetForInterPol = false; m_uiCamShakeStart = 0; m_fCamShakeForce = 0.0f; m_iModeObbeCamIsInForCar = OBBE_INVALID; m_bIgnoreFadingStuffForMusic = false; m_bWaitForInterpolToFinish = false; pToGarageWeAreIn = nil; pToGarageWeAreInForHackAvoidFirstPerson = nil; m_bPlayerIsInGarage = false; m_bJustCameOutOfGarage = false; m_fNearClipScript = DEFAULT_NEAR; m_bUseNearClipScript = false; m_vecDoingSpecialInterPolation = false; m_bAboveGroundTrainNodesLoaded = false; m_bBelowGroundTrainNodesLoaded = false; m_WideScreenOn = false; m_fFOV_Wide_Screen = 0.0f; m_bRestoreByJumpCut = false; CarZoomIndicator = CAM_ZOOM_2; PedZoomIndicator = CAM_ZOOM_2; CarZoomValueSmooth = 0.0f; m_fPedZoomValueSmooth = 0.0f; pTargetEntity = nil; if(FindPlayerVehicle()) pTargetEntity = FindPlayerVehicle(); else pTargetEntity = CWorld::Players[CWorld::PlayerInFocus].m_pPed; m_bInitialNodeFound = false; m_ScreenReductionPercentage = 0.0f; m_ScreenReductionSpeed = 0.0f; m_WideScreenOn = false; m_bWantsToSwitchWidescreenOff = false; WorldViewerBeingUsed = false; PlayerExhaustion = 1.0f; DebugCamMode = CCam::MODE_NONE; m_PedOrientForBehindOrInFront = 0.0f; 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; } if(FrontEndMenuManager.m_bWantToRestart) m_fTimeToFadeMusic = 0.0f; m_bStartingSpline = false; m_iTypeOfSwitch = INTERPOLATION; m_bUseScriptZoomValuePed = false; m_bUseScriptZoomValueCar = false; m_fPedZoomValueScript = 0.0f; m_fCarZoomValueScript = 0.0f; m_bUseSpecialFovTrain = false; m_fFovForTrain = 70.0f; // or DefaultFOV from Cam.cpp m_iModeToGoTo = CCam::MODE_FOLLOWPED; m_bJust_Switched = false; m_bUseTransitionBeta = false; m_matrix.SetScale(1.0f); m_bTargetJustBeenOnTrain = false; m_bInitialNoNodeStaticsSet = false; m_uiLongestTimeInMill = 5000; 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; m_motionBlur = 0; m_bGarageFixedCamPositionSet = false; SetMotionBlur(255, 255, 255, 0, 0); m_bCullZoneChecksOn = false; m_bFailedCullZoneTestPreviously = false; m_iCheckCullZoneThisNumFrames = 6; m_iZoneCullFrameNumWereAt = 0; m_CameraAverageSpeed = 0.0f; m_CameraSpeedSoFar = 0.0f; m_PreviousCameraPosition = CVector(0.0f, 0.0f, 0.0f); m_iWorkOutSpeedThisNumFrames = 4; m_iNumFramesSoFar = 0; m_bJustInitalised = true; m_uiTransitionState = 0; m_uiTimeTransitionStart = 0; m_bLookingAtPlayer = true; 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 float PlayerMinDist = 1.3f; static bool WasPreviouslyInterSyhonFollowPed = false; // only written float FOV = 0.0f; float oldBeta, newBeta; float deltaBeta = 0.0f; bool lookLRBVehicle = false; CVector CamFront, CamUp, CamRight, CamSource, Target; m_bJust_Switched = false; m_RealPreviousCameraPosition = GetPosition(); // Update target entity if(m_bLookingAtPlayer || m_bTargetJustBeenOnTrain || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) UpdateTargetEntity(); if(pTargetEntity == nil) pTargetEntity = FindPlayerPed(); if(Cams[ActiveCam].CamTargetEntity == nil) Cams[ActiveCam].CamTargetEntity = pTargetEntity; if(Cams[(ActiveCam+1)%2].CamTargetEntity == nil) Cams[(ActiveCam+1)%2].CamTargetEntity = pTargetEntity; CamControl(); if(m_bFading) ProcessFade(); if(m_bMusicFading) ProcessMusicFade(); if(m_WideScreenOn) ProcessWideScreenOn(); #ifndef MASTER #ifdef IMPROVED_CAMERA if(CPad::GetPad(1)->GetCircleJustDown() || CTRLJUSTDOWN('B')){ #else if(CPad::GetPad(1)->GetCircleJustDown()){ #endif WorldViewerBeingUsed = !WorldViewerBeingUsed; if(WorldViewerBeingUsed) InitialiseCameraForDebugMode(); else CPad::m_bMapPadOneToPadTwo = false; } #endif RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR); if(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f) oldBeta = 0.0f; else oldBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); Cams[ActiveCam].Process(); Cams[ActiveCam].ProcessSpecialHeightRoutines(); if(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f) newBeta = 0.0f; else newBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); // 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; } } if(m_bUseNearClipScript) RwCameraSetNearClipPlane(Scene.camera, m_fNearClipScript); deltaBeta = newBeta - oldBeta; while(deltaBeta >= PI) deltaBeta -= 2*PI; while(deltaBeta < -PI) deltaBeta += 2*PI; if(Abs(deltaBeta) > 0.3f) m_bJust_Switched = true; #ifndef MASTER // Debug stuff if(!gbModelViewer) 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 uint32 currentTime = CTimer::GetTimeInMilliseconds() - m_uiTimeTransitionStart; if(currentTime >= m_uiTransitionDuration) currentTime = m_uiTransitionDuration; float fractionInter = (float) currentTime / m_uiTransitionDuration; float fractionInterTarget = (float) currentTime / m_uiTransitionDurationTargetCoors; fractionInterTarget = clamp(fractionInterTarget, 0.0f, 1.0f); // Interpolate target separately if(fractionInterTarget <= m_fFractionInterToStopMovingTarget){ float inter; if(m_fFractionInterToStopMovingTarget == 0.0f) inter = 0.0f; else inter = (m_fFractionInterToStopMovingTarget - fractionInterTarget)/m_fFractionInterToStopMovingTarget; inter = 0.5f - 0.5*Cos(inter*PI); // smooth it 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 if(m_fFractionInterToStopMovingTarget == 0.0f) m_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol; Target = m_vecTargetWhenInterPol + inter*(Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - m_vecTargetWhenInterPol); } if(fractionInter <= m_fFractionInterToStopMoving){ float inter; if(m_fFractionInterToStopMoving == 0.0f) inter = 0.0f; else inter = (m_fFractionInterToStopMoving - fractionInter)/m_fFractionInterToStopMoving; inter = 0.5f - 0.5*Cos(inter*PI); // smooth it m_vecSourceWhenInterPol = m_cvecStartingSourceForInterPol + inter*m_cvecSourceSpeedAtStartInter; 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); } } 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); CamFront.Normalise(); if(m_bLookingAtPlayer) CamUp = CVector(0.0f, 0.0f, 1.0f); else CamUp = m_vecUpWhenInterPol; CamUp.Normalise(); if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ CamFront.Normalise(); CamRight = CVector(-1.0f, 0.0f, 0.0f); CamUp = CrossProduct(CamFront, CamRight); CamUp.Normalise(); }else{ CamFront.Normalise(); CamUp.Normalise(); CamRight = CrossProduct(CamFront, CamUp); CamRight.Normalise(); CamUp = CrossProduct(CamRight, CamFront); CamUp.Normalise(); } FOV = m_fFOVWhenInterPol; }else if(fractionInter > m_fFractionInterToStopMoving && fractionInter <= 1.0f){ float inter; if(m_fFractionInterToStopCatchUp == 0.0f) inter = 0.0f; else inter = (fractionInter - m_fFractionInterToStopMoving)/m_fFractionInterToStopCatchUp; 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); CamUp = m_vecUpWhenInterPol + inter*(Cams[ActiveCam].Up - m_vecUpWhenInterPol); deltaBeta = Cams[ActiveCam].m_fTrueBeta - m_fBetaWhenInterPol; MakeAngleLessThan180(deltaBeta); CamFront = Target - CamSource; StoreValuesDuringInterPol(CamSource, Target, CamUp, FOV); CamFront.Normalise(); if(m_bLookingAtPlayer) CamUp = CVector(0.0f, 0.0f, 1.0f); if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ CamFront.Normalise(); CamRight = CVector(-1.0f, 0.0f, 0.0f); CamUp = CrossProduct(CamFront, CamRight); CamUp.Normalise(); }else{ CamFront.Normalise(); CamUp.Normalise(); CamRight = CrossProduct(CamFront, CamUp); CamRight.Normalise(); CamUp = CrossProduct(CamRight, CamFront); CamUp.Normalise(); } #ifndef FIX_BUGS // BUG: FOV was already interpolated but m_fFOVWhenInterPol was not FOV = m_fFOVWhenInterPol; #endif } CVector Dist = CamSource - Target; float DistOnGround = Dist.Magnitude2D(); float Alpha = CGeneral::GetATanOfXY(DistOnGround, Dist.z); float Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y); Cams[ActiveCam].KeepTrackOfTheSpeed(CamSource, Target, CamUp, Alpha, Beta, FOV); }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 #endif { CamSource = Cams[ActiveCam].Source; 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; // unused } if(m_uiTransitionState != 0) if(!m_bLookingAtVector && m_bLookingAtPlayer && !CCullZones::CamStairsForPlayer() && !m_bPlayerIsInGarage){ CEntity *entity = nil; CColPoint colPoint; if(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), CamSource, colPoint, entity, true, false, false, true, false, true, true)){ CamSource = colPoint.point; RwCameraSetNearClipPlane(Scene.camera, 0.05f); } } if(CMBlur::Drunkness > 0.0f){ static float DrunkAngle; int tableIndex = (int)(DEGTORAD(DrunkAngle)/TWOPI * CParticle::SIN_COS_TABLE_SIZE) & CParticle::SIN_COS_TABLE_SIZE-1; DrunkAngle += 5.0f; #ifndef FIX_BUGS // This just messes up interpolation, probably not what they intended // and multiplying the interpolated FOV is also a bit extreme // so let's not do any of this nonsense Cams[ActiveCam].FOV *= (1.0f + CMBlur::Drunkness); #endif CamSource.x += -0.02f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; CamSource.y += -0.02f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; CamUp.Normalise(); CamUp.x += 0.05f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; CamUp.y += 0.05f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; CamUp.Normalise(); CamFront.Normalise(); CamFront.x += -0.1f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex]; CamFront.y += -0.1f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex]; CamFront.Normalise(); CamRight = CrossProduct(CamFront, CamUp); CamRight.Normalise(); CamUp = CrossProduct(CamRight, CamFront); CamUp.Normalise(); } GetMatrix().GetRight() = CrossProduct(CamUp, CamFront); // actually Left GetMatrix().GetForward() = CamFront; GetMatrix().GetUp() = CamUp; GetMatrix().GetPosition() = CamSource; // Process Shake float shakeStrength = m_fCamShakeForce - 0.28f*(CTimer::GetTimeInMilliseconds()-m_uiCamShakeStart)/1000.0f; shakeStrength = clamp(shakeStrength, 0.0f, 2.0f); int shakeRand = CGeneral::GetRandomNumber(); float shakeOffset = shakeStrength*0.1f; GetMatrix().GetPosition().x += shakeOffset * ((shakeRand & 0xF) - 7); GetMatrix().GetPosition().y += shakeOffset * (((shakeRand & 0xF0) >> 4) - 7); GetMatrix().GetPosition().z += shakeOffset * (((shakeRand & 0xF00) >> 8) - 7); if(shakeOffset > 0.0f && m_BlurType != MOTION_BLUR_SNIPER) SetMotionBlurAlpha(Min((int)(shakeStrength*255.0f) + 25, 150)); 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; CVector Front = Cams[2].Front; CVector Up = Cams[2].Up; GetMatrix().GetRight() = CrossProduct(Up, Front); GetMatrix().GetForward() = Front; GetMatrix().GetUp() = Up; GetMatrix().GetPosition() = Source; CDraw::SetFOV(Cams[2].FOV); m_vecGameCamPos = Cams[ActiveCam].Source; *RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition(); *RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward(); *RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp(); *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); }else #endif { RwFrame *frame = RwCameraGetFrame(m_pRwCamera); m_vecGameCamPos = GetPosition(); *RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition(); *RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward(); *RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp(); *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); RwFrameOrthoNormalize(frame); } UpdateSoundDistances(); if((CTimer::GetFrameCounter()&0xF) == 3) DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y); // LOD dist if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){ LODDistMultiplier = 70.0f/CDraw::GetFOV(); 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; 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){ m_PreviousCameraPosition = GetPosition(); m_bJustInitalised = false; } m_CameraSpeedSoFar += (GetPosition() - m_PreviousCameraPosition).Magnitude(); m_iNumFramesSoFar++; if(m_iNumFramesSoFar == m_iWorkOutSpeedThisNumFrames){ m_CameraAverageSpeed = m_CameraSpeedSoFar / m_iWorkOutSpeedThisNumFrames; m_CameraSpeedSoFar = 0.0f; m_iNumFramesSoFar = 0; } m_PreviousCameraPosition = GetPosition(); if(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED){ Cams[ActiveCam].Source = Cams[ActiveCam].SourceBeforeLookBehind; Orientation += PI; } if(m_uiTransitionState != 0){ int OtherCam = (ActiveCam+1)%2; if(Cams[OtherCam].CamTargetEntity && pTargetEntity && pTargetEntity->IsPed() && !Cams[OtherCam].CamTargetEntity->IsVehicle() && Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD){ Cams[OtherCam].Source = Cams[ActiveCam%2].SourceBeforeLookBehind; Orientation += PI; } } m_bCameraJustRestored = false; m_bMoveCamToAvoidGeom = false; } void CCamera::CamControl(void) { static bool PlaceForFixedWhenSniperFound = false; static int16 ReqMode; bool switchByJumpCut = false; bool stairs = false; bool boatTarget = false; int PrevMode = Cams[ActiveCam].Mode; CVector targetPos; CVector garageCenter, garageDoorPos1, garageDoorPos2; CVector garageCenterToDoor, garageCamPos; int whichDoor; m_bObbeCinematicPedCamOn = false; m_bObbeCinematicCarCamOn = false; m_bUseTransitionBeta = false; m_bUseSpecialFovTrain = false; m_bJustCameOutOfGarage = false; m_bTargetJustCameOffTrain = false; m_bInATunnelAndABigVehicle = false; m_bJustJumpedOutOf1stPersonBecauseOfTarget = false; bSwitchedToObbeCam = false; if(Cams[ActiveCam].CamTargetEntity == nil && pTargetEntity == nil) pTargetEntity = PLAYER; m_iZoneCullFrameNumWereAt++; if(m_iZoneCullFrameNumWereAt > m_iCheckCullZoneThisNumFrames) m_iZoneCullFrameNumWereAt = 1; m_bCullZoneChecksOn = m_iZoneCullFrameNumWereAt == m_iCheckCullZoneThisNumFrames; if(m_bCullZoneChecksOn) m_bFailedCullZoneTestPreviously = CCullZones::CamCloseInForPlayer(); if(m_bLookingAtPlayer){ CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_CAMERA; FindPlayerPed()->bIsVisible = true; } if(!CTimer::GetIsPaused() && !m_bIdleOn){ float CloseInCarHeightTarget = 0.0f; float CloseInPedHeightTarget = 0.0f; if(m_bTargetJustBeenOnTrain){ // Getting off train if(!pTargetEntity->IsVehicle() || !((CVehicle*)pTargetEntity)->IsTrain()){ Restore(); m_bTargetJustCameOffTrain = true; m_bTargetJustBeenOnTrain = false; SetWideScreenOff(); } } // 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 #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){ CarZoomIndicator--; // disable topdown here if(CarZoomIndicator == CAM_ZOOM_TOPDOWN) CarZoomIndicator--; } if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && !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; } if(m_bFailedCullZoneTestPreviously) if(CarZoomIndicator != CAM_ZOOM_1STPRS && CarZoomIndicator != CAM_ZOOM_TOPDOWN) ReqMode = CCam::MODE_CAM_ON_A_STRING; 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:{ 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 || stairsZone){ float ground; bool foundGround; 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; #endif }else{ whichDoor = 1; garageDoorPos1.x = pTargetEntity->GetPosition().x; garageDoorPos1.y = pTargetEntity->GetPosition().y; #ifdef FIX_BUGS garageDoorPos1.z = 0.0f; #else 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; } } 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 garageCenterToDoor = garageDoorPos2 - garageCenter; targetPos = pTargetEntity->GetPosition(); ground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround); if(!foundGround) ground = targetPos.z - 0.2f; garageCenterToDoor.z = 0.0f; garageCenterToDoor.Normalise(); 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)); m_bGarageFixedCamPositionSet = true; } } if(CGarages::CameraShouldBeOutside() && m_bGarageFixedCamPositionSet && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)){ if(pToGarageWeAreIn){ ReqMode = CCam::MODE_FIXED; m_bPlayerIsInGarage = true; } }else{ if(m_bPlayerIsInGarage){ m_bJustCameOutOfGarage = true; m_bPlayerIsInGarage = false; } ReqMode = CCam::MODE_CAM_ON_A_STRING; } }else{ if(m_bPlayerIsInGarage){ m_bJustCameOutOfGarage = true; m_bPlayerIsInGarage = false; } m_bGarageFixedCamPositionSet = false; 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) { CarZoomValue = 0.0f; ReqMode = CCam::MODE_1STPERSON; } #ifdef FREE_CAM else if (bFreeCam) { if (CarZoomIndicator == CAM_ZOOM_1) CarZoomValue = LCS_ZOOM_ONE_DISTANCE[vehArrPos]; else if (CarZoomIndicator == CAM_ZOOM_2) CarZoomValue = LCS_ZOOM_TWO_DISTANCE[vehArrPos]; else if (CarZoomIndicator == CAM_ZOOM_3) CarZoomValue = LCS_ZOOM_THREE_DISTANCE[vehArrPos]; } #endif else if (CarZoomIndicator == CAM_ZOOM_1) CarZoomValue = ZOOM_ONE_DISTANCE[vehArrPos]; else if(CarZoomIndicator == CAM_ZOOM_2) CarZoomValue = ZOOM_TWO_DISTANCE[vehArrPos]; else if(CarZoomIndicator == CAM_ZOOM_3) CarZoomValue = ZOOM_THREE_DISTANCE[vehArrPos]; if(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){ CarZoomValue = 1.0f; ReqMode = CCam::MODE_TOPDOWN; } // Check if we have to go into first person if(vehType == VEHICLE_TYPE_CAR && !m_bPlayerIsInGarage){ if(CCullZones::Cam1stPersonForPlayer() && pTargetEntity->GetColModel()->boundingBox.GetSize().z >= 3.026f && pToGarageWeAreInForHackAvoidFirstPerson == nil){ ReqMode = CCam::MODE_1STPERSON; m_bInATunnelAndABigVehicle = true; } } if(ReqMode == CCam::MODE_TOPDOWN && (CCullZones::Cam1stPersonForPlayer() || CCullZones::CamNoRain() || CCullZones::PlayerNoRain())) ReqMode = CCam::MODE_1STPERSON; // Smooth zoom value - ugly code if(m_bUseScriptZoomValueCar){ if(CarZoomValueSmooth < m_fCarZoomValueScript){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Min(CarZoomValueSmooth, m_fCarZoomValueScript); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Max(CarZoomValueSmooth, m_fCarZoomValueScript); } }else if(m_bFailedCullZoneTestPreviously){ CloseInCarHeightTarget = 0.65f; if(CarZoomValueSmooth < -0.65f){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Min(CarZoomValueSmooth, -0.65f); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Max(CarZoomValueSmooth, -0.65f); } }else{ if(CarZoomValueSmooth < CarZoomValue){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Min(CarZoomValueSmooth, CarZoomValue); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); CarZoomValueSmooth = Max(CarZoomValueSmooth, CarZoomValue); } } WellBufferMe(CloseInCarHeightTarget, &Cams[ActiveCam].m_fCloseInCarHeightOffset, &Cams[ActiveCam].m_fCloseInCarHeightOffsetSpeed, 0.1f, 0.25f, false); // Fallen into water if(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) && !boatTarget && !Cams[ActiveCam].CamTargetEntity->IsPed() && pTargetEntity->GetModelIndex() != MI_SKIMMER && pTargetEntity->GetModelIndex() != MI_SEASPAR) ReqMode = CCam::MODE_PLAYER_FALLEN_WATER; } } // Ped target else if(pTargetEntity->IsPed()){ // Change user selected mode if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed && !m_bFreezePedZoomSwitch){ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){ if(PedZoomIndicator == CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; else PedZoomIndicator = CAM_ZOOM_3; }else PedZoomIndicator--; } if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed){ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){ if(PedZoomIndicator == CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; else PedZoomIndicator = CAM_ZOOM_3; }else PedZoomIndicator++; } // disabled top down and obbe's cam here if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_3; else if(PedZoomIndicator > CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1; ReqMode = CCam::MODE_FOLLOWPED; // Check 1st person mode if((m_bLookingAtPlayer || m_bEnable1rstPersonCamCntrlsScript) && pTargetEntity->IsPed() && (!m_WideScreenOn || m_bEnable1rstPersonCamCntrlsScript) && !Cams[0].Using3rdPersonMouseCam() #ifdef FREE_CAM && (!CCamera::bFreeCam || m_bEnable1rstPersonCamCntrlsScript) #endif ){ // See if we want to enter first person mode if(CPad::GetPad(0)->LookAroundLeftRight() || CPad::GetPad(0)->LookAroundUpDown()){ m_uiFirstPersonCamLastInputTime = CTimer::GetTimeInMilliseconds(); m_bFirstPersonBeingUsed = true; } if(m_bFirstPersonBeingUsed){ // Or if we want to go back to 3rd person if(CPad::GetPad(0)->GetPedWalkLeftRight() || CPad::GetPad(0)->GetPedWalkUpDown() || CPad::GetPad(0)->GetSquare() || CPad::GetPad(0)->GetTriangle() || CPad::GetPad(0)->GetCross() || CPad::GetPad(0)->GetCircle() || CTimer::GetTimeInMilliseconds() - m_uiFirstPersonCamLastInputTime > 2850.0f){ m_bFirstPersonBeingUsed = false; }else if(CPad::GetPad(0)->TargetJustDown()){ m_bFirstPersonBeingUsed = false; m_bJustJumpedOutOf1stPersonBecauseOfTarget = true; } } }else m_bFirstPersonBeingUsed = false; if(!FindPlayerPed()->IsPedInControl() || FindPlayerPed()->m_fMoveSpeed > 0.0f) m_bFirstPersonBeingUsed = false; if(m_bFirstPersonBeingUsed){ ReqMode = CCam::MODE_1STPERSON; CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_CAMERA; } // Zoom value if(PedZoomIndicator == CAM_ZOOM_1) m_fPedZoomValue = 0.25f; else if(PedZoomIndicator == CAM_ZOOM_2) m_fPedZoomValue = 1.5f; else if(PedZoomIndicator == CAM_ZOOM_3) m_fPedZoomValue = 2.9f; // Smooth zoom value - ugly code if(m_bUseScriptZoomValuePed){ if(m_fPedZoomValueSmooth < m_fPedZoomValueScript){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValueScript); }else{ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValueScript); } }else if(m_bFailedCullZoneTestPreviously){ static float PedZoomedInVal = 0.5f; CloseInPedHeightTarget = 0.7f; if(m_fPedZoomValueSmooth < PedZoomedInVal){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, PedZoomedInVal); }else{ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, PedZoomedInVal); } }else{ if(m_fPedZoomValueSmooth < m_fPedZoomValue){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValue); }else{ 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); // Check if entering fight cam if(!m_bFirstPersonBeingUsed){ if(FindPlayerPed()->GetPedState() == PED_FIGHT && !m_bUseMouse3rdPerson) ReqMode = CCam::MODE_FIGHT_CAM; if(((CPed*)pTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && FindPlayerPed()->GetPedState() == PED_ATTACK && !m_bUseMouse3rdPerson) ReqMode = CCam::MODE_FIGHT_CAM; } // Garage cam CAttributeZone *stairsZone = nil; if(CCullZones::CamStairsForPlayer()){ stairsZone = CCullZones::FindZoneWithStairsAttributeForPlayer(); if(stairsZone) stairs = true; } if(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) && !m_bUseMouse3rdPerson || stairs){ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){ if(pToGarageWeAreIn || stairs){ float ground; bool foundGround; if(pToGarageWeAreIn){ // 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; #endif }else{ whichDoor = 1; garageDoorPos1.x = pTargetEntity->GetPosition().x; garageDoorPos1.y = pTargetEntity->GetPosition().y; #ifdef FIX_BUGS garageDoorPos1.z = 0.0f; #else garageDoorPos2.z = 0.0f; #endif } }else{ whichDoor = 1; garageDoorPos1 = Cams[ActiveCam].Source; if(stairsZone){ // always true garageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2, (stairsZone->miny+stairsZone->maxy)/2, 0.0f); if(pTargetEntity->GetPosition().x > 376.0f && pTargetEntity->GetPosition().x < 383.0f && pTargetEntity->GetPosition().y > -496.0f && pTargetEntity->GetPosition().y < -489.0f && pTargetEntity->GetPosition().z > 11.6f && pTargetEntity->GetPosition().z < 13.6f){ garageDoorPos1 = CVector(382.6f, -489.6f, 13.1f); }else{ bool bClearViewOutside = true; CVector dirOutside = pTargetEntity->GetPosition() - garageCenter; dirOutside.z = 0.0f; dirOutside.Normalise(); float zoneDim = stairsZone->maxx - stairsZone->minx; if(zoneDim < stairsZone->maxy - stairsZone->miny) zoneDim = stairsZone->maxy - stairsZone->miny; zoneDim *= 2.0f; CVector posOutside = pTargetEntity->GetPosition() + zoneDim*dirOutside; if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)){ posOutside = pTargetEntity->GetPosition() - zoneDim*dirOutside; if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)) bClearViewOutside = false; } if(bClearViewOutside) garageDoorPos1 = posOutside; } } } if(pToGarageWeAreIn){ garageCenter.x = pToGarageWeAreIn->GetGarageCenterX(); garageCenter.y = pToGarageWeAreIn->GetGarageCenterY(); garageCenter.z = 0.0f; }else{ garageDoorPos1.z = 0.0f; if(!stairs) // how can this be true? garageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f); } if(whichDoor == 1) garageCenterToDoor = garageDoorPos1 - garageCenter; else garageCenterToDoor = garageDoorPos2 - garageCenter; targetPos = pTargetEntity->GetPosition(); ground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround); if(!foundGround) ground = targetPos.z - 0.2f; garageCenterToDoor.z = 0.0f; garageCenterToDoor.Normalise(); if(whichDoor == 1){ 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; } if(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !stairs){ garageCamPos = garageCenter; garageCamPos.z += FindPlayerPed()->GetPosition().z + 2.1f; 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)); m_bGarageFixedCamPositionSet = true; } } if((CGarages::CameraShouldBeOutside() || stairs) && m_bLookingAtPlayer && m_bGarageFixedCamPositionSet){ if(pToGarageWeAreIn || stairs){ ReqMode = CCam::MODE_FIXED; m_bPlayerIsInGarage = true; } }else{ if(m_bPlayerIsInGarage){ m_bJustCameOutOfGarage = true; m_bPlayerIsInGarage = false; } ReqMode = CCam::MODE_FOLLOWPED; } }else{ if(m_bPlayerIsInGarage){ m_bJustCameOutOfGarage = true; m_bPlayerIsInGarage = false; } 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()) ReqMode = CCam::MODE_PLAYER_FALLEN_WATER; // Set top down if(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !CCullZones::Cam1stPersonForPlayer() && !CCullZones::CamNoRain() && !CCullZones::PlayerNoRain() && !m_bFirstPersonBeingUsed && !m_bPlayerIsInGarage) ReqMode = CCam::MODE_TOP_DOWN_PED; // Weapon mode if(!CPad::GetPad(0)->GetTarget() && PlayerWeaponMode.Mode != CCam::MODE_HELICANNON_1STPERSON) ClearPlayerWeaponMode(); if(m_PlayerMode.Mode != CCam::MODE_NONE) ReqMode = m_PlayerMode.Mode; 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){ if(ReqMode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].GetWeaponFirstPersonOn()) ReqMode = PlayerWeaponMode.Mode; else ReqMode = CCam::MODE_FOLLOWPED; }else ReqMode = PlayerWeaponMode.Mode; }else if(ReqMode != CCam::MODE_TOP_DOWN_PED && PedZoomIndicator != CAM_ZOOM_3){ // Syphon mode float playerTargetDist; float deadPedDist = 4.0f; static float alivePedDist = 2.0f; // original name lost float pedDist; // actually only used on dead target bool targetDead = false; float camAngle, targetAngle; CVector playerToTarget = m_cvecAimingTargetCoors - pTargetEntity->GetPosition(); CVector playerToCam = Cams[ActiveCam].Source - pTargetEntity->GetPosition(); if(PedZoomIndicator == CAM_ZOOM_1) deadPedDist = 2.25f; if(FindPlayerPed()->m_pPointGunAt){ // BUG: this need not be a ped! if(((CPed*)FindPlayerPed()->m_pPointGunAt)->DyingOrDead()){ targetDead = true; pedDist = deadPedDist; }else pedDist = alivePedDist; playerTargetDist = playerToTarget.Magnitude2D(); camAngle = CGeneral::GetATanOfXY(playerToCam.x, playerToCam.y); targetAngle = CGeneral::GetATanOfXY(playerToTarget.x, playerToTarget.y); ReqMode = PlayerWeaponMode.Mode; // Check whether to start aiming in crim-in-front mode if(Cams[ActiveCam].Mode != CCam::MODE_SYPHON){ float angleDiff = camAngle - targetAngle; while(angleDiff >= PI) angleDiff -= 2*PI; while(angleDiff < -PI) angleDiff += 2*PI; if(Abs(angleDiff) < HALFPI && playerTargetDist < 3.5f && playerToTarget.z > -1.0f) ReqMode = CCam::MODE_SYPHON_CRIM_IN_FRONT; } // Check whether to go to special fixed mode float fixedModeDist = 0.0f; if((ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SYPHON) && (m_uiTransitionState == 0 || Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) && playerTargetDist < pedDist && targetDead){ if(ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT) fixedModeDist = 5.0f; else fixedModeDist = 5.6f; ReqMode = CCam::MODE_SPECIAL_FIXED_FOR_SYPHON; } if(ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){ if(!PlaceForFixedWhenSniperFound){ // Find position CEntity *entity; CColPoint colPoint; CVector fixedPos = pTargetEntity->GetPosition(); fixedPos.x += fixedModeDist*Cos(camAngle); fixedPos.y += fixedModeDist*Sin(camAngle); fixedPos.z += 1.15f; if(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), fixedPos, colPoint, entity, true, false, false, true, false, true, true)) SetCamPositionForFixedMode(colPoint.point, CVector(0.0f, 0.0f, 0.0f)); else SetCamPositionForFixedMode(fixedPos, CVector(0.0f, 0.0f, 0.0f)); PlaceForFixedWhenSniperFound = true; } }else PlaceForFixedWhenSniperFound = false; } } } } } if(DebugCamMode) ReqMode = DebugCamMode; // Process arrested player 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()) startArrestCam = true; }else startArrestCam = false; LastPedState = PLAYER->GetPedState(); if(startArrestCam){ 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 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){ 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_CAMERA && !m_bUseMouse3rdPerson) SetCameraDirectlyBehindForFollowPed_CamOnAString(); ReqMode = m_iModeToGoTo; Cams[ActiveCam].Mode = ReqMode; m_bJust_Switched = true; Cams[ActiveCam].ResetStatics = true; Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; Cams[ActiveCam].m_bCamLookingAtVector = false; Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition; m_bRestoreByJumpCut = false; Cams[ActiveCam].ResetStatics = true; pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); CarZoomValueSmooth = CarZoomValue; m_fPedZoomValueSmooth = m_fPedZoomValue; m_uiTransitionState = 0; m_vecDoingSpecialInterPolation = false; } if(gbModelViewer) ReqMode = CCam::MODE_MODELVIEW; // Turn on Obbe's cam bool canUseObbeCam = true; if(pTargetEntity){ if(pTargetEntity->IsVehicle()){ if(CarZoomIndicator == CAM_ZOOM_CINEMATIC) m_bObbeCinematicCarCamOn = true; }else{ if(PedZoomIndicator == CAM_ZOOM_CINEMATIC) m_bObbeCinematicPedCamOn = true; } } if(m_bTargetJustBeenOnTrain || ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON || ReqMode == CCam::MODE_PED_DEAD_BABY || ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO || ReqMode == CCam::MODE_FIGHT_CAM || ReqMode == CCam::MODE_PLAYER_FALLEN_WATER || 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_CAMERA || WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT || m_bJustCameOutOfGarage || m_bPlayerIsInGarage) canUseObbeCam = false; if(m_bObbeCinematicPedCamOn && canUseObbeCam) ProcessObbeCinemaCameraPed(); 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; DontProcessObbeCinemaCamera(); } // Start the transition or do a jump cut if(m_bLookingAtPlayer){ // Going into top down modes normally needs a jump cut (but see below) if(ReqMode == CCam::MODE_TOPDOWN || ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_TOP_DOWN_PED){ switchByJumpCut = true; } // Going from top down to vehicle else if(ReqMode == CCam::MODE_CAM_ON_A_STRING || ReqMode == CCam::MODE_BEHINDBOAT){ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED) switchByJumpCut = true; }else if(ReqMode == CCam::MODE_FIXED){ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN) 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) switchByJumpCut = false; }else if(ReqMode == CCam::MODE_TOP_DOWN_PED){ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY) switchByJumpCut = false; } if(ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_M16_1STPERSON || ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER || 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_CAMERA || ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO){ // Going into any 1st person mode is a jump cut if(pTargetEntity->IsPed()) switchByJumpCut = true; }else if(ReqMode == CCam::MODE_FIXED && m_bPlayerIsInGarage){ // Going from 1st peron mode into garage if(Cams[ActiveCam].Mode == CCam::MODE_SNIPER || Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || stairs || Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT || 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_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 || Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_ONE || Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_TWO || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY || Cams[ActiveCam].Mode == CCam::MODE_PILLOWS_PAPS || Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || 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_CAMERA || Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || 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 || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || 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_CAMERA){ float angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI; ((CPed*)pTargetEntity)->m_fRotationCur = angle; ((CPed*)pTargetEntity)->m_fRotationDest = angle; } m_bUseTransitionBeta = true; switchByJumpCut = true; if(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ CVector front = Cams[ActiveCam].Source - FindPlayerPed()->GetPosition(); front.z = 0.0f; front.Normalise(); #ifdef FIX_BUGS // this is almost as bad as the bugged code if(front.x == 0.001f && front.y == 0.001f) front.y = 1.0f; #else // someone used = instead of == in the above check by accident front.x = 0.001f; front.y = 1.0f; #endif Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(front.x, front.y); }else Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI; } } }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; if(m_bPlayerIsInGarage && pToGarageWeAreIn){ if(pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP1 || pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP2 || pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP3){ if(pTargetEntity->IsVehicle() && pTargetEntity->GetModelIndex() == MI_MRWHOOP && ReqMode != Cams[ActiveCam].Mode) switchByJumpCut = true; } } #ifdef GTA_SCENE_EDIT if(CSceneEdit::m_bEditOn) ReqMode = CCam::MODE_EDITOR; #endif if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){ if(switchByJumpCut){ if(!m_bPlayerIsInGarage || m_bJustCameOutOfGarage){ if(ReqMode != CCam::MODE_FOLLOWPED && ReqMode != CCam::MODE_M16_1STPERSON && ReqMode != CCam::MODE_SNIPER && ReqMode != CCam::MODE_ROCKETLAUNCHER && !m_bUseMouse3rdPerson) SetCameraDirectlyBehindForFollowPed_CamOnAString(); } Cams[ActiveCam].Mode = ReqMode; m_bJust_Switched = true; Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector; Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition; CarZoomValueSmooth = CarZoomValue; m_fPedZoomValueSmooth = m_fPedZoomValue; m_uiTransitionState = 0; m_vecDoingSpecialInterPolation = false; m_bStartInterScript = false; Cams[ActiveCam].ResetStatics = true; pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); }else if(!m_bWaitForInterpolToFinish){ StartTransition(ReqMode); pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); } }else if(m_uiTransitionState != 0 && ReqMode != Cams[ActiveCam].Mode){ bool startTransition = true; if(ReqMode == CCam::MODE_FIGHT_CAM || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM) startTransition = false; if(ReqMode == CCam::MODE_FOLLOWPED && Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM) startTransition = false; if(!m_bWaitForInterpolToFinish && m_bLookingAtPlayer && m_uiTransitionState != 0){ CVector playerDist; playerDist.x = FindPlayerPed()->GetPosition().x - GetPosition().x; playerDist.y = FindPlayerPed()->GetPosition().y - GetPosition().y; playerDist.z = FindPlayerPed()->GetPosition().z - GetPosition().z; // if player is too far away, keep interpolating and don't transition if(pTargetEntity && pTargetEntity->IsPed()){ if(playerDist.Magnitude() > 17.5f && (ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT)) m_bWaitForInterpolToFinish = true; } } if(m_bWaitForInterpolToFinish) startTransition = false; if(startTransition){ StartTransitionWhenNotFinishedInter(ReqMode); pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); } }else if(ReqMode == CCam::MODE_FIXED && pTargetEntity != Cams[ActiveCam].CamTargetEntity && m_bPlayerIsInGarage){ if(m_uiTransitionState != 0) StartTransitionWhenNotFinishedInter(ReqMode); else StartTransition(ReqMode); 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); pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); }else if(m_uiTransitionState != 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){ ReqMode = m_iModeToGoTo; StartTransitionWhenNotFinishedInter(ReqMode); pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); }else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT || jumpCutTo1stPrs){ m_uiTransitionState = 0; m_vecDoingSpecialInterPolation = false; 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; Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector; Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition; m_bJust_Switched = true; pTargetEntity->RegisterReference(&pTargetEntity); Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity); CarZoomValueSmooth = CarZoomValue; m_fPedZoomValueSmooth = m_fPedZoomValue; } } m_bStartInterScript = false; if(Cams[ActiveCam].CamTargetEntity == nil) Cams[ActiveCam].CamTargetEntity = pTargetEntity; // Ped visibility 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 || 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; bool switchedFromObbe = false; if(!canUseObbeCam && WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){ RestoreWithJumpCut(); switchedFromObbe = true; SetCameraDirectlyBehindForFollowPed_CamOnAString(); } if(PrevMode != Cams[ActiveCam].Mode || switchedFromObbe || Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING) if(CPad::GetPad(0)->CycleCameraModeJustDown() && !CReplay::IsPlayingBack() && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && !m_WideScreenOn && (WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam)) DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); } // What a mess! void CCamera::UpdateTargetEntity(void) { 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){ if(FindPlayerPed()->GetPedState() != PED_ARRESTED) obbeCam = false; if(FindPlayerVehicle() == nil) pTargetEntity = FindPlayerPed(); } } if((m_bLookingAtPlayer || obbeCam) && m_uiTransitionState == 0 || pTargetEntity == nil || m_bTargetJustBeenOnTrain){ if(FindPlayerVehicle()) pTargetEntity = FindPlayerVehicle(); else{ pTargetEntity = FindPlayerPed(); // this keeps the camera on the player while entering cars if(PLAYER->GetPedState() == PED_ENTER_CAR || PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) enteringCar = true; if(!enteringCar) if(Cams[ActiveCam].CamTargetEntity != pTargetEntity) Cams[ActiveCam].CamTargetEntity = pTargetEntity; } bool cantOpen = true; 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){ pTargetEntity = PLAYER->m_pMyVehicle; if(PLAYER->m_pMyVehicle == nil) pTargetEntity = PLAYER; } } if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){ if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS) pTargetEntity = PLAYER->m_pMyVehicle; if(PLAYER->m_pMyVehicle == nil) pTargetEntity = PLAYER; } if(PLAYER->GetPedState() == PED_EXIT_CAR) pTargetEntity = FindPlayerPed(); if(PLAYER->GetPedState() == PED_DRAG_FROM_CAR) pTargetEntity = FindPlayerPed(); if(pTargetEntity->IsVehicle() && CarZoomIndicator == CAM_ZOOM_1STPRS && FindPlayerPed()->GetPedState() == PED_ARRESTED) pTargetEntity = FindPlayerPed(); } } const float SOUND_DIST = 20.0f; void CCamera::UpdateSoundDistances(void) { CVector center, end; CEntity *entity; CColPoint colPoint; float f; int n; if((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER || Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || 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_CAMERA || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) && pTargetEntity->IsPed()) center = GetPosition() + 0.5f*GetForward(); else center = GetPosition() + 5.0f*GetForward(); // check up n = CTimer::GetFrameCounter() % 12; if(n == 0){ SoundDistUpAsReadOld = SoundDistUpAsRead; if(CWorld::ProcessVerticalLine(center, center.z+SOUND_DIST, colPoint, entity, true, false, false, false, true, false, nil)) SoundDistUpAsRead = colPoint.point.z - center.z; else SoundDistUpAsRead = SOUND_DIST; } f = (n + 1) / 6.0f; SoundDistUp = (1.0f-f)*SoundDistUpAsReadOld + f*SoundDistUpAsRead; } void CCamera::InitialiseCameraForDebugMode(void) { if(FindPlayerVehicle()) Cams[2].Source = FindPlayerVehicle()->GetPosition(); else if(FindPlayerPed()) Cams[2].Source = FindPlayerPed()->GetPosition(); Cams[2].Alpha = 0.0f; Cams[2].Beta = 0.0f; Cams[2].Mode = CCam::MODE_DEBUG; } void CCamera::CamShake(float strength, float x, float y, float z) { CVector Dist = Cams[ActiveCam].Source - CVector(x, y, z); // a bit complicated... float dist2d = Sqrt(SQR(Dist.x) + SQR(Dist.y)); float dist3d = Sqrt(SQR(dist2d) + SQR(Dist.z)); if(dist3d > 100.0f) dist3d = 100.0f; if(dist3d < 0.0f) dist3d = 0.0f; float mult = 1.0f - dist3d/100.0f; float curForce = mult*(m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - m_uiCamShakeStart)/1000.0f); strength = mult*strength; if(clamp(curForce, 0.0f, 2.0f) < strength){ m_fCamShakeForce = strength; m_uiCamShakeStart = CTimer::GetTimeInMilliseconds(); } } // This seems to be CCamera::CamShake(float) on PS2 void CamShakeNoPos(CCamera *cam, float strength) { float curForce = cam->m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - cam->m_uiCamShakeStart)/1000.0f; if(clamp(curForce, 0.0f, 2.0f) < strength){ cam->m_fCamShakeForce = strength; cam->m_uiCamShakeStart = CTimer::GetTimeInMilliseconds(); } } bool bAvoidTest1 = false; bool bAvoidTest2 = false; // unused bool bAvoidTest3 = false; // unused float fRangePlayerRadius = 0.5f; float fCloseNearClipLimit = 0.15f; float fAvoidTweakFOV = 1.15f; float fAvoidProbTimerDamp = 0.9f; void CCamera::AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV) { float Beta = 0.0f; float Alpha = 0.0f; CVector vDist = TargetPos - Source; m_vecClearGeometryVec = CVector(0.0f, 0.0f, 0.0f); float fDist = vDist.Magnitude(); float fDistOnGround = vDist.Magnitude2D(); if(vDist.x == 0.0f && vDist.y == 0.0f) Beta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); else Beta = CGeneral::GetATanOfXY(vDist.x, vDist.y); if(fDistOnGround != 0.0f || vDist.z != 0.0f) Alpha = CGeneral::GetATanOfXY(fDistOnGround, vDist.z); CVector Front(Cos(Alpha)*Cos(Beta), Cos(Alpha)*Sin(Beta), Sin(Alpha)); NewSource = TargetPos - Front*fDist; Front.Normalise(); // Clip camera source CColPoint point; CEntity *entity = nil; CWorld::pIgnoreEntity = pTargetEntity; if(CWorld::ProcessLineOfSight(TargetPos, NewSource, point, entity, true, false, false, true, false, false, true)){ CVector ClipPoint1 = point.point; NewSource = point.point; if(!bAvoidTest1){ if(CWorld::ProcessLineOfSight(NewSource, TargetPos, point, entity, false, true, true, true, false, false, true)){ if((NewSource - point.point).Magnitude() < RwCameraGetNearClipPlane(Scene.camera)) NewSource = point.point; else if((NewSource - ClipPoint1).Magnitude() < RwCameraGetNearClipPlane(Scene.camera)) NewSource = ClipPoint1; } } } CWorld::pIgnoreEntity = nil; vDist = TargetPos - NewSource; fDist = vDist.Magnitude(); if(FindPlayerPed()) if(fDist - fRangePlayerRadius < RwCameraGetNearClipPlane(Scene.camera)) RwCameraSetNearClipPlane(Scene.camera, Max(fDist - fRangePlayerRadius, fCloseNearClipLimit)); static float fClearGeomAmount; static float fClearGeomAmountSpeed; float Near = RwCameraGetNearClipPlane(Scene.camera); float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f); float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fAvoidTweakFOV; CVector Center = NewSource + Front*Near; float fClearGeomTarget = 0.0f; if(CWorld::TestSphereAgainstWorld(Center, ViewPlaneWidth, nil, true, false, false, true, false, true)){ CVector CamToCol = gaTempSphereColPoints[0].point - NewSource; float FrontDist = DotProduct(CamToCol, Front); CVector CenterToCol = gaTempSphereColPoints[0].point - Center; if(FrontDist < DEFAULT_NEAR && FrontDist > fCloseNearClipLimit){ if(FrontDist < RwCameraGetNearClipPlane(Scene.camera)) RwCameraSetNearClipPlane(Scene.camera, FrontDist); }else if(FrontDist < fCloseNearClipLimit) RwCameraSetNearClipPlane(Scene.camera, fCloseNearClipLimit); float ColDepth = ViewPlaneWidth - CenterToCol.Magnitude(); // amount of radius in collision CenterToCol.Normalise(); CVector Normal = gaTempSphereColPoints[0].normal; Normal.Normalise(); if(-DotProduct(CenterToCol, Normal) < 0.0f) Normal = -Normal; // always push away from col surface float DistToMove = DotProduct(-ColDepth*CenterToCol, Normal); m_vecClearGeometryVec = DistToMove*Normal; // move source so this point is out of collision if(pTargetEntity && pTargetEntity->IsPed() && RwCameraGetNearClipPlane(Scene.camera) < 2.0f*fCloseNearClipLimit){ float TargetNormalDir = DotProduct(Normal, pTargetEntity->GetForward()); if(TargetNormalDir < 0.0f){ // target looking towards collision if(m_fAvoidTheGeometryProbsTimer < 0.0f) m_fAvoidTheGeometryProbsTimer = 0.0f; m_fAvoidTheGeometryProbsTimer += CTimer::GetTimeStep(); }else if(TargetNormalDir > 0.5f){ // target looking away from collision if(m_fAvoidTheGeometryProbsTimer > 0.0f) m_fAvoidTheGeometryProbsTimer = 0.0f; m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep(); } if(m_nAvoidTheGeometryProbsDirn == 0){ if(CrossProduct(pTargetEntity->GetPosition() - NewSource, Normal).z > 0.0f) m_nAvoidTheGeometryProbsDirn = -1; else m_nAvoidTheGeometryProbsDirn = 1; } } fClearGeomTarget = 1.0f; } m_fAvoidTheGeometryProbsTimer *= Pow(fAvoidProbTimerDamp, CTimer::GetTimeStep()); WellBufferMe(fClearGeomTarget, &fClearGeomAmount, &fClearGeomAmountSpeed, 0.2f, 0.05f, false); m_vecClearGeometryVec *= fClearGeomAmount; m_bMoveCamToAvoidGeom = true; } void CCamera::GetArrPosForVehicleType(int apperance, int &index) { switch(apperance){ case VEHICLE_APPEARANCE_CAR: index = 0; break; case VEHICLE_APPEARANCE_BIKE: index = 1; break; case VEHICLE_APPEARANCE_HELI: index = 2; break; case VEHICLE_APPEARANCE_PLANE: index = 3; break; case VEHICLE_APPEARANCE_BOAT: index = 4; break; } } void CCamera::GetScreenRect(CRect &rect) { rect.left = 0.0f; rect.right = SCREEN_WIDTH; if(m_WideScreenOn #ifdef CUTSCENE_BORDERS_SWITCH && CMenuManager::m_PrefsCutsceneBorders #endif ){ float borderSize = (SCREEN_HEIGHT / 2) * (m_ScreenReductionPercentage / 100.f); rect.top = borderSize - SCREEN_SCALE_Y(22.f); rect.bottom = SCREEN_HEIGHT - borderSize - SCREEN_SCALE_Y(14.f); }else{ rect.top = 0.0f; rect.bottom = SCREEN_HEIGHT; } } void CCamera::TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller) { bool doSwitch = true; if(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT) doSwitch = false; if(doSwitch){ WhoIsInControlOfTheCamera = controller; if(target){ if(mode == CCam::MODE_NONE){ // Why are we checking the old entity? if(pTargetEntity->IsPed()) mode = CCam::MODE_FOLLOWPED; else if(pTargetEntity->IsVehicle()) mode = CCam::MODE_CAM_ON_A_STRING; } }else if(FindPlayerVehicle()) target = FindPlayerVehicle(); else target = PLAYER; m_bLookingAtVector = false; pTargetEntity = target; m_iModeToGoTo = mode; m_iTypeOfSwitch = typeOfSwitch; m_bLookingAtPlayer = false; m_bStartInterScript = true; } } void CCamera::TakeControlNoEntity(const CVector &position, int16 typeOfSwitch, int32 controller) { bool doSwitch = true; if(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT) doSwitch = false; if(doSwitch){ WhoIsInControlOfTheCamera = controller; m_bLookingAtVector = true; m_bLookingAtPlayer = false; m_iModeToGoTo = CCam::MODE_FIXED; m_vecFixedModeVector = position; m_iTypeOfSwitch = typeOfSwitch; m_bStartInterScript = true; } } void CCamera::TakeControlWithSpline(int16 typeOfSwitch) { m_iModeToGoTo = CCam::MODE_FLYBY; m_bLookingAtPlayer = false; m_bLookingAtVector = false; m_bcutsceneFinished = false; m_iTypeOfSwitch = typeOfSwitch; m_bStartInterScript = true; }; void CCamera::Restore(void) { m_bLookingAtPlayer = true; m_bLookingAtVector = false; m_iTypeOfSwitch = INTERPOLATION; m_bUseNearClipScript = false; m_iModeObbeCamIsInForCar = OBBE_INVALID; m_fPositionAlongSpline = 0.0; m_bStartingSpline = false; m_bScriptParametersSetForInterPol = false; WhoIsInControlOfTheCamera = CAMCONTROL_GAME; if(FindPlayerVehicle()){ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING; pTargetEntity = FindPlayerVehicle(); }else{ m_iModeToGoTo = CCam::MODE_FOLLOWPED; pTargetEntity = PLAYER; } if(PLAYER->GetPedState() == PED_ENTER_CAR || PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR){ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING; pTargetEntity = PLAYER->m_pSeekTarget; } if(PLAYER->GetPedState() == PED_EXIT_CAR){ m_iModeToGoTo = CCam::MODE_FOLLOWPED; 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 CCamera::RestoreWithJumpCut(void) { m_bRestoreByJumpCut = true; m_bLookingAtPlayer = true; m_bLookingAtVector = false; m_iTypeOfSwitch = JUMP_CUT; m_bUseNearClipScript = false; m_iModeObbeCamIsInForCar = OBBE_INVALID; m_fPositionAlongSpline = 0.0; m_bStartingSpline = false; 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; pTargetEntity = FindPlayerVehicle(); }else{ m_iModeToGoTo = CCam::MODE_FOLLOWPED; pTargetEntity = PLAYER; } if(PLAYER->GetPedState() == PED_ENTER_CAR || PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR){ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING; pTargetEntity = PLAYER->m_pSeekTarget; } if(PLAYER->GetPedState() == PED_EXIT_CAR){ m_iModeToGoTo = CCam::MODE_FOLLOWPED; pTargetEntity = PLAYER; } m_bUseScriptZoomValuePed = false; m_bUseScriptZoomValueCar = false; } void CCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffSet) { m_vecFixedModeSource = Source; m_vecFixedModeUpOffSet = UpOffSet; m_bGarageFixedCamPositionSet = false; } 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; m_bItsOkToLookJustAtThePlayer = false; m_fFractionInterToStopMoving = 0.25f; m_fFractionInterToStopCatchUp = 0.75f; if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT || Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || Cams[ActiveCam].Mode == CCam::MODE_SYPHON || Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){ if(newMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || newMode == CCam::MODE_FOLLOWPED || newMode == CCam::MODE_SYPHON || newMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) switchPedMode = true; if(newMode == CCam::MODE_CAM_ON_A_STRING) switchPedToCar = true; } 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; if(Cams[ActiveCam].Mode == CCam::MODE_FIXED) switchFromFixed = true; m_bUseTransitionBeta = false; if((Cams[ActiveCam].Mode == CCam::MODE_SNIPER || Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER || Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT || 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_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; ((CPed*)pTargetEntity)->m_fRotationCur = angle; ((CPed*)pTargetEntity)->m_fRotationDest = angle; } Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; Cams[ActiveCam].CamTargetEntity = pTargetEntity; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector; if(newMode == CCam::MODE_SNIPER || newMode == CCam::MODE_ROCKETLAUNCHER || newMode == CCam::MODE_M16_1STPERSON || newMode == CCam::MODE_SNIPER_RUNABOUT || newMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || 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_CAMERA) Cams[ActiveCam].Alpha = 0.0f; 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: Cams[ActiveCam].BetaSpeed = 0.0f; break; case CCam::MODE_BEHINDBOAT: Cams[ActiveCam].BetaSpeed = 0.0f; break; case CCam::MODE_FOLLOWPED: // Getting out of vehicle normally betaOffset = DEGTORAD(55.0f); if(m_bJustCameOutOfGarage){ m_bUseTransitionBeta = true; if(Cams[ActiveCam].Front.x != 0.0f || Cams[ActiveCam].Front.y != 0.0f) Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI; else Cams[ActiveCam].m_fTransitionBeta = 0.0f; } if(m_bTargetJustCameOffTrain) m_bCamDirectlyInFront = true; if(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING) break; m_bUseTransitionBeta = true; vehicleVertical = false; if(((CPed*)pTargetEntity)->m_carInObjective && ((CPed*)pTargetEntity)->m_carInObjective->GetForward().x == 0.0f && ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y == 0.0f) vehicleVertical = true; if(vehicleVertical){ Cams[ActiveCam].m_fTransitionBeta = 0.0f; break; } camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); if(((CPed*)pTargetEntity)->m_carInObjective) targetBeta = CGeneral::GetATanOfXY(((CPed*)pTargetEntity)->m_carInObjective->GetForward().x, ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y); else targetBeta = camBeta; deltaBeta = targetBeta - camBeta; while(deltaBeta >= PI) deltaBeta -= 2*PI; while(deltaBeta < -PI) deltaBeta += 2*PI; deltaBeta = Abs(deltaBeta); door = FindPlayerPed()->m_vehDoor; if(deltaBeta > HALFPI){ if(((CPed*)pTargetEntity)->m_carInObjective){ if(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) betaOffset = -DEGTORAD(95.0f); }else{ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) betaOffset = -DEGTORAD(95.0f); } } Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset; }else{ if(((CPed*)pTargetEntity)->m_carInObjective){ if(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) betaOffset = -DEGTORAD(55.0f); else if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) betaOffset = DEGTORAD(95.0f); }else{ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) betaOffset = -DEGTORAD(55.0f); else if(door == CAR_DOOR_RF || door == CAR_DOOR_RR) betaOffset = DEGTORAD(95.0f); } } Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI; } break; case CCam::MODE_SNIPER: case CCam::MODE_ROCKETLAUNCHER: case CCam::MODE_M16_1STPERSON: 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_HELICANNON_1STPERSON: case CCam::MODE_CAMERA: if(FindPlayerVehicle()) Cams[ActiveCam].Beta = Atan2(FindPlayerVehicle()->GetForward().x, FindPlayerVehicle()->GetForward().y); else Cams[ActiveCam].Beta = Atan2(PLAYER->GetForward().x, PLAYER->GetForward().y); break; case CCam::MODE_SYPHON: Cams[ActiveCam].Alpha = 0.0f; Cams[ActiveCam].AlphaSpeed = 0.0f; break; case CCam::MODE_CAM_ON_A_STRING: // Get into vehicle betaOffset = DEGTORAD(57.0f); if(!m_bLookingAtPlayer || m_bJustCameOutOfGarage) break; m_bUseTransitionBeta = true; Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y); break; case CCam::MODE_PED_DEAD_BABY: Cams[ActiveCam].Alpha = DEGTORAD(15.0f); break; case CCam::MODE_FIGHT_CAM: Cams[ActiveCam].Beta = 0.0f; Cams[ActiveCam].BetaSpeed = 0.0f; Cams[ActiveCam].Alpha = 0.0f; Cams[ActiveCam].AlphaSpeed = 0.0f; break; } Cams[ActiveCam].Init(); Cams[ActiveCam].Mode = newMode; m_uiTransitionDuration = 1350; if(switchSyphonMode) m_uiTransitionDuration = 1800; else if(switchFromFight) m_uiTransitionDuration = 750; else if(switchPedToCar){ 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 m_uiTransitionState = 1; m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds(); m_uiTransitionJUSTStarted = 1; if(m_vecDoingSpecialInterPolation){ m_cvecStartingSourceForInterPol = SourceDuringInter; m_cvecStartingTargetForInterPol = TargetDuringInter; m_cvecStartingUpForInterPol = UpDuringInter; m_fStartingAlphaForInterPol = m_fAlphaDuringInterPol; m_fStartingBetaForInterPol = m_fBetaDuringInterPol; }else{ m_cvecStartingSourceForInterPol = Cams[ActiveCam].Source; m_cvecStartingTargetForInterPol = Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter; m_cvecStartingUpForInterPol = Cams[ActiveCam].Up; m_fStartingAlphaForInterPol = Cams[ActiveCam].m_fTrueAlpha; m_fStartingBetaForInterPol = Cams[ActiveCam].m_fTrueBeta; } Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector; Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector; Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource; Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet; Cams[ActiveCam].Mode = newMode; // already done above Cams[ActiveCam].CamTargetEntity = pTargetEntity; m_uiTransitionState = 1; // these three already done above m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds(); m_uiTransitionJUSTStarted = 1; m_fStartingFOVForInterPol = Cams[ActiveCam].FOV; m_cvecSourceSpeedAtStartInter = Cams[ActiveCam].m_cvecSourceSpeedOverOneFrame; m_cvecTargetSpeedAtStartInter = Cams[ActiveCam].m_cvecTargetSpeedOverOneFrame; m_cvecUpSpeedAtStartInter = Cams[ActiveCam].m_cvecUpOverOneFrame; m_fAlphaSpeedAtStartInter = Cams[ActiveCam].m_fAlphaSpeedOverOneFrame; m_fBetaSpeedAtStartInter = Cams[ActiveCam].m_fBetaSpeedOverOneFrame; m_fFOVSpeedAtStartInter = Cams[ActiveCam].m_fFovSpeedOverOneFrame; Cams[ActiveCam].ResetStatics = true; 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; } } void CCamera::StartTransitionWhenNotFinishedInter(int16 mode) { m_vecDoingSpecialInterPolation = true; StartTransition(mode); } void CCamera::StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV) { SourceDuringInter = source; TargetDuringInter = target; UpDuringInter = up; FOVDuringInter = FOV; CVector Dist = source - TargetDuringInter; float DistOnGround = Dist.Magnitude2D(); m_fBetaDuringInterPol = CGeneral::GetATanOfXY(Dist.x, Dist.y); m_fAlphaDuringInterPol = CGeneral::GetATanOfXY(DistOnGround, Dist.z); } void CCamera::SetWideScreenOn(void) { m_WideScreenOn = true; } void CCamera::SetWideScreenOff(void) { m_bWantsToSwitchWidescreenOff = m_WideScreenOn; } void CCamera::ProcessWideScreenOn(void) { if(m_bWantsToSwitchWidescreenOff){ m_bWantsToSwitchWidescreenOff = false; m_WideScreenOn = false; m_ScreenReductionPercentage = 0.0f; m_fFOV_Wide_Screen = 0.0f; m_fWideScreenReductionAmount = 0.0f; }else{ m_fFOV_Wide_Screen = 0.3f*Cams[ActiveCam].FOV; m_fWideScreenReductionAmount = 1.0f; m_ScreenReductionPercentage = 30.0f; } } 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); // top border CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, top), CRGBA(0, 0, 0, 255)); // bottom border CSprite2d::DrawRect(CRect(0.0f, bottom, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255)); } bool CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) { CVehicle *veh; uint32 t = time; // no annoying compiler warnings CVector fwd; if(obbeMode < 0) return true; switch(obbeMode){ case OBBE_WHEEL: veh = FindPlayerVehicle(); if(veh){ 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; } if(CTimer::GetTimeInMilliseconds() > t+5000) return true; SetNearClipScript(0.6f); return false; case OBBE_1: 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; fwd = FindPlayerCoors() - m_vecFixedModeSource; fwd.z = 0.0f; // too far and driving away from cam 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() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return true; if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)) return true; fwd = FindPlayerCoors() - m_vecFixedModeSource; fwd.z = 0.0f; if(fwd.Magnitude() < 2.0f) // very close, fix near clip SetNearClipScript(Max(fwd.Magnitude()*0.5f, 0.05f)); // too far and driving away from cam if(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; // too close if(fwd.Magnitude() < 2.0f) return true; return false; case OBBE_3: 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() > 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() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return true; 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() > 38.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_ONSTRING: return CTimer::GetTimeInMilliseconds() > t+3000; case OBBE_COPCAR: return CTimer::GetTimeInMilliseconds() > t+2000 && !FindPlayerVehicle()->GetIsOnScreen(); case OBBE_COPCAR_WHEEL: if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat()) return true; if(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false)) return true; if(CTimer::GetTimeInMilliseconds() > t+1000) return true; SetNearClipScript(0.6f); return false; // Ped modes case OBBE_9: 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() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_10: 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() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_11: 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() > 25.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; return false; case OBBE_12: 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() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; 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; } } bool CCamera::TryToStartNewCamMode(int obbeMode) { CVehicle *veh; CVector target, camPos, playerSpeed, fwd, fwd2; float angle; float ground; bool foundGround; int i; if(obbeMode < 0) return true; switch(obbeMode){ case OBBE_WHEEL: veh = FindPlayerVehicle(); 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(); if(!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_1: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 20.0f*playerSpeed; camPos += 3.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f); if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); if(foundGround) camPos.z = ground + 1.5f; else{ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround); if(foundGround) camPos.z = ground + 1.5f; } if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; fwd = FindPlayerCoors() - camPos; fwd.z = 0.0f; // too far and driving away from cam if(fwd.Magnitude() > 40.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return false; // too close 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() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 16.0f*playerSpeed; camPos += 2.5f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f); ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); if(foundGround) camPos.z = ground + 0.5f; else{ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround); if(foundGround) camPos.z = ground + 0.5f; } if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; fwd = FindPlayerCoors() - camPos; fwd.z = 0.0f; // too far and driving away from cam if(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 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_3: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 30.0f*playerSpeed; camPos += 8.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f); if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_1STPERSON: TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_5: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 30.0f*playerSpeed; camPos += 6.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f); ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); if(foundGround) camPos.z = ground + 3.5f; else{ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround); if(foundGround) camPos.z = ground + 3.5f; } if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_ONSTRING: TakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_COPCAR: #ifdef FIX_BUGS if (CReplay::IsPlayingBack()) return false; #endif if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1) return false; if(FindPlayerVehicle() == nil) return false; if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; i = CPools::GetVehiclePool()->GetSize(); while(--i >= 0){ veh = CPools::GetVehiclePool()->GetSlot(i); if(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){ float dx = veh->GetPosition().x - FindPlayerCoors().x; float dy = veh->GetPosition().y - FindPlayerCoors().y; float dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude(); if(dist < 30.0f){ if(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f && veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){ TakeControl(veh, CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE); return true; } } } } return false; case OBBE_COPCAR_WHEEL: #ifdef FIX_BUGS if (CReplay::IsPlayingBack()) return false; #endif if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1) return false; if(FindPlayerVehicle() == nil) return false; if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) return false; i = CPools::GetVehiclePool()->GetSize(); while(--i >= 0){ veh = CPools::GetVehiclePool()->GetSlot(i); if(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){ float dx = veh->GetPosition().x - FindPlayerCoors().x; float dy = veh->GetPosition().y - FindPlayerCoors().y; float dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude(); if(dist < 30.0f){ if(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f && veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){ target = Multiply3x3(veh->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f)); target += veh->GetPosition(); if(!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; } } } } return false; case OBBE_9: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 15.0f*playerSpeed; camPos += CVector(2.0f, 1.0f, 0.0f); ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround); if(foundGround) camPos.z = ground + 0.5f; else{ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround); if(foundGround) camPos.z = ground + 0.5f; } if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_10: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 5.0f*playerSpeed; camPos += CVector(2.0f, 1.0f, 0.5f); if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_11: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 20.0f*playerSpeed; camPos += CVector(2.0f, 1.0f, 20.0f); if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_12: camPos = FindPlayerCoors(); playerSpeed = FindPlayerSpeed(); playerSpeed.z = 0.0f; playerSpeed.Normalise(); camPos += 5.0f*playerSpeed; camPos += CVector(2.0f, 1.0f, 10.5f); if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false)) return false; SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f)); TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_13: #ifdef FIX_BUGS TakeControl(FindPlayerEntity(), CCam::MODE_TOP_DOWN_PED, JUMP_CUT, CAMCONTROL_OBBE); #else 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 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, OBBE_ONSTRING // actually unused... }; void CCamera::ProcessObbeCinemaCameraCar(void) { static int OldMode = -1; static int32 TimeForNext = 0; int i = 0; if(!bDidWeProcessAnyCinemaCam){ OldMode = -1; bSwitchedToObbeCam = true; } if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfCarCams[OldMode], TimeForNext)){ // This is very strange code... for(OldMode = (OldMode+1) % 14; !TryToStartNewCamMode(SequenceOfCarCams[OldMode]) && i <= 14; OldMode = (OldMode+1) % 14) i++; TimeForNext = CTimer::GetTimeInMilliseconds(); if(i >= 14){ OldMode = 14; TryToStartNewCamMode(SequenceOfCarCams[14]); } } m_iModeObbeCamIsInForCar = OldMode; 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 CCamera::ProcessObbeCinemaCameraPed(void) { // static bool bObbePedProcessed = false; // unused static int PedOldMode = -1; static int32 PedTimeForNext = 0; if(!bDidWeProcessAnyCinemaCam) PedOldMode = -1; if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfPedCams[PedOldMode], PedTimeForNext)){ for(PedOldMode = (PedOldMode+1) % 5; !TryToStartNewCamMode(SequenceOfPedCams[PedOldMode]); PedOldMode = (PedOldMode+1) % 5); PedTimeForNext = CTimer::GetTimeInMilliseconds(); } bDidWeProcessAnyCinemaCam = true; } void CCamera::DontProcessObbeCinemaCamera(void) { bDidWeProcessAnyCinemaCam = false; } #ifdef GTA_TRAIN void CCamera::LoadTrainCamNodes(char const *name) { CFileMgr::SetDir("data"); char token[16] = { 0 }; char filename[16] = { 0 }; uint8 *buf; ssize_t bufpos = 0; int field = 0; int tokpos = 0; char c; int i; ssize_t len; strcpy(filename, name); len = (int)strlen(filename); filename[len] = '.'; filename[len+1] = 'd'; filename[len+2] = 'a'; filename[len+3] = 't'; m_uiNumberOfTrainCamNodes = 0; buf = new uint8[20000]; len = CFileMgr::LoadFile(filename, buf, 20000, "r"); for(i = 0; i < MAX_NUM_OF_NODES; i++){ m_arrTrainCamNode[i].m_cvecPointToLookAt = CVector(0.0f, 0.0f, 0.0f); m_arrTrainCamNode[i].m_cvecMinPointInRange = CVector(0.0f, 0.0f, 0.0f); m_arrTrainCamNode[i].m_cvecMaxPointInRange = CVector(0.0f, 0.0f, 0.0f); m_arrTrainCamNode[i].m_fDesiredFOV = 0.0f; m_arrTrainCamNode[i].m_fNearClip = 0.0f; } while(bufpos <= len){ c = buf[bufpos]; switch(c){ case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // case '10': case '11': case '12': case '13': // ahem... token[tokpos++] = c; bufpos++; break; case ',': case ';': // game has the code for this duplicated but we handle both under the same case switch((field+14)%14){ case 0: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.x = atof(token); break; case 1: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.y = atof(token); break; case 2: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.z = atof(token); break; case 3: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.x = atof(token); break; case 4: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.y = atof(token); break; case 5: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.z = atof(token); break; case 6: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.x = atof(token); break; case 7: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.y = atof(token); break; case 8: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.z = atof(token); break; case 9: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.x = atof(token); break; case 10: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.y = atof(token); break; case 11: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.z = atof(token); break; case 12: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fDesiredFOV = atof(token); break; case 13: m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fNearClip = atof(token); m_uiNumberOfTrainCamNodes++; break; } field++; bufpos++; memset(token, 0, sizeof(token)); tokpos = 0; break; default: bufpos++; break; } } delete[] buf; CFileMgr::SetDir(""); } void CCamera::Process_Train_Camera_Control(void) { bool found = false; CTrain *target = (CTrain*)pTargetEntity; m_bUseSpecialFovTrain = true; static bool OKtoGoBackToNodeCam = true; // only ever set to true uint32 i; if(target->m_nTrackId == TRACK_ELTRAIN && !m_bAboveGroundTrainNodesLoaded){ m_bAboveGroundTrainNodesLoaded = true; m_bBelowGroundTrainNodesLoaded = false; LoadTrainCamNodes("Train"); m_uiTimeLastChange = CTimer::GetTimeInMilliseconds(); OKtoGoBackToNodeCam = true; m_iCurrentTrainCamNode = 0; } if(target->m_nTrackId == TRACK_SUBWAY && !m_bBelowGroundTrainNodesLoaded){ m_bBelowGroundTrainNodesLoaded = true; m_bAboveGroundTrainNodesLoaded = false; LoadTrainCamNodes("Train2"); m_uiTimeLastChange = CTimer::GetTimeInMilliseconds(); OKtoGoBackToNodeCam = true; m_iCurrentTrainCamNode = 0; } m_bTargetJustBeenOnTrain = true; uint32 node = m_iCurrentTrainCamNode; for(i = 0; i < m_uiNumberOfTrainCamNodes && !found; i++){ if(target->IsWithinArea(m_arrTrainCamNode[node].m_cvecMinPointInRange.x, m_arrTrainCamNode[node].m_cvecMinPointInRange.y, m_arrTrainCamNode[node].m_cvecMinPointInRange.z, m_arrTrainCamNode[node].m_cvecMaxPointInRange.x, m_arrTrainCamNode[node].m_cvecMaxPointInRange.y, m_arrTrainCamNode[node].m_cvecMaxPointInRange.z)){ m_iCurrentTrainCamNode = node; found = true; } node++; if(node >= m_uiNumberOfTrainCamNodes) node = 0; } #ifdef FIX_BUGS // Not really a bug but be nice and respect the debug mode if(DebugCamMode){ TakeControl(target, DebugCamMode, JUMP_CUT, CAMCONTROL_SCRIPT); return; } #endif if(found){ SetWideScreenOn(); if(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){ TakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT); if(target->Doors[0].IsFullyOpen()) SetWideScreenOff(); }else{ SetCamPositionForFixedMode(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecCamPosition, CVector(0.0f, 0.0f, 0.0f)); if(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.x == 999.0f && m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.y == 999.0f && m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.z == 999.0f) TakeControl(target, CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT); else TakeControlNoEntity(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt, JUMP_CUT, CAMCONTROL_SCRIPT); RwCameraSetNearClipPlane(Scene.camera, m_arrTrainCamNode[m_iCurrentTrainCamNode].m_fNearClip); } }else{ if(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){ TakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT); if(target->Doors[0].IsFullyOpen()) SetWideScreenOff(); } } } #endif void CCamera::LoadPathSplines(int file) { bool reading = true; char c, token[32] = { 0 }; int i, j, n; n = 0; DeleteCutSceneCamDataMemory(); for(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++) 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; i = 0; j = 0; while(reading){ CFileMgr::Read(file, &c, 1); switch(c){ case '\0': reading = false; break; case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'e': case 'E': token[n++] = c; break; case ',': #ifdef FIX_BUGS if(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH) #endif m_arrPathArray[i].m_arr_PathData[j] = atof(token); j++; memset(token, 0, 32); n = 0; break; case ';': #ifdef FIX_BUGS if(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH) #endif m_arrPathArray[i].m_arr_PathData[j] = atof(token); i++; j = 0; if (i == MAX_NUM_OF_SPLINETYPES) reading = false; memset(token, 0, 32); n = 0; } } } 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); m_fPositionAlongSpline = 1.0f; m_bcutsceneFinished = true; } uint32 CCamera::GetCutSceneFinishTime(void) { int cam = ActiveCam; if (Cams[cam].Mode == CCam::MODE_FLYBY) return Cams[cam].m_uiFinishTime; cam = (cam + 1) % 2; if (Cams[cam].Mode == CCam::MODE_FLYBY) return Cams[cam].m_uiFinishTime; return 0; } void CCamera::SetCamCutSceneOffSet(const CVector &pos) { m_vecCutSceneOffset = pos; }; void CCamera::SetPercentAlongCutScene(float percent) { if(Cams[ActiveCam].Mode == CCam::MODE_FLYBY) Cams[ActiveCam].m_fTimeElapsedFloat = percent/100.0f * Cams[ActiveCam].m_uiFinishTime; else if(Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FLYBY) Cams[(ActiveCam+1)%2].m_fTimeElapsedFloat = percent/100.0f * Cams[(ActiveCam+1)%2].m_uiFinishTime; } void CCamera::SetParametersForScriptInterpolation(float stopMoving, float catchUp, int32 time) { m_fScriptPercentageInterToStopMoving = stopMoving * 0.01f; m_fScriptPercentageInterToCatchUp = catchUp * 0.01f; m_fScriptTimeForInterPolation = time; m_bScriptParametersSetForInterPol = true; } void CCamera::SetZoomValueFollowPedScript(int16 dist) { switch (dist) { case 0: m_fPedZoomValueScript = 0.25f; break; case 1: m_fPedZoomValueScript = 1.5f; break; case 2: m_fPedZoomValueScript = 2.9f; break; default: break; } m_bUseScriptZoomValuePed = true; } 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 = 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 #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_fPedZoomValueScript = 0.25f; break; case 1: m_fPedZoomValueScript = 1.5f; break; case 2: m_fPedZoomValueScript = 2.9f; break; default: break; } m_bUseScriptZoomValuePed = true; } } void CCamera::SetNearClipScript(float clip) { m_fNearClipScript = clip; m_bUseNearClipScript = true; } void CCamera::ProcessFade(void) { if(m_bFading){ if(m_iFadingDirection == FADE_IN){ 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; m_fFLOATingFade = 0.0f; } }else if(m_iFadingDirection == FADE_OUT){ 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; m_fFLOATingFade = 255.0f; } } CDraw::FadeValue = m_fFLOATingFade; } } void CCamera::ProcessMusicFade(void) { if(m_bMusicFading){ if(m_iMusicFadingDirection == FADE_IN){ if(m_fTimeToFadeMusic == 0.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; } }else if(m_iMusicFadingDirection == FADE_OUT){ if(m_fTimeToFadeMusic == 0.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(127 - m_fFLOATingFadeMusic/255.0f * 127); DMAudio.SetMusicFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127); } } void CCamera::Fade(float timeout, int16 direction) { m_bFading = true; m_iFadingDirection = direction; m_fTimeToFadeOut = timeout; m_uiFadeTimeStarted = CTimer::GetTimeInMilliseconds(); if(!m_bIgnoreFadingStuffForMusic){ m_bMusicFading = true; m_iMusicFadingDirection = direction; m_fTimeToFadeMusic = timeout; m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds(); } } void CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b) { m_FadeTargetIsSplashScreen = r == 2 && g == 2 && b == 2; CDraw::FadeRed = r; CDraw::FadeGreen = g; CDraw::FadeBlue = b; } bool CCamera::GetFading(void) { return m_bFading; } int CCamera::GetFadingDirection(void) { if(m_bFading) return m_iFadingDirection == FADE_IN ? FADE_IN : FADE_OUT; else return FADE_NONE; } int CCamera::GetScreenFadeStatus(void) { if(m_fFLOATingFade == 0.0f) return FADE_0; if(m_fFLOATingFade == 255.0f) return FADE_2; return FADE_1; } //--LCS: TODO void CCamera::RenderMotionBlur(void) { if(m_BlurType == 0) return; CMBlur::MotionBlurRender(m_pRwCamera, m_BlurRed, m_BlurGreen, m_BlurBlue, // m_motionBlur, m_BlurType, m_imotionBlurAddAlpha); m_motionBlur, m_BlurType, 32); // hack hack } void CCamera::SetMotionBlur(int r, int g, int b, int a, int type) { m_BlurRed = r; m_BlurGreen = g; m_BlurBlue = b; m_motionBlur = a; m_BlurType = type; } void CCamera::SetMotionBlurAlpha(int a) { m_imotionBlurAddAlpha = a; } int CCamera::GetLookDirection(void) { if(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING || Cams[ActiveCam].Mode == CCam::MODE_1STPERSON || Cams[ActiveCam].Mode == CCam::MODE_BEHINDBOAT || Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED) return Cams[ActiveCam].DirectionWasLooking; return LOOKING_FORWARD; } bool CCamera::GetLookingForwardFirstPerson(void) { return Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && Cams[ActiveCam].DirectionWasLooking == LOOKING_FORWARD; } bool CCamera::GetLookingLRBFirstPerson(void) { return Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD; } void CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString(void) { m_bCamDirectlyBehind = true; CPlayerPed *player = FindPlayerPed(); if (player) m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y); } void CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString(void) { m_bCamDirectlyInFront = true; CPlayerPed *player = FindPlayerPed(); if (player) m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y); } 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; PlayerWeaponMode.Duration = 0.0f; } 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; PlayerWeaponMode.Duration = 0.0f; } void CCamera::UpdateAimingCoors(CVector const &coors) { m_cvecAimingTargetCoors = coors; } bool CCamera::Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target) { if(CPad::GetPad(0)->GetLookBehindForPed()){ source = pos; target = dist*Cams[ActiveCam].CamTargetEntity->GetForward() + source; return false; }else{ float angleX = DEGTORAD((m_f3rdPersonCHairMultX-0.5f) * 1.8f * 0.5f * Cams[ActiveCam].FOV * CDraw::GetAspectRatio()); float angleY = DEGTORAD((0.5f-m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV); source = Cams[ActiveCam].Source; target = Cams[ActiveCam].Front; target += Cams[ActiveCam].Up * Tan(angleY); target += CrossProduct(Cams[ActiveCam].Front, Cams[ActiveCam].Up) * Tan(angleX); target.Normalise(); source += DotProduct(pos - source, target)*target; target = dist*target + source; return true; } } float CCamera::Find3rdPersonQuickAimPitch(void) { float clampedFrontZ = clamp(Cams[ActiveCam].Front.z, -1.0f, 1.0f); float rot = Asin(clampedFrontZ); 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 CCamera::SetRwCamera(RwCamera *cam) { m_pRwCamera = cam; m_viewMatrix.Attach(RwCameraGetViewMatrix(m_pRwCamera), false); CMBlur::MotionBlurOpen(m_pRwCamera); } void CCamera::CalculateDerivedValues(void) { m_cameraMatrix = Invert(m_matrix); float hfov = DEGTORAD(CDraw::GetScaledFOV()/2.0f); float c = Cos(hfov); float s = Sin(hfov); // right plane m_vecFrustumNormals[0] = CVector(c, -s, 0.0f); // left plane m_vecFrustumNormals[1] = CVector(-c, -s, 0.0f); CDraw::CalculateAspectRatio(); c /= SCREEN_ASPECT_RATIO; s /= SCREEN_ASPECT_RATIO; // bottom plane m_vecFrustumNormals[2] = CVector(0.0f, -s, -c); // top plane m_vecFrustumNormals[3] = CVector(0.0f, -s, c); if(GetForward().x == 0.0f && GetForward().y == 0.0f) GetForward().x = 0.0001f; else Orientation = Atan2(GetForward().x, GetForward().y); CamFrontXNorm = GetForward().x; CamFrontYNorm = GetForward().y; float l = Sqrt(SQR(CamFrontXNorm) + SQR(CamFrontYNorm)); if(l == 0.0f) CamFrontXNorm = 1.0f; else{ CamFrontXNorm /= l; CamFrontYNorm /= l; } } bool CCamera::IsPointVisible(const CVector ¢er, const CMatrix *mat) { RwV3d c; c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y < CDraw::GetNearClipZ()) return false; if(c.y > CDraw::GetFarClipZ()) return false; if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false; if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > 0.0f) return false; if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > 0.0f) return false; if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > 0.0f) return false; return true; } bool CCamera::IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat) { RwV3d c; c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y + radius < CDraw::GetNearClipZ()) return false; if(c.y - radius > CDraw::GetFarClipZ()) return false; if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false; if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > radius) return false; if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > radius) return false; if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > radius) return false; return true; } bool CCamera::IsSphereVisible(const CVector ¢er, float radius) { CMatrix mat = m_cameraMatrix; return IsSphereVisible(center, radius, &mat); } bool CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat) { int i; int frustumTests[6] = { 0 }; RwV3dTransformPoints(box, box, 8, &mat->m_matrix); for(i = 0; i < 8; i++){ if(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++; if(box[i].y > CDraw::GetFarClipZ()) frustumTests[1]++; if(box[i].x*m_vecFrustumNormals[0].x + box[i].y*m_vecFrustumNormals[0].y > 0.0f) frustumTests[2]++; if(box[i].x*m_vecFrustumNormals[1].x + box[i].y*m_vecFrustumNormals[1].y > 0.0f) frustumTests[3]++; // Why not test z? // if(box[i].y*m_vecFrustumNormals[2].y + box[i].z*m_vecFrustumNormals[2].z > 0.0f) frustumTests[4]++; // if(box[i].y*m_vecFrustumNormals[3].y + box[i].z*m_vecFrustumNormals[3].z > 0.0f) frustumTests[5]++; } for(i = 0; i < 6; i++) if(frustumTests[i] == 8) return false; // Box is completely outside of one plane return true; } CCamPathSplines::CCamPathSplines(void) { m_arr_PathData = nil; }