summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-03-27 18:41:22 +0100
committerGitHub <noreply@github.com>2020-03-27 18:41:22 +0100
commit29f69f6216fa629786415e8062ceab3d671ac912 (patch)
treea59a5d54c5a33cdc1c5bd91535331ec2b5955472
parentMerge pull request #356 from blingu/master (diff)
parentimplemented some unused PS2 cams (diff)
downloadre3-29f69f6216fa629786415e8062ceab3d671ac912.tar
re3-29f69f6216fa629786415e8062ceab3d671ac912.tar.gz
re3-29f69f6216fa629786415e8062ceab3d671ac912.tar.bz2
re3-29f69f6216fa629786415e8062ceab3d671ac912.tar.lz
re3-29f69f6216fa629786415e8062ceab3d671ac912.tar.xz
re3-29f69f6216fa629786415e8062ceab3d671ac912.tar.zst
re3-29f69f6216fa629786415e8062ceab3d671ac912.zip
-rw-r--r--README.md1
-rw-r--r--src/control/SceneEdit.cpp5
-rw-r--r--src/control/SceneEdit.h5
-rw-r--r--src/core/Cam.cpp4424
-rw-r--r--src/core/Camera.cpp1171
-rw-r--r--src/core/Camera.h121
-rw-r--r--src/core/Debug.cpp46
-rw-r--r--src/core/Debug.h14
-rw-r--r--src/core/Pad.h6
-rw-r--r--src/core/World.cpp71
-rw-r--r--src/core/World.h6
-rw-r--r--src/core/config.h2
-rw-r--r--src/core/main.cpp1
-rw-r--r--src/core/re3.cpp39
-rw-r--r--src/peds/Ped.cpp4
-rw-r--r--src/render/Font.cpp2
-rw-r--r--src/render/Hud.cpp39
-rw-r--r--src/render/Renderer.cpp6
18 files changed, 4695 insertions, 1268 deletions
diff --git a/README.md b/README.md
index 6e8f717c..3c394e62 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,6 @@ CBoat
CBrightLights
CBulletInfo
CBulletTraces
-CCam
CCamera
CCopPed
CCrane
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
index 28b4ea6c..4c05e11b 100644
--- a/src/control/SceneEdit.cpp
+++ b/src/control/SceneEdit.cpp
@@ -2,5 +2,10 @@
#include "patcher.h"
#include "SceneEdit.h"
+int32 &CSceneEdit::m_bCameraFollowActor = *(int*)0x940590;
+bool &CSceneEdit::m_bRecording = *(bool*)0x95CD1F;
+CVector &CSceneEdit::m_vecCurrentPosition = *(CVector*)0x943064;
+CVector &CSceneEdit::m_vecCamHeading = *(CVector*)0x942F8C;
+
WRAPPER void CSceneEdit::Update(void) { EAXJMP(0x585570); }
WRAPPER void CSceneEdit::Init(void) { EAXJMP(0x585170); }
diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h
index e9209b90..ec321b27 100644
--- a/src/control/SceneEdit.h
+++ b/src/control/SceneEdit.h
@@ -3,6 +3,11 @@
class CSceneEdit
{
public:
+ static int32 &m_bCameraFollowActor;
+ static bool &m_bRecording;
+ static CVector &m_vecCurrentPosition;
+ static CVector &m_vecCamHeading;
+
static void Update(void);
static void Init(void);
};
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
new file mode 100644
index 00000000..12c72993
--- /dev/null
+++ b/src/core/Cam.cpp
@@ -0,0 +1,4424 @@
+#include "common.h"
+#include "patcher.h"
+#include "main.h"
+#include "Draw.h"
+#include "World.h"
+#include "Vehicle.h"
+#include "Automobile.h"
+#include "Ped.h"
+#include "PlayerPed.h"
+#include "CopPed.h"
+#include "RpAnimBlend.h"
+#include "ControllerConfig.h"
+#include "Pad.h"
+#include "Frontend.h"
+#include "General.h"
+#include "Renderer.h"
+#include "Shadows.h"
+#include "Hud.h"
+#include "ZoneCull.h"
+#include "SurfaceTable.h"
+#include "WaterLevel.h"
+#include "MBlur.h"
+#include "SceneEdit.h"
+#include "Debug.h"
+#include "Camera.h"
+
+const float DefaultFOV = 70.0f; // beta: 80.0f
+
+bool PrintDebugCode = false;
+int16 &DebugCamMode = *(int16*)0x95CCF2;
+
+void
+CCam::Init(void)
+{
+ Mode = MODE_FOLLOWPED;
+ Front = CVector(0.0f, 0.0f, -1.0f);
+ Up = CVector(0.0f, 0.0f, 1.0f);
+ Rotating = 0;
+ m_iDoCollisionChecksOnFrameNum = 1;
+ m_iDoCollisionCheckEveryNumOfFrames = 9;
+ m_iFrameNumWereAt = 0;
+ m_bCollisionChecksOn = 1;
+ m_fRealGroundDist = 0.0f;
+ BetaSpeed = 0.0f;
+ AlphaSpeed = 0.0f;
+ DistanceSpeed = 0.0f;
+ f_max_role_angle = DEGTORAD(5.0f);
+ Distance = 30.0f;
+ DistanceSpeed = 0.0f;
+ m_pLastCarEntered = 0;
+ m_pLastPedLookedAt = 0;
+ ResetStatics = 1;
+ Beta = 0.0f;
+ m_bFixingBeta = 0;
+ CA_MIN_DISTANCE = 0.0f;
+ CA_MAX_DISTANCE = 0.0f;
+ LookingBehind = 0;
+ LookingLeft = 0;
+ LookingRight = 0;
+ m_fPlayerInFrontSyphonAngleOffSet = DEGTORAD(20.0f);
+ m_fSyphonModeTargetZOffSet = 0.5f;
+ m_fRadiusForDead = 1.5f;
+ DirectionWasLooking = LOOKING_FORWARD;
+ LookBehindCamWasInFront = 0;
+ f_Roll = 0.0f;
+ f_rollSpeed = 0.0f;
+ m_fCloseInPedHeightOffset = 0.0f;
+ m_fCloseInPedHeightOffsetSpeed = 0.0f;
+ m_fCloseInCarHeightOffset = 0.0f;
+ m_fCloseInCarHeightOffsetSpeed = 0.0f;
+ m_fPedBetweenCameraHeightOffset = 0.0f;
+ m_fTargetBeta = 0.0f;
+ m_fBufferedTargetBeta = 0.0f;
+ m_fBufferedTargetOrientation = 0.0f;
+ m_fBufferedTargetOrientationSpeed = 0.0f;
+ m_fDimensionOfHighestNearCar = 0.0f;
+ m_fRoadOffSet = 0.0f;
+}
+
+void
+CCam::Process(void)
+{
+ CVector CameraTarget;
+ float TargetSpeedVar = 0.0f;
+ float TargetOrientation = 0.0f;
+
+ if(CamTargetEntity == nil)
+ CamTargetEntity = TheCamera.pTargetEntity;
+
+ m_iFrameNumWereAt++;
+ if(m_iFrameNumWereAt > m_iDoCollisionCheckEveryNumOfFrames)
+ m_iFrameNumWereAt = 1;
+ m_bCollisionChecksOn = m_iFrameNumWereAt == m_iDoCollisionChecksOnFrameNum;
+
+ if(m_bCamLookingAtVector){
+ CameraTarget = m_cvecCamFixedModeVector;
+ }else if(CamTargetEntity->IsVehicle()){
+ CameraTarget = CamTargetEntity->GetPosition();
+
+ if(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)
+ TargetOrientation = 0.0f;
+ else
+ TargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);
+
+ CVector Fwd(0.0f, 0.0f, 0.0f);
+ Fwd.x = CamTargetEntity->GetForward().x;
+ Fwd.y = CamTargetEntity->GetForward().y;
+ Fwd.Normalise();
+ // Game normalizes again here manually. useless, so skipped
+
+ float FwdSpeedX = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().x * Fwd.x;
+ float FwdSpeedY = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().y * Fwd.y;
+ if(FwdSpeedX + FwdSpeedY > 0.0f)
+ TargetSpeedVar = min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/0.9f, 1.0f);
+ else
+ TargetSpeedVar = -min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f);
+ SpeedVar = 0.895f*SpeedVar + 0.105*TargetSpeedVar;
+ }else{
+ CameraTarget = CamTargetEntity->GetPosition();
+
+ if(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)
+ TargetOrientation = 0.0f;
+ else
+ TargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);
+ TargetSpeedVar = 0.0f;
+ SpeedVar = 0.0f;
+ }
+
+ switch(Mode){
+ case MODE_TOPDOWN:
+ case MODE_GTACLASSIC:
+ Process_TopDown(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_BEHINDCAR:
+ Process_BehindCar(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_FOLLOWPED:
+ if(CCamera::m_bUseMouse3rdPerson)
+ Process_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ else
+ Process_FollowPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+// case MODE_AIMING:
+ case MODE_DEBUG:
+ Process_Debug(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_SNIPER:
+ Process_Sniper(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_ROCKETLAUNCHER:
+ Process_Rocket(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_MODELVIEW:
+ Process_ModelView(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+// case MODE_BILL:
+ case MODE_SYPHON:
+ Process_Syphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_CIRCLE:
+ Process_Circle(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+// case MODE_CHEESYZOOM:
+ case MODE_WHEELCAM:
+ Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_FIXED:
+ Process_Fixed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_1STPERSON:
+ Process_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_FLYBY:
+ Process_FlyBy(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_CAM_ON_A_STRING:
+ Process_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_REACTION:
+ Process_ReactionCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_FOLLOW_PED_WITH_BIND:
+ Process_FollowPed_WithBinding(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_CHRIS:
+ Process_Chris_With_Binding_PlusRotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_BEHINDBOAT:
+ Process_BehindBoat(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_PLAYER_FALLEN_WATER:
+ Process_Player_Fallen_Water(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+// case MODE_CAM_ON_TRAIN_ROOF:
+// case MODE_CAM_RUNNING_SIDE_TRAIN:
+// case MODE_BLOOD_ON_THE_TRACKS:
+// case MODE_IM_THE_PASSENGER_WOOWOO:
+ case MODE_SYPHON_CRIM_IN_FRONT:
+ Process_Syphon_Crim_In_Front(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_PED_DEAD_BABY:
+ ProcessPedsDeadBaby();
+ break;
+// case MODE_PILLOWS_PAPS:
+// case MODE_LOOK_AT_CARS:
+ case MODE_ARRESTCAM_ONE:
+ ProcessArrestCamOne();
+ break;
+ case MODE_ARRESTCAM_TWO:
+ ProcessArrestCamTwo();
+ break;
+ case MODE_M16_1STPERSON:
+ case MODE_HELICANNON_1STPERSON: // miami
+ Process_M16_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_SPECIAL_FIXED_FOR_SYPHON:
+ Process_SpecialFixedForSyphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_FIGHT_CAM:
+ Process_Fight_Cam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_TOP_DOWN_PED:
+ Process_TopDownPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_SNIPER_RUNABOUT:
+ case MODE_ROCKETLAUNCHER_RUNABOUT:
+ case MODE_1STPERSON_RUNABOUT:
+ case MODE_M16_1STPERSON_RUNABOUT:
+ case MODE_FIGHT_CAM_RUNABOUT:
+ Process_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ case MODE_EDITOR:
+ Process_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
+ break;
+ default:
+ Source = CVector(0.0f, 0.0f, 0.0f);
+ Front = CVector(0.0f, 1.0f, 0.0f);
+ Up = CVector(0.0f, 0.0f, 1.0f);
+ }
+
+ CVector TargetToCam = Source - m_cvecTargetCoorsForFudgeInter;
+ float DistOnGround = TargetToCam.Magnitude2D();
+ m_fTrueBeta = CGeneral::GetATanOfXY(TargetToCam.x, TargetToCam.y);
+ m_fTrueAlpha = CGeneral::GetATanOfXY(TargetToCam.z, DistOnGround);
+ if(TheCamera.m_uiTransitionState == 0) // TODO? what values are possible? enum?
+ KeepTrackOfTheSpeed(Source, m_cvecTargetCoorsForFudgeInter, Up, m_fTrueAlpha, m_fTrueBeta, FOV);
+
+ // Look Behind, Left, Right
+ LookingBehind = false;
+ LookingLeft = false;
+ LookingRight = false;
+ SourceBeforeLookBehind = Source;
+ if(&TheCamera.Cams[TheCamera.ActiveCam] == this){
+ if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_1STPERSON || Mode == MODE_BEHINDBOAT) &&
+ CamTargetEntity->IsVehicle()){
+ if(CPad::GetPad(0)->GetLookBehindForCar()){
+ LookBehind();
+ if(DirectionWasLooking != LOOKING_BEHIND)
+ TheCamera.m_bJust_Switched = true;
+ DirectionWasLooking = LOOKING_BEHIND;
+ }else if(CPad::GetPad(0)->GetLookLeft()){
+ LookLeft();
+ if(DirectionWasLooking != LOOKING_LEFT)
+ TheCamera.m_bJust_Switched = true;
+ DirectionWasLooking = LOOKING_LEFT;
+ }else if(CPad::GetPad(0)->GetLookRight()){
+ LookRight();
+ if(DirectionWasLooking != LOOKING_RIGHT)
+ TheCamera.m_bJust_Switched = true;
+ DirectionWasLooking = LOOKING_RIGHT;
+ }else{
+ if(DirectionWasLooking != LOOKING_FORWARD)
+ TheCamera.m_bJust_Switched = true;
+ DirectionWasLooking = LOOKING_FORWARD;
+ }
+ }
+ if(Mode == MODE_FOLLOWPED && CamTargetEntity->IsPed()){
+ if(CPad::GetPad(0)->GetLookBehindForPed()){
+ LookBehind();
+ if(DirectionWasLooking != LOOKING_BEHIND)
+ TheCamera.m_bJust_Switched = true;
+ DirectionWasLooking = LOOKING_BEHIND;
+ }else
+ DirectionWasLooking = LOOKING_FORWARD;
+ }
+ }
+
+ if(Mode == MODE_SNIPER || Mode == MODE_ROCKETLAUNCHER || Mode == MODE_M16_1STPERSON ||
+ Mode == MODE_1STPERSON || Mode == MODE_HELICANNON_1STPERSON || GetWeaponFirstPersonOn())
+ ClipIfPedInFrontOfPlayer();
+}
+
+// MaxSpeed is a limit of how fast the value is allowed to change. 1.0 = to Target in up to 1ms
+// Acceleration is how fast the speed will change to MaxSpeed. 1.0 = to MaxSpeed in 1ms
+void
+WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle)
+{
+ float Delta = Target - *CurrentValue;
+
+ if(IsAngle){
+ while(Delta >= PI) Delta -= 2*PI;
+ while(Delta < -PI) Delta += 2*PI;
+ }
+
+ float TargetSpeed = Delta * MaxSpeed;
+ // Add or subtract absolute depending on sign, genius!
+// if(TargetSpeed - *CurrentSpeed > 0.0f)
+// *CurrentSpeed += Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
+// else
+// *CurrentSpeed -= Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
+ // this is simpler:
+ *CurrentSpeed += Acceleration * (TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
+
+ // Clamp speed if we overshot
+ if(TargetSpeed < 0.0f && *CurrentSpeed < TargetSpeed)
+ *CurrentSpeed = TargetSpeed;
+ else if(TargetSpeed > 0.0f && *CurrentSpeed > TargetSpeed)
+ *CurrentSpeed = TargetSpeed;
+
+ *CurrentValue += *CurrentSpeed * min(10.0f, CTimer::GetTimeStep());
+}
+
+void
+MakeAngleLessThan180(float &Angle)
+{
+ while(Angle >= PI) Angle -= 2*PI;
+ while(Angle < -PI) Angle += 2*PI;
+}
+
+void
+CCam::ProcessSpecialHeightRoutines(void)
+{
+ int i = 0;
+ bool StandingOnBoat = false;
+ static bool PreviouslyFailedRoadHeightCheck = false;
+ CVector CamToTarget, CamToPed;
+ float DistOnGround, BetaAngle;
+ CPed *Player;
+ int ClosestPed = 0;
+ bool FoundPed = false;
+ float ClosestPedDist, PedZDist;
+ CColPoint colPoint;
+
+ CamToTarget = TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();
+ DistOnGround = CamToTarget.Magnitude2D();
+ BetaAngle = CGeneral::GetATanOfXY(CamToTarget.x, CamToTarget.y);
+ m_bTheHeightFixerVehicleIsATrain = false;
+ ClosestPedDist = 0.0f;
+ // CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);
+ Player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+
+ if(DistOnGround > 10.0f)
+ DistOnGround = 10.0f;
+
+ if(CamTargetEntity && CamTargetEntity->IsPed()){
+ if(FindPlayerPed()->m_pCurSurface && FindPlayerPed()->m_pCurSurface->IsVehicle() &&
+ ((CVehicle*)FindPlayerPed()->m_pCurSurface)->IsBoat())
+ StandingOnBoat = true;
+
+ // Move up the camera if there is a ped close to it
+ if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM){
+ // Find ped closest to camera
+ while(i < Player->m_numNearPeds){
+ if(Player->m_nearPeds[i] && Player->m_nearPeds[i]->GetPedState() != PED_DEAD){
+ CamToPed = Player->m_nearPeds[i]->GetPosition() - TheCamera.GetGameCamPosition();
+ if(FoundPed){
+ if(CamToPed.Magnitude2D() < ClosestPedDist){
+ ClosestPed = i;
+ ClosestPedDist = CamToPed.Magnitude2D();
+ }
+ }else{
+ FoundPed = true;
+ ClosestPed = i;
+ ClosestPedDist = CamToPed.Magnitude2D();
+ }
+ }
+ i++;
+ }
+
+ if(FoundPed){
+ float Offset = 0.0f;
+ CPed *Ped = Player->m_nearPeds[ClosestPed];
+ CamToPed = Ped->GetPosition() - TheCamera.GetGameCamPosition();
+ PedZDist = 0.0f;
+ float dist = CamToPed.Magnitude2D(); // should be same as ClosestPedDist
+ if(dist < 2.1f){
+ // Ped is close to camera, move up
+
+ // Z Distance between player and close ped
+ PedZDist = 0.0f;
+ if(Ped->bIsStanding)
+ PedZDist = Ped->GetPosition().z - Player->GetPosition().z;
+ // Ignore if too distant
+ if(PedZDist > 1.2f || PedZDist < -1.2f)
+ PedZDist = 0.0f;
+
+ float DistScale = (2.1f - dist)/2.1f;
+ if(Mode == MODE_FOLLOWPED){
+ if(TheCamera.PedZoomIndicator == 1.0f)
+ Offset = 0.45*DistScale + PedZDist;
+ if(TheCamera.PedZoomIndicator == 2.0f)
+ Offset = 0.35*DistScale + PedZDist;
+ if(TheCamera.PedZoomIndicator == 3.0f)
+ Offset = 0.25*DistScale + PedZDist;
+ if(Abs(CGeneral::GetRadianAngleBetweenPoints(CamToPed.x, CamToPed.y, CamToTarget.x, CamToTarget.y)) > HALFPI)
+ Offset += 0.3f;
+ m_fPedBetweenCameraHeightOffset = Offset + 1.3f;
+ PedZDist = 0.0f;
+ }else if(Mode == MODE_FIGHT_CAM)
+ m_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.5f;
+ }else
+ m_fPedBetweenCameraHeightOffset = 0.0f;
+ }else{
+ PedZDist = 0.0f;
+ m_fPedBetweenCameraHeightOffset = 0.0f;
+ }
+ }else
+ PedZDist = 0.0f;
+
+
+ // Move camera up for vehicles in the way
+ if(m_bCollisionChecksOn && (Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM)){
+ bool FoundCar = false;
+ CEntity *vehicle = nil;
+ float TestDist = DistOnGround + 1.25f;
+ float HighestCar = 0.0f;
+ CVector TestBase = CamTargetEntity->GetPosition();
+ CVector TestPoint;
+ TestBase.z -= 0.15f;
+
+ TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f);
+ if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
+ vehicle->IsVehicle()){
+ float height = vehicle->GetColModel()->boundingBox.GetSize().z;
+ FoundCar = true;
+ HighestCar = height;
+ if(((CVehicle*)vehicle)->IsTrain())
+ m_bTheHeightFixerVehicleIsATrain = true;
+ }
+
+ TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle+DEGTORAD(28.0f)), Sin(BetaAngle+DEGTORAD(28.0f)), 0.0f);
+ if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
+ vehicle->IsVehicle()){
+ float height = vehicle->GetColModel()->boundingBox.GetSize().z;
+ if(FoundCar){
+ HighestCar = max(HighestCar, height);
+ }else{
+ FoundCar = true;
+ HighestCar = height;
+ }
+ if(((CVehicle*)vehicle)->IsTrain())
+ m_bTheHeightFixerVehicleIsATrain = true;
+ }
+
+ TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle-DEGTORAD(28.0f)), Sin(BetaAngle-DEGTORAD(28.0f)), 0.0f);
+ if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
+ vehicle->IsVehicle()){
+ float height = vehicle->GetColModel()->boundingBox.GetSize().z;
+ if(FoundCar){
+ HighestCar = max(HighestCar, height);
+ }else{
+ FoundCar = true;
+ HighestCar = height;
+ }
+ if(((CVehicle*)vehicle)->IsTrain())
+ m_bTheHeightFixerVehicleIsATrain = true;
+ }
+
+ if(FoundCar){
+ m_fDimensionOfHighestNearCar = HighestCar + 0.1f;
+ if(Mode == MODE_FIGHT_CAM)
+ m_fDimensionOfHighestNearCar += 0.75f;
+ }else
+ m_fDimensionOfHighestNearCar = 0.0f;
+ }
+
+ // Move up for road
+ if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM ||
+ Mode == MODE_SYPHON || Mode == MODE_SYPHON_CRIM_IN_FRONT || Mode == MODE_SPECIAL_FIXED_FOR_SYPHON){
+ bool Inside = false;
+ bool OnRoad = false;
+
+ switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched)
+ case SURFACE_GRASS:
+ case SURFACE_DIRT:
+ case SURFACE_DIRTTRACK:
+ case SURFACE_STEEL:
+ case SURFACE_TIRE:
+ case SURFACE_STONE:
+ OnRoad = true;
+
+ if(CCullZones::PlayerNoRain())
+ Inside = true;
+
+ if((m_bCollisionChecksOn || PreviouslyFailedRoadHeightCheck || OnRoad) &&
+ m_fCloseInPedHeightOffset < 0.0001f && !Inside){
+ CVector TestPoint;
+ CEntity *road;
+ float GroundZ = 0.0f;
+ bool FoundGround = false;
+ float RoofZ = 0.0f;
+ bool FoundRoof = false;
+ static float MinHeightAboveRoad = 0.9f;
+
+ TestPoint = CamTargetEntity->GetPosition() - DistOnGround * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f);
+ m_fRoadOffSet = 0.0f;
+
+ if(CWorld::ProcessVerticalLine(TestPoint, -1000.0f, colPoint, road, true, false, false, false, false, false, nil)){
+ FoundGround = true;
+ GroundZ = colPoint.point.z;
+ }
+ // Move up if too close to ground
+ if(FoundGround){
+ if(TestPoint.z - GroundZ < MinHeightAboveRoad){
+ m_fRoadOffSet = GroundZ + MinHeightAboveRoad - TestPoint.z;
+ PreviouslyFailedRoadHeightCheck = true;
+ }else{
+ if(m_bCollisionChecksOn)
+ PreviouslyFailedRoadHeightCheck = false;
+ else
+ m_fRoadOffSet = 0.0f;
+ }
+ }else{
+ if(CWorld::ProcessVerticalLine(TestPoint, 1000.0f, colPoint, road, true, false, false, false, false, false, nil)){
+ FoundRoof = true;
+ RoofZ = colPoint.point.z;
+ }
+ if(FoundRoof){
+ if(TestPoint.z - RoofZ < MinHeightAboveRoad){
+ m_fRoadOffSet = RoofZ + MinHeightAboveRoad - TestPoint.z;
+ PreviouslyFailedRoadHeightCheck = true;
+ }else{
+ if(m_bCollisionChecksOn)
+ PreviouslyFailedRoadHeightCheck = false;
+ else
+ m_fRoadOffSet = 0.0f;
+ }
+ }
+ }
+ }
+ }
+
+ if(PreviouslyFailedRoadHeightCheck && m_fCloseInPedHeightOffset < 0.0001f){
+ if(colPoint.surfaceB != SURFACE_TARMAC &&
+ colPoint.surfaceB != SURFACE_GRASS &&
+ colPoint.surfaceB != SURFACE_DIRT &&
+ colPoint.surfaceB != SURFACE_DIRTTRACK &&
+ colPoint.surfaceB != SURFACE_STONE){
+ if(m_fRoadOffSet > 1.4f)
+ m_fRoadOffSet = 1.4f;
+ }else{
+ if(Mode == MODE_FOLLOWPED){
+ if(TheCamera.PedZoomIndicator == 1.0f)
+ m_fRoadOffSet += 0.2f;
+ if(TheCamera.PedZoomIndicator == 2.0f)
+ m_fRoadOffSet += 0.5f;
+ if(TheCamera.PedZoomIndicator == 3.0f)
+ m_fRoadOffSet += 0.95f;
+ }
+ }
+ }
+ }
+
+ if(StandingOnBoat){
+ m_fRoadOffSet = 0.0f;
+ m_fDimensionOfHighestNearCar = 1.0f;
+ m_fPedBetweenCameraHeightOffset = 0.0f;
+ }
+}
+
+void
+CCam::GetVectorsReadyForRW(void)
+{
+ CVector right;
+ Up = CVector(0.0f, 0.0f, 1.0f);
+ Front.Normalise();
+ if(Front.x == 0.0f && Front.y == 0.0f){
+ Front.x = 0.0001f;
+ Front.y = 0.0001f;
+ }
+ right = CrossProduct(Front, Up);
+ right.Normalise();
+ Up = CrossProduct(right, Front);
+}
+
+void
+CCam::LookBehind(void)
+{
+ float Dist, DeltaBeta, TargetOrientation, Angle;
+ CVector TargetCoors, TargetFwd, TestCoors;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ TargetCoors = CamTargetEntity->GetPosition();
+ Front = CamTargetEntity->GetPosition() - Source;
+
+ if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
+ LookingBehind = true;
+ Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 15.5f;
+ TargetFwd = CamTargetEntity->GetForward();
+ TargetFwd.Normalise();
+ TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
+ DeltaBeta = TargetOrientation - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(DirectionWasLooking == LOOKING_BEHIND)
+ LookBehindCamWasInFront = DeltaBeta <= -HALFPI || DeltaBeta >= HALFPI;
+ if(LookBehindCamWasInFront)
+ TargetOrientation += PI;
+ Source.x = Dist*Cos(TargetOrientation) + TargetCoors.x;
+ Source.y = Dist*Sin(TargetOrientation) + TargetCoors.y;
+ Source.z -= 1.0f;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ Source = colPoint.point;
+ }
+ Source.z += 1.0f;
+ Front = CamTargetEntity->GetPosition() - Source;
+ GetVectorsReadyForRW();
+ }
+ if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
+ LookingBehind = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.25f);
+ Front = CamTargetEntity->GetForward();
+ Front.Normalise();
+ if(((CVehicle*)CamTargetEntity)->IsBoat())
+ Source.z -= 0.5f;
+ Source += 0.25f*Front;
+ Front = -Front;
+#ifdef FIX_BUGS
+ // not sure if this is a bug...
+ GetVectorsReadyForRW();
+#endif
+ }
+ if(CamTargetEntity->IsPed()){
+ Angle = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y) + PI;
+ Source.x = 4.5f*Cos(Angle) + TargetCoors.x;
+ Source.y = 4.5f*Sin(Angle) + TargetCoors.y;
+ Source.z = 1.15f + TargetCoors.z;
+ TestCoors = TargetCoors;
+ TestCoors.z = Source.z;
+ if(CWorld::ProcessLineOfSight(TestCoors, Source, colPoint, entity, true, true, false, true, false, true, true)){
+ Source.x = colPoint.point.x;
+ Source.y = colPoint.point.y;
+ if((TargetCoors - Source).Magnitude2D() < 1.15f)
+ RwCameraSetNearClipPlane(Scene.camera, 0.05f);
+ }
+ Front = TargetCoors - Source;
+ GetVectorsReadyForRW();
+ }
+}
+
+void
+CCam::LookLeft(void)
+{
+ float Dist, TargetOrientation;
+ CVector TargetCoors, TargetFwd;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
+ LookingLeft = true;
+ TargetCoors = CamTargetEntity->GetPosition();
+ Front = CamTargetEntity->GetPosition() - Source;
+ Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f;
+ TargetFwd = CamTargetEntity->GetForward();
+ TargetFwd.Normalise();
+ TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
+ Source.x = Dist*Cos(TargetOrientation - HALFPI) + TargetCoors.x;
+ Source.y = Dist*Sin(TargetOrientation - HALFPI) + TargetCoors.y;
+ Source.z -= 1.0f;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source = colPoint.point;
+ }
+ Source.z += 1.0f;
+ Front = CamTargetEntity->GetPosition() - Source;
+ Front.z += 1.1f;
+ if(Mode == MODE_BEHINDBOAT)
+ Front.z += 1.2f;
+ GetVectorsReadyForRW();
+ }
+ if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
+ LookingLeft = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.25f);
+ if(((CVehicle*)CamTargetEntity)->IsBoat())
+ Source.z -= 0.5f;
+
+ Up = CamTargetEntity->GetUp();
+ Up.Normalise();
+ Front = CamTargetEntity->GetForward();
+ Front.Normalise();
+ Front = -CrossProduct(Front, Up);
+ Front.Normalise();
+#ifdef FIX_BUGS
+ // not sure if this is a bug...
+ GetVectorsReadyForRW();
+#endif
+ }
+}
+
+void
+CCam::LookRight(void)
+{
+ float Dist, TargetOrientation;
+ CVector TargetCoors, TargetFwd;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
+ LookingRight = true;
+ TargetCoors = CamTargetEntity->GetPosition();
+ Front = CamTargetEntity->GetPosition() - Source;
+ Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f;
+ TargetFwd = CamTargetEntity->GetForward();
+ TargetFwd.Normalise();
+ TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
+ Source.x = Dist*Cos(TargetOrientation + HALFPI) + TargetCoors.x;
+ Source.y = Dist*Sin(TargetOrientation + HALFPI) + TargetCoors.y;
+ Source.z -= 1.0f;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source = colPoint.point;
+ }
+ Source.z += 1.0f;
+ Front = CamTargetEntity->GetPosition() - Source;
+ Front.z += 1.1f;
+ if(Mode == MODE_BEHINDBOAT)
+ Front.z += 1.2f;
+ GetVectorsReadyForRW();
+ }
+ if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
+ LookingRight = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.25f);
+ if(((CVehicle*)CamTargetEntity)->IsBoat())
+ Source.z -= 0.5f;
+
+ Up = CamTargetEntity->GetUp();
+ Up.Normalise();
+ Front = CamTargetEntity->GetForward();
+ Front.Normalise();
+ Front = CrossProduct(Front, Up);
+ Front.Normalise();
+#ifdef FIX_BUGS
+ // not sure if this is a bug...
+ GetVectorsReadyForRW();
+#endif
+ }
+}
+
+void
+CCam::ClipIfPedInFrontOfPlayer(void)
+{
+ float FwdAngle, PedAngle, DeltaAngle, fDist, Near;
+ CVector vDist;
+ CPed *Player;
+ bool found = false;
+ int ped = 0;
+
+ // unused: TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();
+
+ FwdAngle = CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);
+ Player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ while(ped < Player->m_numNearPeds && !found)
+ if(Player->m_nearPeds[ped] && Player->m_nearPeds[ped]->GetPedState() != PED_DEAD)
+ found = true;
+ else
+ ped++;
+ if(found){
+ vDist = Player->m_nearPeds[ped]->GetPosition() - TheCamera.GetGameCamPosition();
+ PedAngle = CGeneral::GetATanOfXY(vDist.x, vDist.y);
+ DeltaAngle = FwdAngle - PedAngle;
+ while(DeltaAngle >= PI) DeltaAngle -= 2*PI;
+ while(DeltaAngle < -PI) DeltaAngle += 2*PI;
+ if(Abs(DeltaAngle) < HALFPI){
+ fDist = Sqrt(SQR(vDist.x) + SQR(vDist.y));
+ if(fDist < 1.25f){
+ Near = 0.9f - (1.25f - fDist);
+ if(Near < 0.05f)
+ Near = 0.05f;
+ RwCameraSetNearClipPlane(Scene.camera, Near);
+ }
+ }
+ }
+}
+
+void
+CCam::KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov)
+{
+ static CVector PreviousSource = source;
+ static CVector PreviousTarget = target;
+ static CVector PreviousUp = up;
+ static float PreviousBeta = beta;
+ static float PreviousAlpha = alpha;
+ static float PreviousFov = fov;
+
+ if(TheCamera.m_bJust_Switched){
+ PreviousSource = source;
+ PreviousTarget = target;
+ PreviousUp = up;
+ }
+
+ m_cvecSourceSpeedOverOneFrame = PreviousSource - source;
+ m_cvecTargetSpeedOverOneFrame = PreviousTarget - target;
+ m_cvecUpOverOneFrame = PreviousUp - up;
+ m_fFovSpeedOverOneFrame = fov - PreviousFov;
+ m_fBetaSpeedOverOneFrame = beta - PreviousBeta;
+ MakeAngleLessThan180(m_fBetaSpeedOverOneFrame);
+ m_fAlphaSpeedOverOneFrame = alpha - PreviousAlpha;
+ MakeAngleLessThan180(m_fAlphaSpeedOverOneFrame);
+
+ PreviousSource = source;
+ PreviousTarget = target;
+ PreviousUp = up;
+ PreviousBeta = beta;
+ PreviousAlpha = alpha;
+ PreviousFov = fov;
+}
+
+bool
+CCam::Using3rdPersonMouseCam(void)
+{
+ return CCamera::m_bUseMouse3rdPerson &&
+ (Mode == MODE_FOLLOWPED ||
+ TheCamera.m_bPlayerIsInGarage &&
+ FindPlayerPed() && FindPlayerPed()->m_nPedState != PED_DRIVING &&
+ Mode != MODE_TOPDOWN && this->CamTargetEntity == FindPlayerPed());
+}
+
+bool
+CCam::GetWeaponFirstPersonOn(void)
+{
+ CEntity *target = this->CamTargetEntity;
+ if (target && target->IsPed())
+ return ((CPed*)target)->GetWeapon()->m_bAddRotOffset;
+
+ return false;
+}
+
+bool
+CCam::IsTargetInWater(const CVector &CamCoors)
+{
+ if(CamTargetEntity == nil)
+ return false;
+ if(CamTargetEntity->IsPed()){
+ if(!((CPed*)CamTargetEntity)->bIsInWater)
+ return false;
+ if(!((CPed*)CamTargetEntity)->bIsStanding)
+ return true;
+ return false;
+ }
+ return ((CPhysical*)CamTargetEntity)->bIsInWater;
+}
+
+void
+CCam::PrintMode(void)
+{
+ // Doesn't do anything
+ char buf[256];
+
+ if(PrintDebugCode){
+ sprintf(buf, " ");
+ sprintf(buf, " ");
+ sprintf(buf, " ");
+
+ static char *modes[] = { "None",
+ "Top Down", "GTA Classic", "Behind Car", "Follow Ped",
+ "Aiming", "Debug", "Sniper", "Rocket", "Model Viewer", "Bill",
+ "Syphon", "Circle", "Cheesy Zoom", "Wheel", "Fixed",
+ "1st Person", "Fly by", "on a String", "Reaction",
+ "Follow Ped with Bind", "Chris", "Behind Boat",
+ "Player fallen in Water", "Train Roof", "Train Side",
+ "Blood on the tracks", "Passenger", "Syphon Crim in Front",
+ "Dead Baby", "Pillow Paps", "Look at Cars", "Arrest One",
+ "Arrest Two", "M16", "Special fixed for Syphon", "Fight",
+ "Top Down Ped",
+ "Sniper run about", "Rocket run about",
+ "1st Person run about", "M16 run about", "Fight run about",
+ "Editor"
+ };
+ sprintf(buf, "Cam: %s", modes[TheCamera.Cams[TheCamera.ActiveCam].Mode]);
+ CDebug::PrintAt(buf, 2, 5);
+ }
+
+ if(DebugCamMode != MODE_NONE){
+ switch(Mode){
+ case MODE_FOLLOWPED:
+ sprintf(buf, "Debug:- Cam Choice1. No Locking, used as game default");
+ break;
+ case MODE_REACTION:
+ sprintf(buf, "Debug:- Cam Choice2. Reaction Cam On A String ");
+ sprintf(buf, " Uses Locking Button LeftShoulder 1. "); // lie
+ break;
+ case MODE_FOLLOW_PED_WITH_BIND:
+ sprintf(buf, "Debug:- Cam Choice3. Game ReactionCam with Locking ");
+ sprintf(buf, " Uses Locking Button LeftShoulder 1. ");
+ break;
+ case MODE_CHRIS:
+ sprintf(buf, "Debug:- Cam Choice4. Chris's idea. ");
+ sprintf(buf, " Uses Locking Button LeftShoulder 1. ");
+ sprintf(buf, " Also control the camera using the right analogue stick.");
+ break;
+ }
+ }
+}
+
+// This code is really bad. wtf R*?
+CVector
+CCam::DoAverageOnVector(const CVector &vec)
+{
+ int i;
+ CVector Average = { 0.0f, 0.0f, 0.0f };
+
+ if(ResetStatics){
+ m_iRunningVectorArrayPos = 0;
+ m_iRunningVectorCounter = 1;
+ }
+
+ // TODO: make this work with NUMBER_OF_VECTORS_FOR_AVERAGE != 2
+ if(m_iRunningVectorCounter == 3){
+ m_arrPreviousVectors[0] = m_arrPreviousVectors[1];
+ m_arrPreviousVectors[1] = vec;
+ }else
+ m_arrPreviousVectors[m_iRunningVectorArrayPos] = vec;
+
+ for(i = 0; i <= m_iRunningVectorArrayPos; i++)
+ Average += m_arrPreviousVectors[i];
+ Average /= i;
+
+ m_iRunningVectorArrayPos++;
+ m_iRunningVectorCounter++;
+ if(m_iRunningVectorArrayPos >= NUMBER_OF_VECTORS_FOR_AVERAGE)
+ m_iRunningVectorArrayPos = NUMBER_OF_VECTORS_FOR_AVERAGE-1;
+ if(m_iRunningVectorCounter > NUMBER_OF_VECTORS_FOR_AVERAGE+1)
+ m_iRunningVectorCounter = NUMBER_OF_VECTORS_FOR_AVERAGE+1;
+
+ return Average;
+}
+
+// Rotate Beta in direction opposite of BetaOffset in 5 deg. steps.
+// Return the first angle for which Beta + BetaOffset + Angle has a clear view.
+// i.e. BetaOffset is a safe zone so that Beta + Angle is really clear.
+// If BetaOffset == 0, try both directions.
+float
+CCam::GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
+{
+ CColPoint point;
+ CEntity *ent = nil;
+ CVector ToSource;
+ float a;
+
+ // This would be so much nicer if we just got the step variable before the loop...R*
+
+ for(a = 0.0f; a <= PI; a += DEGTORAD(5.0f)){
+ if(BetaOffset <= 0.0f){
+ ToSource = CVector(Cos(Beta + BetaOffset + a), Sin(Beta + BetaOffset + a), 0.0f)*Dist;
+ if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
+ point, ent, checkBuildings, checkVehicles, checkPeds,
+ checkObjects, checkDummies, true, true))
+ return a;
+ }
+ if(BetaOffset >= 0.0f){
+ ToSource = CVector(Cos(Beta + BetaOffset - a), Sin(Beta + BetaOffset - a), 0.0f)*Dist;
+ if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
+ point, ent, checkBuildings, checkVehicles, checkPeds,
+ checkObjects, checkDummies, true, true))
+ return -a;
+ }
+ }
+ return 0.0f;
+}
+
+static float DefaultAcceleration = 0.045f;
+static float DefaultMaxStep = 0.15f;
+
+void
+CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ const float GroundDist = 1.85f;
+
+ CVector TargetCoors, Dist, IdealSource;
+ float Length = 0.0f;
+ float LateralLeft = 0.0f;
+ float LateralRight = 0.0f;
+ float Center = 0.0f;
+ static bool PreviouslyObscured;
+ static bool PickedASide;
+ static float FixedTargetOrientation = 0.0f;
+ float AngleToGoTo = 0.0f;
+ float BetaOffsetAvoidBuildings = 0.45f; // ~25 deg
+ float BetaOffsetGoingBehind = 0.45f;
+ bool GoingBehind = false;
+ bool Obscured = false;
+ bool BuildingCheckObscured = false;
+ bool HackPlayerOnStoppingTrain = false;
+ static int TimeIndicatedWantedToGoDown = 0;
+ static bool StartedCountingForGoDown = false;
+ float DeltaBeta;
+
+ m_bFixingBeta = false;
+ bBelowMinDist = false;
+ bBehindPlayerDesired = false;
+
+#ifdef FIX_BUGS
+ if(!CamTargetEntity->IsPed())
+ return;
+#endif
+ assert(CamTargetEntity->IsPed());
+
+ // CenterDist should be > LateralDist because we don't have an angle for safety in this case
+ float CenterDist, LateralDist;
+ float AngleToGoToSpeed;
+ if(m_fCloseInPedHeightOffset > 0.00001f){
+ LateralDist = 0.55f;
+ CenterDist = 1.25f;
+ BetaOffsetAvoidBuildings = 0.9f; // ~50 deg
+ BetaOffsetGoingBehind = 0.9f;
+ AngleToGoToSpeed = 0.88254666f;
+ }else{
+ LateralDist = 0.8f;
+ CenterDist = 1.35f;
+ if(TheCamera.PedZoomIndicator == 1.0f || TheCamera.PedZoomIndicator == 4.0f){
+ LateralDist = 1.25f;
+ CenterDist = 1.6f;
+ }
+ AngleToGoToSpeed = 0.43254671f;
+ }
+
+ FOV = DefaultFOV;
+
+ if(ResetStatics){
+ Rotating = false;
+ m_bCollisionChecksOn = true;
+ FixedTargetOrientation = 0.0f;
+ PreviouslyObscured = false;
+ PickedASide = false;
+ StartedCountingForGoDown = false;
+ AngleToGoTo = 0.0f;
+ // unused LastAngleWithNoPickedASide
+ }
+
+
+ TargetCoors = CameraTarget;
+ IdealSource = Source;
+ TargetCoors.z += m_fSyphonModeTargetZOffSet;
+
+ TargetCoors = DoAverageOnVector(TargetCoors);
+ TargetCoors.z += m_fRoadOffSet;
+
+ Dist.x = IdealSource.x - TargetCoors.x;
+ Dist.y = IdealSource.y - TargetCoors.y;
+ Length = Dist.Magnitude2D();
+
+ // Cam on a string. With a fixed distance. Zoom in/out is done later.
+ if(Length != 0.0f)
+ IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * GroundDist;
+ else
+ IdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
+
+ // TODO: what's transition beta?
+ if(TheCamera.m_bUseTransitionBeta && ResetStatics){
+ CVector VecDistance;
+ IdealSource.x = TargetCoors.x + GroundDist*Cos(m_fTransitionBeta);
+ IdealSource.y = TargetCoors.y + GroundDist*Sin(m_fTransitionBeta);
+ Beta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y);
+ }else
+ Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
+
+ if(TheCamera.m_bCamDirectlyBehind){
+ m_bCollisionChecksOn = true;
+ Beta = TargetOrientation + PI;
+ }
+
+ if(FindPlayerVehicle())
+ if(FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)
+ HackPlayerOnStoppingTrain = true;
+
+ if(TheCamera.m_bCamDirectlyInFront){
+ m_bCollisionChecksOn = true;
+ Beta = TargetOrientation;
+ }
+
+ while(Beta >= PI) Beta -= 2.0f * PI;
+ while(Beta < -PI) Beta += 2.0f * PI;
+
+ // BUG? is this ever used?
+ // The values seem to be roughly m_fPedZoomValueSmooth + 1.85
+ if(ResetStatics){
+ if(TheCamera.PedZoomIndicator == 1.0) m_fRealGroundDist = 2.090556f;
+ if(TheCamera.PedZoomIndicator == 2.0) m_fRealGroundDist = 3.34973f;
+ if(TheCamera.PedZoomIndicator == 3.0) m_fRealGroundDist = 4.704914f;
+ if(TheCamera.PedZoomIndicator == 4.0) m_fRealGroundDist = 2.090556f;
+ }
+ // And what is this? It's only used for collision and rotation it seems
+ float RealGroundDist;
+ if(TheCamera.PedZoomIndicator == 1.0) RealGroundDist = 2.090556f;
+ if(TheCamera.PedZoomIndicator == 2.0) RealGroundDist = 3.34973f;
+ if(TheCamera.PedZoomIndicator == 3.0) RealGroundDist = 4.704914f;
+ if(TheCamera.PedZoomIndicator == 4.0) RealGroundDist = 2.090556f;
+ if(m_fCloseInPedHeightOffset > 0.00001f)
+ RealGroundDist = 1.7016f;
+
+
+ bool Shooting = false;
+ CPed *ped = (CPed*)CamTargetEntity;
+ if(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
+ if(CPad::GetPad(0)->GetWeapon())
+ Shooting = true;
+ if(ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||
+ ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)
+ Shooting = false;
+
+
+ if(m_fCloseInPedHeightOffset > 0.00001f)
+ TargetCoors.z -= m_fRoadOffSet;
+
+ // Figure out if and where we want to rotate
+
+ if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
+
+ // Center cam behind player
+
+ GoingBehind = true;
+ m_bCollisionChecksOn = true;
+ float OriginalBeta = Beta;
+ // Set Beta behind player
+ Beta = TargetOrientation + PI;
+ TargetCoors.z -= 0.1f;
+
+ AngleToGoTo = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
+ if(AngleToGoTo != 0.0f){
+ if(AngleToGoTo < 0.0f)
+ AngleToGoTo -= AngleToGoToSpeed;
+ else
+ AngleToGoTo += AngleToGoToSpeed;
+ }else{
+ float LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetGoingBehind, true, false, false, true, false);
+ float LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetGoingBehind, true, false, false, true, false);
+ if(LateralLeft == 0.0f && LateralRight != 0.0f)
+ AngleToGoTo += LateralRight;
+ else if(LateralLeft != 0.0f && LateralRight == 0.0f)
+ AngleToGoTo += LateralLeft;
+ }
+
+ TargetCoors.z += 0.1f;
+ Beta = OriginalBeta;
+
+ if(PickedASide){
+ if(AngleToGoTo == 0.0f)
+ FixedTargetOrientation = TargetOrientation + PI;
+ Rotating = true;
+ }else{
+ FixedTargetOrientation = TargetOrientation + PI + AngleToGoTo;
+ Rotating = true;
+ PickedASide = true;
+ }
+ }else{
+
+ // Rotate cam to avoid clipping into buildings
+
+ TargetCoors.z -= 0.1f;
+
+ Center = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
+ if(m_bCollisionChecksOn || PreviouslyObscured || Center != 0.0f || m_fCloseInPedHeightOffset > 0.00001f){
+ if(Center != 0.0f){
+ AngleToGoTo = Center;
+ }else{
+ LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetAvoidBuildings, true, false, false, true, false);
+ LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetAvoidBuildings, true, false, false, true, false);
+ if(LateralLeft == 0.0f && LateralRight != 0.0f){
+ AngleToGoTo += LateralRight;
+ if(m_fCloseInPedHeightOffset > 0.0f)
+ RwCameraSetNearClipPlane(Scene.camera, 0.7f);
+ }else if(LateralLeft != 0.0f && LateralRight == 0.0f){
+ AngleToGoTo += LateralLeft;
+ if(m_fCloseInPedHeightOffset > 0.0f)
+ RwCameraSetNearClipPlane(Scene.camera, 0.7f);
+ }
+ }
+ if(LateralLeft != 0.0f || LateralRight != 0.0f || Center != 0.0f)
+ BuildingCheckObscured = true;
+ }
+
+ TargetCoors.z += 0.1f;
+ }
+
+ if(m_fCloseInPedHeightOffset > 0.00001f)
+ TargetCoors.z += m_fRoadOffSet;
+
+
+ // Have to fix to avoid collision
+
+ if(AngleToGoTo != 0.0f){
+ Obscured = true;
+ Rotating = true;
+ if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
+ if(!PickedASide)
+ FixedTargetOrientation = Beta + AngleToGoTo; // can this even happen?
+ }else
+ FixedTargetOrientation = Beta + AngleToGoTo;
+
+ // This calculation is only really used to figure out how fast to rotate out of collision
+
+ m_fAmountFractionObscured = 1.0f;
+ CVector PlayerPos = FindPlayerPed()->GetPosition();
+ float RotationDist = (AngleToGoTo == Center ? CenterDist : LateralDist) * RealGroundDist;
+ // What's going on here? - AngleToGoTo?
+ CVector RotatedSource = PlayerPos + CVector(Cos(Beta - AngleToGoTo), Sin(Beta - AngleToGoTo), 0.0f) * RotationDist;
+
+ CColPoint colpoint;
+ CEntity *entity;
+ if(CWorld::ProcessLineOfSight(PlayerPos, RotatedSource, colpoint, entity, true, false, false, true, false, false, false)){
+ if((PlayerPos - RotatedSource).Magnitude() != 0.0f)
+ m_fAmountFractionObscured = (PlayerPos - colpoint.point).Magnitude() / (PlayerPos - RotatedSource).Magnitude();
+ else
+ m_fAmountFractionObscured = 1.0f;
+ }
+ }
+ if(m_fAmountFractionObscured < 0.0f) m_fAmountFractionObscured = 0.0f;
+ if(m_fAmountFractionObscured > 1.0f) m_fAmountFractionObscured = 1.0f;
+
+
+
+ // Figure out speed values for Beta rotation
+
+ float Acceleration, MaxSpeed;
+ static float AccelerationMult = 0.35f;
+ static float MaxSpeedMult = 0.85f;
+ static float AccelerationMultClose = 0.7f;
+ static float MaxSpeedMultClose = 1.6f;
+ float BaseAcceleration = 0.025f;
+ float BaseMaxSpeed = 0.09f;
+ if(m_fCloseInPedHeightOffset > 0.00001f){
+ if(AngleToGoTo == 0.0f){
+ BaseAcceleration = 0.022f;
+ BaseMaxSpeed = 0.04f;
+ }else{
+ BaseAcceleration = DefaultAcceleration;
+ BaseMaxSpeed = DefaultMaxStep;
+ }
+ }
+ if(AngleToGoTo == 0.0f){
+ Acceleration = BaseAcceleration;
+ MaxSpeed = BaseMaxSpeed;
+ }else if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !Shooting){
+ Acceleration = 0.051f;
+ MaxSpeed = 0.18f;
+ }else if(m_fCloseInPedHeightOffset > 0.00001f){
+ Acceleration = BaseAcceleration + AccelerationMultClose*sq(m_fAmountFractionObscured - 1.05f);
+ MaxSpeed = BaseMaxSpeed + MaxSpeedMultClose*sq(m_fAmountFractionObscured - 1.05f);
+ }else{
+ Acceleration = DefaultAcceleration + AccelerationMult*sq(m_fAmountFractionObscured - 1.05f);
+ MaxSpeed = DefaultMaxStep + MaxSpeedMult*sq(m_fAmountFractionObscured - 1.05f);
+ }
+ static float AccelerationLimit = 0.3f;
+ static float MaxSpeedLimit = 0.65f;
+ if(Acceleration > AccelerationLimit) Acceleration = AccelerationLimit;
+ if(MaxSpeed > MaxSpeedLimit) MaxSpeed = MaxSpeedLimit;
+
+
+ int MoveState = ((CPed*)CamTargetEntity)->m_nMoveState;
+ if(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL &&
+ !CPad::GetPad(0)->ForceCameraBehindPlayer() && !Obscured && !Shooting){
+ Rotating = false;
+ BetaSpeed = 0.0f;
+ }
+
+ // Now do the Beta rotation
+
+ float Distance = (IdealSource - TargetCoors).Magnitude2D();
+ m_fDistanceBeforeChanges = Distance;
+
+ if(Rotating){
+ m_bFixingBeta = true;
+
+ while(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI;
+ while(FixedTargetOrientation < -PI) FixedTargetOrientation += 2*PI;
+
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+
+/*
+ // This is inlined WellBufferMe
+ DeltaBeta = FixedTargetOrientation - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+
+ float ReqSpeed = DeltaBeta * MaxSpeed;
+ // Add or subtract absolute depending on sign, genius!
+ if(ReqSpeed - BetaSpeed > 0.0f)
+ BetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
+ else
+ BetaSpeed -= SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
+ // this would be simpler:
+ // BetaSpeed += SpeedStep * (ReqSpeed - BetaSpeed) * CTimer::ms_fTimeStep;
+
+ if(ReqSpeed < 0.0f && BetaSpeed < ReqSpeed)
+ BetaSpeed = ReqSpeed;
+ else if(ReqSpeed > 0.0f && BetaSpeed > ReqSpeed)
+ BetaSpeed = ReqSpeed;
+
+ Beta += BetaSpeed * min(10.0f, CTimer::GetTimeStep());
+*/
+ WellBufferMe(FixedTargetOrientation, &Beta, &BetaSpeed, MaxSpeed, Acceleration, true);
+
+ if(ResetStatics){
+ Beta = FixedTargetOrientation;
+ BetaSpeed = 0.0f;
+ }
+
+ Source.x = TargetCoors.x + Distance * Cos(Beta);
+ Source.y = TargetCoors.y + Distance * Sin(Beta);
+
+ // Check if we can stop rotating
+ DeltaBeta = FixedTargetOrientation - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(Abs(DeltaBeta) < DEGTORAD(1.0f) && !bBehindPlayerDesired){
+ // Stop rotation
+ PickedASide = false;
+ Rotating = false;
+ BetaSpeed = 0.0f;
+ }
+ }
+
+
+ if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront ||
+ HackPlayerOnStoppingTrain || Rotating){
+ if(TheCamera.m_bCamDirectlyBehind){
+ Beta = TargetOrientation + PI;
+ Source.x = TargetCoors.x + Distance * Cos(Beta);
+ Source.y = TargetCoors.y + Distance * Sin(Beta);
+ }
+ if(TheCamera.m_bCamDirectlyInFront){
+ Beta = TargetOrientation;
+ Source.x = TargetCoors.x + Distance * Cos(Beta);
+ Source.y = TargetCoors.y + Distance * Sin(Beta);
+ }
+ if(HackPlayerOnStoppingTrain){
+ Beta = TargetOrientation + PI;
+ Source.x = TargetCoors.x + Distance * Cos(Beta);
+ Source.y = TargetCoors.y + Distance * Sin(Beta);
+ m_fDimensionOfHighestNearCar = 0.0f;
+ m_fCamBufferedHeight = 0.0f;
+ m_fCamBufferedHeightSpeed = 0.0f;
+ }
+ // Beta and Source already set in the rotation code
+ }else{
+ Source = IdealSource;
+ BetaSpeed = 0.0f;
+ }
+
+ // Subtract m_fRoadOffSet from both?
+ TargetCoors.z -= m_fRoadOffSet;
+ Source.z = IdealSource.z - m_fRoadOffSet;
+
+ // Apply zoom now
+ // m_fPedZoomValueSmooth makes the cam go down the further out it is
+ // 0.25 -> 0.20 for nearest dist
+ // 1.50 -> -0.05 for mid dist
+ // 2.90 -> -0.33 for far dist
+ Source.z += (2.5f - TheCamera.m_fPedZoomValueSmooth)*0.2f - 0.25f;
+ // Zoom out camera
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source -= Front * TheCamera.m_fPedZoomValueSmooth;
+ // and then we move up again
+ // -0.375
+ // 0.25
+ // 0.95
+ Source.z += (TheCamera.m_fPedZoomValueSmooth - 1.0f)*0.5f + m_fCloseInPedHeightOffset;
+
+
+ // Process height offset to avoid peds and cars
+
+ float TargetZOffSet = m_fRoadOffSet + m_fDimensionOfHighestNearCar;
+ TargetZOffSet = max(TargetZOffSet, m_fPedBetweenCameraHeightOffset);
+ float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z;
+
+ if(TargetHeight > m_fCamBufferedHeight){
+ // Have to go up
+ if(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight)
+ WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false);
+ else if(TargetZOffSet == m_fRoadOffSet && TargetZOffSet > m_fCamBufferedHeight){
+ // TODO: figure this out
+ bool foo = false;
+ switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched)
+ case SURFACE_GRASS:
+ case SURFACE_DIRT:
+ case SURFACE_PAVEMENT:
+ case SURFACE_STEEL:
+ case SURFACE_TIRE:
+ case SURFACE_STONE:
+ foo = true;
+ if(foo)
+ WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false);
+ else
+ WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
+ }else
+ WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
+ StartedCountingForGoDown = false;
+ }else{
+ // Have to go down
+ if(StartedCountingForGoDown){
+ if(CTimer::GetTimeInMilliseconds() != TimeIndicatedWantedToGoDown){
+ if(TargetHeight > 0.0f)
+ WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
+ else
+ WellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
+ }
+ }else{
+ StartedCountingForGoDown = true;
+ TimeIndicatedWantedToGoDown = CTimer::GetTimeInMilliseconds();
+ }
+ }
+
+ Source.z += m_fCamBufferedHeight;
+
+
+ // Clip Source if necessary
+
+ bool ClipSource = m_fCloseInPedHeightOffset > 0.00001f && m_fCamBufferedHeight > 0.001f;
+ if(GoingBehind || ResetStatics || ClipSource){
+ CColPoint colpoint;
+ CEntity *entity;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colpoint, entity, true, false, false, true, false, true, true)){
+ Source = colpoint.point;
+ if((TargetCoors - Source).Magnitude2D() < 1.0f)
+ RwCameraSetNearClipPlane(Scene.camera, 0.05f);
+ }
+ }
+
+ TargetCoors.z += min(1.0f, m_fCamBufferedHeight/2.0f);
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+
+ Front = TargetCoors - Source;
+ m_fRealGroundDist = Front.Magnitude2D();
+ m_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist;
+ Front.Normalise();
+ GetVectorsReadyForRW();
+ TheCamera.m_bCamDirectlyBehind = false;
+ TheCamera.m_bCamDirectlyInFront = false;
+ PreviouslyObscured = BuildingCheckObscured;
+
+ ResetStatics = false;
+}
+
+static float fBaseDist = 1.7f;
+static float fAngleDist = 2.0f;
+static float fFalloff = 3.0f;
+static float fStickSens = 0.01f;
+static float fTweakFOV = 1.05f;
+static float fTranslateCamUp = 0.8f;
+static int16 nFadeControlThreshhold = 45;
+static float fDefaultAlphaOrient = -0.22f;
+
+void
+CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ FOV = DefaultFOV;
+
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ CVector TargetCoors;
+ float CamDist;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if(ResetStatics){
+ Rotating = false;
+ m_bCollisionChecksOn = true;
+ CPad::GetPad(0)->ClearMouseHistory();
+ ResetStatics = false;
+ }
+
+ bool OnTrain = FindPlayerVehicle() && FindPlayerVehicle()->IsTrain();
+
+ // Look around
+ bool UseMouse = false;
+ float MouseX = CPad::GetPad(0)->GetMouseX();
+ float MouseY = CPad::GetPad(0)->GetMouseY();
+ float LookLeftRight, LookUpDown;
+ if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
+ UseMouse = true;
+ LookLeftRight = -2.5f*MouseX;
+ LookUpDown = 4.0f*MouseY;
+ }else{
+ LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
+ LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
+ }
+ float AlphaOffset, BetaOffset;
+ if(UseMouse){
+ BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
+ AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
+ }else{
+ BetaOffset = LookLeftRight * fStickSens * (0.5f/7.0f) * FOV/80.0f * CTimer::GetTimeStep();
+ AlphaOffset = LookUpDown * fStickSens * (0.3f/7.0f) * FOV/80.0f * CTimer::GetTimeStep();
+ }
+
+ if(TheCamera.GetFading() && TheCamera.GetFadingDirection() == FADE_IN && nFadeControlThreshhold < CDraw::FadeValue ||
+ CDraw::FadeValue > 200){
+ if(Alpha < fDefaultAlphaOrient-0.05f)
+ AlphaOffset = 0.05f;
+ else if(Alpha < fDefaultAlphaOrient)
+ AlphaOffset = fDefaultAlphaOrient - Alpha;
+ else if(Alpha > fDefaultAlphaOrient+0.05f)
+ AlphaOffset = -0.05f;
+ else if(Alpha > fDefaultAlphaOrient)
+ AlphaOffset = fDefaultAlphaOrient - Alpha;
+ else
+ AlphaOffset = 0.0f;
+ }
+
+ Alpha += AlphaOffset;
+ Beta += BetaOffset;
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors = CameraTarget;
+ TargetCoors.z += fTranslateCamUp;
+ TargetCoors = DoAverageOnVector(TargetCoors);
+
+ if(Alpha > fBaseDist) // comparing an angle against a distance?
+ CamDist = fBaseDist + Cos(min(Alpha*fFalloff, HALFPI))*fAngleDist;
+ else
+ CamDist = fBaseDist + Cos(Alpha)*fAngleDist;
+
+ if(TheCamera.m_bUseTransitionBeta)
+ Beta = -CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
+
+ if(TheCamera.m_bCamDirectlyBehind)
+ Beta = TheCamera.m_PedOrientForBehindOrInFront;
+ if(TheCamera.m_bCamDirectlyInFront)
+ Beta = TheCamera.m_PedOrientForBehindOrInFront + PI;
+ if(OnTrain)
+ Beta = TargetOrientation;
+
+ Front.x = Cos(Alpha) * Cos(Beta);
+ Front.y = Cos(Alpha) * Sin(Beta);
+ Front.z = Sin(Alpha);
+ Source = TargetCoors - Front*CamDist;
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+
+ // Clip Source and fix near clip
+ CWorld::pIgnoreEntity = CamTargetEntity;
+ entity = nil;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){
+ float PedColDist = (TargetCoors - colPoint.point).Magnitude();
+ float ColCamDist = CamDist - PedColDist;
+ if(entity->IsPed() && ColCamDist > 1.0f){
+ // Ped in the way but not clipping through
+ if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){
+ PedColDist = (TargetCoors - colPoint.point).Magnitude();
+ Source = colPoint.point;
+ if(PedColDist < 0.9f + 0.3f)
+ RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
+ }else{
+ RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, 0.9f));
+ }
+ }else{
+ Source = colPoint.point;
+ if(PedColDist < 0.9f + 0.3f)
+ RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
+ }
+ }
+ CWorld::pIgnoreEntity = nil;
+
+ float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);
+ float ViewPlaneWidth = ViewPlaneHeight * CDraw::FindAspectRatio() * fTweakFOV;
+ float Near = RwCameraGetNearClipPlane(Scene.camera);
+ float radius = ViewPlaneWidth*Near;
+ entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
+ int i = 0;
+ while(entity){
+ CVector CamToCol = gaTempSphereColPoints[0].point - Source;
+ float frontDist = DotProduct(CamToCol, Front);
+ float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;
+
+ // Try to decrease near clip
+ dist = max(min(Near, dist), 0.1f);
+ if(dist < Near)
+ RwCameraSetNearClipPlane(Scene.camera, dist);
+
+ // Move forward a bit
+ if(dist == 0.1f)
+ Source += (TargetCoors - Source)*0.3f;
+
+#ifndef FIX_BUGS
+ // this is totally wrong...
+ radius = Tan(FOV / 2.0f) * Near;
+#endif
+ // Keep testing
+ entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
+
+ i++;
+ if(i > 5)
+ entity = nil;
+ }
+
+ if(CamTargetEntity->GetClump()){
+ // what's going on here?
+ if(RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_PUMP) ||
+ RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROW) ||
+ RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_THROWU) ||
+ RpAnimBlendClumpGetAssociation(CamTargetEntity->GetClump(), ANIM_WEAPON_START_THROW)){
+ CPed *player = FindPlayerPed();
+ float PlayerDist = (Source - player->GetPosition()).Magnitude();
+ if(PlayerDist < 2.75f)
+ Near = PlayerDist/2.75f * 0.9f - 0.3f;
+ RwCameraSetNearClipPlane(Scene.camera, max(Near, 0.1f));
+ }
+ }
+
+ TheCamera.m_bCamDirectlyInFront = false;
+ TheCamera.m_bCamDirectlyBehind = false;
+
+ GetVectorsReadyForRW();
+
+ if(((CPed*)CamTargetEntity)->CanStrafeOrMouseControl() && CDraw::FadeValue < 250 &&
+ (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100)){
+ float Heading = Front.Heading();
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
+ TheCamera.pTargetEntity->SetHeading(Heading);
+ TheCamera.pTargetEntity->GetMatrix().UpdateRW();
+ }
+}
+
+void
+CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ FOV = DefaultFOV;
+
+ if(!CamTargetEntity->IsVehicle())
+ return;
+
+ CVector TargetCoors = CameraTarget;
+ TargetCoors.z -= 0.2f;
+ CA_MAX_DISTANCE = 9.95f;
+ CA_MIN_DISTANCE = 8.5f;
+
+ CVector Dist = Source - TargetCoors;
+ float Length = Dist.Magnitude2D();
+ m_fDistanceBeforeChanges = Length;
+ if(Length < 0.002f)
+ Length = 0.002f;
+ Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
+ if(Length > CA_MAX_DISTANCE){
+ Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
+ Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
+ }else if(Length < CA_MIN_DISTANCE){
+ Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
+ Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
+ }
+ TargetCoors.z += 0.8f;
+
+ WorkOutCamHeightWeeCar(TargetCoors, TargetOrientation);
+ RotCamIfInFrontCar(TargetCoors, TargetOrientation);
+ FixCamIfObscured(TargetCoors, 1.2f, TargetOrientation);
+
+ Front = TargetCoors - Source;
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ ResetStatics = false;
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation)
+{
+ CColPoint colpoint;
+ CEntity *ent;
+ float TargetZOffSet = 0.0f;
+ static bool PreviouslyFailedRoadHeightCheck = false;
+ static float RoadHeightFix = 0.0f;
+ static float RoadHeightFixSpeed = 0.0f;
+
+ if(ResetStatics){
+ RoadHeightFix = 0.0f;
+ RoadHeightFixSpeed = 0.0f;
+ Alpha = DEGTORAD(25.0f);
+ AlphaSpeed = 0.0f;
+ }
+ float AlphaTarget = DEGTORAD(25.0f);
+ if(CCullZones::CamNoRain() || CCullZones::PlayerNoRain())
+ AlphaTarget = DEGTORAD(14.0f);
+ WellBufferMe(AlphaTarget, &Alpha, &AlphaSpeed, 0.1f, 0.05f, true);
+ Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);
+
+ if(FindPlayerVehicle()){
+ m_fRoadOffSet = 0.0f;
+ bool FoundRoad = false;
+ bool FoundRoof = false;
+ float RoadZ = 0.0f;
+ float RoofZ = 0.0f;
+
+ if(CWorld::ProcessVerticalLine(Source, -1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
+ ent->IsBuilding()){
+ FoundRoad = true;
+ RoadZ = colpoint.point.z;
+ }
+
+ if(FoundRoad){
+ if(Source.z - RoadZ < 0.9f){
+ PreviouslyFailedRoadHeightCheck = true;
+ TargetZOffSet = RoadZ + 0.9f - Source.z;
+ }else{
+ if(m_bCollisionChecksOn)
+ PreviouslyFailedRoadHeightCheck = false;
+ else
+ TargetZOffSet = 0.0f;
+ }
+ }else{
+ if(CWorld::ProcessVerticalLine(Source, 1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
+ ent->IsBuilding()){
+ FoundRoof = true;
+ RoofZ = colpoint.point.z;
+ }
+ if(FoundRoof){
+ if(Source.z - RoofZ < 0.9f){
+ PreviouslyFailedRoadHeightCheck = true;
+ TargetZOffSet = RoofZ + 0.9f - Source.z;
+ }else{
+ if(m_bCollisionChecksOn)
+ PreviouslyFailedRoadHeightCheck = false;
+ else
+ TargetZOffSet = 0.0f;
+ }
+ }
+ }
+ }
+
+ if(TargetZOffSet > RoadHeightFix)
+ RoadHeightFix = TargetZOffSet;
+ else
+ WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false);
+
+ if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_METAL6) &&
+ colpoint.surfaceB != SURFACE_STEEL && colpoint.surfaceB != SURFACE_STONE &&
+ RoadHeightFix > 1.4f)
+ RoadHeightFix = 1.4f;
+
+ Source.z += RoadHeightFix;
+}
+
+void
+CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight)
+{
+ static float LastTargetAlphaWithCollisionOn = 0.0f;
+ static float LastTopAlphaSpeed = 0.0f;
+ static float LastAlphaSpeedStep = 0.0f;
+ static bool PreviousNearCheckNearClipSmall = false;
+
+ bool CamClear = true;
+ float ModeAlpha = 0.0f;
+
+ if(ResetStatics){
+ LastTargetAlphaWithCollisionOn = 0.0f;
+ LastTopAlphaSpeed = 0.0f;
+ LastAlphaSpeedStep = 0.0f;
+ PreviousNearCheckNearClipSmall = false;
+ }
+
+ float TopAlphaSpeed = 0.15f;
+ float AlphaSpeedStep = 0.015f;
+
+ float zoomvalue = TheCamera.CarZoomValueSmooth;
+ if(zoomvalue < 0.1f)
+ zoomvalue = 0.1f;
+ if(TheCamera.CarZoomIndicator == 1.0f)
+ ModeAlpha = CGeneral::GetATanOfXY(23.0f, zoomvalue); // near
+ else if(TheCamera.CarZoomIndicator == 2.0f)
+ ModeAlpha = CGeneral::GetATanOfXY(10.8f, zoomvalue); // mid
+ else if(TheCamera.CarZoomIndicator == 3.0f)
+ ModeAlpha = CGeneral::GetATanOfXY(7.0f, zoomvalue); // far
+
+
+ float Length = (Source - TargetCoors).Magnitude2D();
+ if(m_bCollisionChecksOn){ // there's another variable (on PC) but it's uninitialised
+ CVector Forward = CamTargetEntity->GetForward();
+ float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);
+ // this shouldn't be necessary....
+ while(CarAlpha >= PI) CarAlpha -= 2*PI;
+ while(CarAlpha < -PI) CarAlpha += 2*PI;
+
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+ float deltaBeta = Beta - TargetOrientation;
+ while(deltaBeta >= PI) deltaBeta -= 2*PI;
+ while(deltaBeta < -PI) deltaBeta += 2*PI;
+
+ float BehindCarNess = Cos(deltaBeta); // 1 if behind car, 0 if side, -1 if in front
+ CarAlpha = -CarAlpha * BehindCarNess;
+ if(CarAlpha < -0.01f)
+ CarAlpha = -0.01f;
+
+ float DeltaAlpha = CarAlpha - Alpha;
+ while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
+ while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
+ // What's this?? wouldn't it make more sense to clamp?
+ float AngleLimit = DEGTORAD(1.8f);
+ if(DeltaAlpha < -AngleLimit)
+ DeltaAlpha += AngleLimit;
+ else if(DeltaAlpha > AngleLimit)
+ DeltaAlpha -= AngleLimit;
+ else
+ DeltaAlpha = 0.0f;
+
+ // Now the collision
+
+ float TargetAlpha = 0.0f;
+ bool FoundRoofCenter = false;
+ bool FoundRoofSide1 = false;
+ bool FoundRoofSide2 = false;
+ bool FoundCamRoof = false;
+ bool FoundCamGround = false;
+ float CamRoof = 0.0f;
+ float CarBottom = TargetCoors.z - TargetHeight/2.0f;
+
+ // Check car center
+ float CarRoof = CWorld::FindRoofZFor3DCoord(TargetCoors.x, TargetCoors.y, CarBottom, &FoundRoofCenter);
+
+ // Check sides of the car
+ Forward = CamTargetEntity->GetForward(); // we actually still have that...
+ Forward.Normalise(); // shouldn't be necessary
+ float CarSideAngle = CGeneral::GetATanOfXY(Forward.x, Forward.y) + PI/2.0f;
+ float SideX = 2.5f * Cos(CarSideAngle);
+ float SideY = 2.5f * Sin(CarSideAngle);
+ CWorld::FindRoofZFor3DCoord(TargetCoors.x + SideX, TargetCoors.y + SideY, CarBottom, &FoundRoofSide1);
+ CWorld::FindRoofZFor3DCoord(TargetCoors.x - SideX, TargetCoors.y - SideY, CarBottom, &FoundRoofSide2);
+
+ // Now find out at what height we'd like to place the camera
+ float CamGround = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, TargetCoors.z + Length*Sin(Alpha + ModeAlpha) + m_fCloseInCarHeightOffset, &FoundCamGround);
+ float CamTargetZ = 0.0f;
+ if(FoundCamGround){
+ // This is the normal case
+ CamRoof = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamGround + TargetHeight, &FoundCamRoof);
+ CamTargetZ = CamGround + TargetHeight*1.5f + 0.1f;
+ }else{
+ FoundCamRoof = false;
+ CamTargetZ = TargetCoors.z;
+ }
+
+ if(FoundRoofCenter && !FoundCamRoof && (FoundRoofSide1 || FoundRoofSide2)){
+ // Car is under something but camera isn't
+ // This seems weird...
+ TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, CarRoof - CamTargetZ - 1.5f);
+ CamClear = false;
+ }
+ if(FoundCamRoof){
+ // Camera is under something
+ float roof = FoundRoofCenter ? min(CamRoof, CarRoof) : CamRoof;
+ // Same weirdness again?
+ TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, roof - CamTargetZ - 1.5f);
+ CamClear = false;
+ }
+ while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
+ while(TargetAlpha < -PI) TargetAlpha += 2*PI;
+ if(TargetAlpha < DEGTORAD(-7.0f))
+ TargetAlpha = DEGTORAD(-7.0f);
+
+ // huh?
+ if(TargetAlpha > ModeAlpha)
+ CamClear = true;
+ // Camera is contrained by collision in some way
+ PreviousNearCheckNearClipSmall = false;
+ if(!CamClear){
+ PreviousNearCheckNearClipSmall = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+
+ DeltaAlpha = TargetAlpha - (Alpha + ModeAlpha);
+ while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
+ while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
+
+ TopAlphaSpeed = 0.3f;
+ AlphaSpeedStep = 0.03f;
+ }
+
+ // Now do things if CamClear...but what is that anyway?
+ float CamZ = TargetCoors.z + Length*Sin(Alpha + DeltaAlpha + ModeAlpha) + m_fCloseInCarHeightOffset;
+ bool FoundGround, FoundRoof;
+ float CamGround2 = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, CamZ, &FoundGround);
+ if(FoundGround){
+ if(CamClear)
+ if(CamZ - CamGround2 < 1.5f){
+ PreviousNearCheckNearClipSmall = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+
+ float a;
+ if(Length == 0.0f || CamGround2 + 1.5f - TargetCoors.z == 0.0f)
+ a = Alpha;
+ else
+ a = CGeneral::GetATanOfXY(Length, CamGround2 + 1.5f - TargetCoors.z);
+ while(a > PI) a -= 2*PI;
+ while(a < -PI) a += 2*PI;
+ DeltaAlpha = a - Alpha;
+ }
+ }else{
+ if(CamClear){
+ float CamRoof2 = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamZ, &FoundRoof);
+ if(FoundRoof && CamZ - CamRoof2 < 1.5f){
+ PreviousNearCheckNearClipSmall = true;
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+
+ if(CamRoof2 > TargetCoors.z + 3.5f)
+ CamRoof2 = TargetCoors.z + 3.5f;
+
+ float a;
+ if(Length == 0.0f || CamRoof2 + 1.5f - TargetCoors.z == 0.0f)
+ a = Alpha;
+ else
+ a = CGeneral::GetATanOfXY(Length, CamRoof2 + 1.5f - TargetCoors.z);
+ while(a > PI) a -= 2*PI;
+ while(a < -PI) a += 2*PI;
+ DeltaAlpha = a - Alpha;
+ }
+ }
+ }
+
+ LastTargetAlphaWithCollisionOn = DeltaAlpha + Alpha;
+ LastTopAlphaSpeed = TopAlphaSpeed;
+ LastAlphaSpeedStep = AlphaSpeedStep;
+ }else{
+ if(PreviousNearCheckNearClipSmall)
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ }
+
+ WellBufferMe(LastTargetAlphaWithCollisionOn, &Alpha, &AlphaSpeed, LastTopAlphaSpeed, LastAlphaSpeedStep, true);
+
+ Source.z = TargetCoors.z + Sin(Alpha + ModeAlpha)*Length + m_fCloseInCarHeightOffset;
+}
+
+// Rotate cam behind the car when the car is moving forward
+bool
+CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
+{
+ bool MovingForward = false;
+ CPhysical *phys = (CPhysical*)CamTargetEntity;
+
+ float ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
+ if(ForwardSpeed > 0.02f)
+ MovingForward = true;
+
+ float Dist = (Source - TargetCoors).Magnitude2D();
+
+ float DeltaBeta = TargetOrientation - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+
+ if(Abs(DeltaBeta) > DEGTORAD(20.0f) && MovingForward && TheCamera.m_uiTransitionState == 0)
+ m_bFixingBeta = true;
+
+ CPad *pad = CPad::GetPad(0);
+ if(!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))
+ if(DirectionWasLooking != LOOKING_FORWARD)
+ TheCamera.m_bCamDirectlyBehind = true;
+
+ if(!m_bFixingBeta && !TheCamera.m_bUseTransitionBeta && !TheCamera.m_bCamDirectlyBehind && !TheCamera.m_bCamDirectlyInFront)
+ return false;
+
+ bool SetBeta = false;
+ if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront || TheCamera.m_bUseTransitionBeta)
+ if(&TheCamera.Cams[TheCamera.ActiveCam] == this)
+ SetBeta = true;
+
+ if(m_bFixingBeta || SetBeta){
+ WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, 0.15f, 0.007f, true);
+
+ if(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this)
+ Beta = TargetOrientation;
+ if(TheCamera.m_bCamDirectlyInFront && &TheCamera.Cams[TheCamera.ActiveCam] == this)
+ Beta = TargetOrientation + PI;
+ if(TheCamera.m_bUseTransitionBeta && &TheCamera.Cams[TheCamera.ActiveCam] == this)
+ Beta = m_fTransitionBeta;
+
+ Source.x = TargetCoors.x - Cos(Beta)*Dist;
+ Source.y = TargetCoors.y - Sin(Beta)*Dist;
+
+ // Check if we're done
+ DeltaBeta = TargetOrientation - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(Abs(DeltaBeta) < DEGTORAD(2.0f))
+ m_bFixingBeta = false;
+ }
+ TheCamera.m_bCamDirectlyBehind = false;
+ TheCamera.m_bCamDirectlyInFront = false;
+ return true;
+}
+
+// Move the cam to avoid clipping through buildings
+bool
+CCam::FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation)
+{
+ CVector Target = TargetCoors;
+ bool UseEntityPos = false;
+ CVector EntityPos;
+ static CColPoint colPoint;
+ static bool LastObscured = false;
+
+ if(Mode == MODE_BEHINDCAR)
+ Target.z += TargetHeight/2.0f;
+ if(Mode == MODE_CAM_ON_A_STRING){
+ UseEntityPos = true;
+ Target.z += TargetHeight/2.0f;
+ EntityPos = CamTargetEntity->GetPosition();
+ }
+
+ CVector TempSource = Source;
+
+ bool Obscured1 = false;
+ bool Obscured2 = false;
+ bool Fix1 = false;
+ float Dist1 = 0.0f;
+ float Dist2 = 0.0f;
+ CEntity *ent;
+ if(m_bCollisionChecksOn || LastObscured){
+ Obscured1 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
+ if(Obscured1){
+ Dist1 = (Target - colPoint.point).Magnitude2D();
+ Fix1 = true;
+ if(UseEntityPos)
+ Obscured1 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
+ }else if(m_bFixingBeta){
+ float d = (TempSource - Target).Magnitude();
+ TempSource.x = Target.x - d*Cos(TargetOrientation);
+ TempSource.y = Target.y - d*Sin(TargetOrientation);
+
+ // same check again
+ Obscured2 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
+ if(Obscured2){
+ Dist2 = (Target - colPoint.point).Magnitude2D();
+ if(UseEntityPos)
+ Obscured2 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
+ }
+ }
+ LastObscured = Obscured1 || Obscured2;
+ }
+
+ // nothing to do
+ if(!LastObscured)
+ return false;
+
+ if(Fix1){
+ Source.x = Target.x - Cos(Beta)*Dist1;
+ Source.y = Target.y - Sin(Beta)*Dist1;
+ if(Mode == MODE_BEHINDCAR)
+ Source = colPoint.point;
+ }else{
+ WellBufferMe(Dist2, &m_fDistanceBeforeChanges, &DistanceSpeed, 0.2f, 0.025f, false);
+ Source.x = Target.x - Cos(Beta)*m_fDistanceBeforeChanges;
+ Source.y = Target.y - Sin(Beta)*m_fDistanceBeforeChanges;
+ }
+
+ if(ResetStatics){
+ m_fDistanceBeforeChanges = (Source - Target).Magnitude2D();
+ DistanceSpeed = 0.0f;
+ Source.x = colPoint.point.x;
+ Source.y = colPoint.point.y;
+ }
+ return true;
+}
+
+void
+CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ if(!CamTargetEntity->IsVehicle())
+ return;
+
+ FOV = DefaultFOV;
+
+ if(ResetStatics){
+ AlphaSpeed = 0.0f;
+ if(TheCamera.m_bIdleOn)
+ TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds();
+ }
+
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
+ CVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min;
+ float BaseDist = Dimensions.Magnitude2D();
+
+ CVector TargetCoors = CameraTarget;
+ TargetCoors.z += Dimensions.z - 0.1f; // final
+ Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
+ while(Alpha >= PI) Alpha -= 2*PI;
+ while(Alpha < -PI) Alpha += 2*PI;
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+ m_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D();
+
+ Cam_On_A_String_Unobscured(TargetCoors, BaseDist);
+ WorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z);
+ RotCamIfInFrontCar(TargetCoors, TargetOrientation);
+ FixCamIfObscured(TargetCoors, Dimensions.z, TargetOrientation);
+ FixCamWhenObscuredByVehicle(TargetCoors);
+
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ GetVectorsReadyForRW();
+ ResetStatics = false;
+}
+
+// Basic Cam on a string algorithm
+void
+CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)
+{
+ CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth;
+ CA_MIN_DISTANCE = min(BaseDist*0.6f, 3.5f);
+
+ CVector Dist = Source - TargetCoors;
+
+ if(ResetStatics)
+ Source = TargetCoors + Dist*(CA_MAX_DISTANCE + 1.0f);
+
+ float Length = Dist.Magnitude2D();
+ if(Length < 0.001f){
+ // This probably shouldn't happen. reset view
+ CVector Forward = CamTargetEntity->GetForward();
+ Forward.z = 0.0f;
+ Forward.Normalise();
+ Source = TargetCoors - Forward*CA_MAX_DISTANCE;
+ Dist = Source - TargetCoors;
+ Length = Dist.Magnitude2D();
+ }
+
+ if(Length > CA_MAX_DISTANCE){
+ Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
+ Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
+ }else if(Length < CA_MIN_DISTANCE){
+ Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
+ Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
+ }
+}
+
+void
+CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)
+{
+ // BUG? is this never reset
+ static float HeightFixerCarsObscuring = 0.0f;
+ static float HeightFixerCarsObscuringSpeed = 0.0f;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ float HeightTarget = 0.0f;
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, false, true, false, false, false, false, false)){
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(entity->GetModelIndex());
+ HeightTarget = mi->GetColModel()->boundingBox.max.z + 1.0f + TargetCoors.z - Source.z;
+ if(HeightTarget < 0.0f)
+ HeightTarget = 0.0f;
+ }
+ WellBufferMe(HeightTarget, &HeightFixerCarsObscuring, &HeightFixerCarsObscuringSpeed, 0.2f, 0.025f, false);
+ Source.z += HeightFixerCarsObscuring;
+}
+
+void
+CCam::Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)
+{
+ FOV = DefaultFOV;
+
+ if(!CamTargetEntity->IsVehicle())
+ return;
+
+ float Dist;
+ float HeightTarget = 0.0f;
+ static float AdjustHeightTargetMoveBuffer = 0.0f;
+ static float AdjustHeightTargetMoveSpeed = 0.0f;
+ static float NearClipDistance = 1.5f;
+ const float FarClipDistance = 200.0f;
+ CVector TargetFront, Target;
+ CVector TestSource, TestTarget;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ TargetFront = CameraTarget;
+ TargetFront.x += 18.0f*CamTargetEntity->GetForward().x*SpeedVar;
+ TargetFront.y += 18.0f*CamTargetEntity->GetForward().y*SpeedVar;
+
+ if(ResetStatics){
+ AdjustHeightTargetMoveBuffer = 0.0f;
+ AdjustHeightTargetMoveSpeed = 0.0f;
+ }
+
+ float f = Pow(0.8f, 4.0f);
+ Target = f*CameraTarget + (1.0f-f)*TargetFront;
+ if(Mode == MODE_GTACLASSIC)
+ SpeedVar = TargetSpeedVar;
+ Source = Target + CVector(0.0f, 0.0f, (40.0f*SpeedVar + 30.0f)*0.8f);
+ // What is this? looks horrible
+ if(Mode == MODE_GTACLASSIC)
+ Source.x += (uint8)(100.0f*CameraTarget.x)/500.0f;
+
+ TestSource = Source;
+ TestTarget = TestSource;
+ TestTarget.z = Target.z;
+ if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
+ if(Source.z < colPoint.point.z+3.0f)
+ HeightTarget = colPoint.point.z+3.0f - Source.z;
+ }else{
+ TestSource = Source;
+ TestTarget = TestSource;
+ TestTarget.z += 10.0f;
+ if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false))
+ if(Source.z < colPoint.point.z+3.0f)
+ HeightTarget = colPoint.point.z+3.0f - Source.z;
+ }
+ WellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.2f, 0.02f, false);
+ Source.z += AdjustHeightTargetMoveBuffer;
+
+ if(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)
+ RwCameraSetFarClipPlane(Scene.camera, FarClipDistance);
+ RwCameraSetNearClipPlane(Scene.camera, NearClipDistance);
+
+ Front = CVector(-0.01f, -0.01f, -1.0f); // look down
+ Front.Normalise();
+ Dist = (Source - CameraTarget).Magnitude();
+ m_cvecTargetCoorsForFudgeInter = Dist*Front + Source;
+ Up = CVector(0.0f, 1.0f, 0.0f);
+
+ ResetStatics = false;
+}
+
+void
+CCam::AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit)
+{
+ float Target = 0.0f;
+ float MaxSpeed = 0.13f;
+ float Acceleration = 0.015f;
+ float SpeedMult;
+ float dy;
+ CVector TestPoint2;
+ CVector TestPoint1;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ TestPoint2 = TargetCoors + Offset;
+ TestPoint1 = TargetCoors;
+ TestPoint1.z = TestPoint2.z;
+ if(CWorld::ProcessLineOfSight(TestPoint1, TestPoint2, colPoint, entity, true, false, false, false, false, false, false)){
+ // What is this even?
+ dy = TestPoint1.y - colPoint.point.y;
+ if(dy > yDistLimit)
+ dy = yDistLimit;
+ SpeedMult = yDistLimit - Abs(dy/yDistLimit);
+
+ Target = 2.5f;
+ MaxSpeed += SpeedMult*0.3f;
+ Acceleration += SpeedMult*0.03f;
+ }
+ WellBufferMe(Target, Adjuster, AdjusterSpeed, MaxSpeed, Acceleration, false);
+}
+
+void
+CCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ float Dist;
+ float HeightTarget;
+ static int NumPedPosCountsSoFar = 0;
+ static float PedAverageSpeed = 0.0f;
+ static float AdjustHeightTargetMoveBuffer = 0.0f;
+ static float AdjustHeightTargetMoveSpeed = 0.0f;
+ static float PedSpeedSoFar = 0.0f;
+ static float FarClipDistance = 200.0f;
+ static float NearClipDistance = 1.5f;
+ static float TargetAdjusterForSouth = 0.0f;
+ static float TargetAdjusterSpeedForSouth = 0.0f;
+ static float TargetAdjusterForNorth = 0.0f;
+ static float TargetAdjusterSpeedForNorth = 0.0f;
+ static float TargetAdjusterForEast = 0.0f;
+ static float TargetAdjusterSpeedForEast = 0.0f;
+ static float TargetAdjusterForWest = 0.0f;
+ static float TargetAdjusterSpeedForWest = 0.0f;
+ static CVector PreviousPlayerMoveSpeedVec;
+ CVector TargetCoors, PlayerMoveSpeed;
+ CVector TestSource, TestTarget;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ FOV = DefaultFOV;
+ TargetCoors = CameraTarget;
+ PlayerMoveSpeed = ((CPed*)CamTargetEntity)->GetMoveSpeed();
+
+ if(ResetStatics){
+ PreviousPlayerMoveSpeedVec = PlayerMoveSpeed;
+ AdjustHeightTargetMoveBuffer = 0.0f;
+ AdjustHeightTargetMoveSpeed = 0.0f;
+ NumPedPosCountsSoFar = 0;
+ PedSpeedSoFar = 0.0f;
+ PedAverageSpeed = 0.0f;
+ TargetAdjusterForWest = 0.0f;
+ TargetAdjusterSpeedForWest = 0.0f;
+ TargetAdjusterForEast = 0.0f;
+ TargetAdjusterSpeedForEast = 0.0f;
+ TargetAdjusterForNorth = 0.0f;
+ TargetAdjusterSpeedForNorth = 0.0f;
+ TargetAdjusterForSouth = 0.0f;
+ TargetAdjusterSpeedForSouth = 0.0f;
+ }
+
+ if(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)
+ RwCameraSetFarClipPlane(Scene.camera, FarClipDistance);
+ RwCameraSetNearClipPlane(Scene.camera, NearClipDistance);
+
+ // Average ped speed
+ NumPedPosCountsSoFar++;
+ PedSpeedSoFar += PlayerMoveSpeed.Magnitude();
+ if(NumPedPosCountsSoFar == 5){
+ PedAverageSpeed = 0.4f*PedAverageSpeed + 0.6*(PedSpeedSoFar/5.0f);
+ NumPedPosCountsSoFar = 0;
+ PedSpeedSoFar = 0.0f;
+ }
+ PreviousPlayerMoveSpeedVec = PlayerMoveSpeed;
+
+ // Zoom out depending on speed
+ if(PedAverageSpeed > 0.01f && PedAverageSpeed <= 0.04f)
+ HeightTarget = 2.5f;
+ else if(PedAverageSpeed > 0.04f && PedAverageSpeed <= 0.145f)
+ HeightTarget = 4.5f;
+ else if(PedAverageSpeed > 0.145f)
+ HeightTarget = 7.0f;
+ else
+ HeightTarget = 0.0f;
+
+ // Zoom out if locked on target is far away
+ if(FindPlayerPed()->m_pPointGunAt){
+ Dist = (FindPlayerPed()->m_pPointGunAt->GetPosition() - CameraTarget).Magnitude2D();
+ if(Dist > 6.0f)
+ HeightTarget = max(HeightTarget, Dist/22.0f*37.0f);
+ }
+
+ Source = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
+
+ // Collision checks
+ entity = nil;
+ TestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
+ TestTarget = TestSource;
+ TestTarget.z = TargetCoors.z;
+ if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
+ if(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)
+ HeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);
+ }else{
+ TestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
+ TestTarget = TestSource;
+ TestSource.z += HeightTarget;
+ TestTarget.z = TestSource.z + 10.0f;
+ if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
+ if(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)
+ HeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);
+ }
+ }
+
+ WellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.3f, 0.03f, false);
+ Source.z += AdjustHeightTargetMoveBuffer;
+
+ // Wall checks
+ AvoidWallsTopDownPed(TargetCoors, CVector(0.0f, -3.0f, 3.0f), &TargetAdjusterForSouth, &TargetAdjusterSpeedForSouth, 1.0f);
+ Source.y += TargetAdjusterForSouth;
+ AvoidWallsTopDownPed(TargetCoors, CVector(0.0f, 3.0f, 3.0f), &TargetAdjusterForNorth, &TargetAdjusterSpeedForNorth, 1.0f);
+ Source.y -= TargetAdjusterForNorth;
+ // BUG: east and west flipped
+ AvoidWallsTopDownPed(TargetCoors, CVector(3.0f, 0.0f, 3.0f), &TargetAdjusterForWest, &TargetAdjusterSpeedForWest, 1.0f);
+ Source.x -= TargetAdjusterForWest;
+ AvoidWallsTopDownPed(TargetCoors, CVector(-3.0f, 0.0f, 3.0f), &TargetAdjusterForEast, &TargetAdjusterSpeedForEast, 1.0f);
+ Source.x += TargetAdjusterForEast;
+
+ TargetCoors.y = Source.y + 1.0f;
+ TargetCoors.y += TargetAdjusterForSouth;
+ TargetCoors.x += TargetAdjusterForEast;
+ TargetCoors.x -= TargetAdjusterForWest;
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+#ifdef FIX_BUGS
+ if(Front.x == 0.0f && Front.y == 0.0f)
+ Front.y = 0.0001f;
+#else
+ // someone used = instead of == in the above check by accident
+ Front.x = 0.0f;
+#endif
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Up = CrossProduct(Front, CVector(-1.0f, 0.0f, 0.0f));
+ Up.Normalise();
+
+ ResetStatics = false;
+}
+
+// Identical to M16
+void
+CCam::Process_Rocket(const CVector &CameraTarget, float, float, float)
+{
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ static bool FailedTestTwelveFramesAgo = false;
+ RwV3d HeadPos;
+ CVector TargetCoors;
+
+ FOV = DefaultFOV;
+ TargetCoors = CameraTarget;
+
+ if(ResetStatics){
+ Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ FailedTestTwelveFramesAgo = false;
+ // static DPadVertical unused
+ // static DPadHorizontal unused
+ m_bCollisionChecksOn = true;
+ ResetStatics = false;
+ }
+
+ ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
+ Source = HeadPos;
+ Source.z += 0.1f;
+ Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
+ Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
+
+ // Look around
+ bool UseMouse = false;
+ float MouseX = CPad::GetPad(0)->GetMouseX();
+ float MouseY = CPad::GetPad(0)->GetMouseY();
+ float LookLeftRight, LookUpDown;
+ if(MouseX != 0.0f || MouseY != 0.0f){
+ UseMouse = true;
+ LookLeftRight = -3.0f*MouseX;
+ LookUpDown = 4.0f*MouseY;
+ }else{
+ LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
+ LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
+ }
+ if(UseMouse){
+ Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
+ Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
+ }else{
+ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
+ float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
+ Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
+ Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+ }
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+ TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+ TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source += Front*0.4f;
+
+ if(m_bCollisionChecksOn){
+ if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ CVector TestPoint;
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else
+ FailedTestTwelveFramesAgo = false;
+ }
+ }
+ }
+
+ if(FailedTestTwelveFramesAgo)
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source -= Front*0.4f;
+
+ GetVectorsReadyForRW();
+ float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
+}
+
+// Identical to Rocket
+void
+CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
+{
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ static bool FailedTestTwelveFramesAgo = false;
+ RwV3d HeadPos;
+ CVector TargetCoors;
+
+ FOV = DefaultFOV;
+ TargetCoors = CameraTarget;
+
+ if(ResetStatics){
+ Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ FailedTestTwelveFramesAgo = false;
+ // static DPadVertical unused
+ // static DPadHorizontal unused
+ m_bCollisionChecksOn = true;
+ ResetStatics = false;
+ }
+
+ ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
+ Source = HeadPos;
+ Source.z += 0.1f;
+ Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
+ Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
+
+ // Look around
+ bool UseMouse = false;
+ float MouseX = CPad::GetPad(0)->GetMouseX();
+ float MouseY = CPad::GetPad(0)->GetMouseY();
+ float LookLeftRight, LookUpDown;
+ if(MouseX != 0.0f || MouseY != 0.0f){
+ UseMouse = true;
+ LookLeftRight = -3.0f*MouseX;
+ LookUpDown = 4.0f*MouseY;
+ }else{
+ LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
+ LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
+ }
+ if(UseMouse){
+ Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
+ Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
+ }else{
+ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
+ float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
+ Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
+ Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+ }
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+ TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+ TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source += Front*0.4f;
+
+ if(m_bCollisionChecksOn){
+ if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ CVector TestPoint;
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else
+ FailedTestTwelveFramesAgo = false;
+ }
+ }
+ }
+
+ if(FailedTestTwelveFramesAgo)
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source -= Front*0.4f;
+
+ GetVectorsReadyForRW();
+ float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
+}
+
+void
+CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ static float DontLookThroughWorldFixer = 0.0f;
+ CVector TargetCoors;
+
+ FOV = DefaultFOV;
+ TargetCoors = CameraTarget;
+ if(CamTargetEntity->m_rwObject == nil)
+ return;
+
+ if(ResetStatics){
+ Beta = TargetOrientation;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = TargetOrientation;
+ if(CamTargetEntity->IsPed()){
+ Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ }
+ DontLookThroughWorldFixer = 0.0f;
+ }
+
+ if(CamTargetEntity->IsPed()){
+ static bool FailedTestTwelveFramesAgo = false;
+ RwV3d HeadPos;
+
+ TargetCoors = CameraTarget;
+
+ if(ResetStatics){
+ Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ FailedTestTwelveFramesAgo = false;
+ // static DPadVertical unused
+ // static DPadHorizontal unused
+ m_bCollisionChecksOn = true;
+ ResetStatics = false;
+ }
+
+ ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
+ Source = HeadPos;
+ Source.z += 0.1f;
+ Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
+ Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
+
+ float LookLeftRight, LookUpDown;
+ LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
+ LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
+ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
+ float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
+ Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
+ Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+ TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+ TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source += Front*0.4f;
+
+ if(m_bCollisionChecksOn){
+ if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ CVector TestPoint;
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else
+ FailedTestTwelveFramesAgo = false;
+ }
+ }
+ }
+
+ if(FailedTestTwelveFramesAgo)
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source -= Front*0.4f;
+
+ GetVectorsReadyForRW();
+ float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
+ }else{
+ assert(CamTargetEntity->IsVehicle());
+ CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
+ CVector CamPos = mi->m_vehicleType == VEHICLE_TYPE_BOAT ? mi->m_positions[BOAT_POS_FRONTSEAT] : mi->m_positions[CAR_POS_FRONTSEAT];
+ CamPos.x = 0.0f;
+ CamPos.y += -0.08f;
+ CamPos.z += 0.62f;
+ FOV = 60.0f;
+ Source = Multiply3x3(CamTargetEntity->GetMatrix(), CamPos);
+ Source += CamTargetEntity->GetPosition();
+ if(((CVehicle*)CamTargetEntity)->IsBoat())
+ Source.z += 0.5f;
+
+ if(((CVehicle*)CamTargetEntity)->IsUpsideDown()){
+ if(DontLookThroughWorldFixer < 0.5f)
+ DontLookThroughWorldFixer += 0.03f;
+ else
+ DontLookThroughWorldFixer = 0.5f;
+ }else{
+ if(DontLookThroughWorldFixer < 0.0f)
+#ifdef FIX_BUGS
+ DontLookThroughWorldFixer += 0.03f;
+#else
+ DontLookThroughWorldFixer -= 0.03f;
+#endif
+ else
+ DontLookThroughWorldFixer = 0.0f;
+ }
+ Source.z += DontLookThroughWorldFixer;
+ Front = CamTargetEntity->GetForward();
+ Front.Normalise();
+ Up = CamTargetEntity->GetUp();
+ Up.Normalise();
+ CVector Right = CrossProduct(Front, Up);
+ Right.Normalise();
+ Up = CrossProduct(Right, Front);
+ Up.Normalise();
+ }
+
+ ResetStatics = false;
+}
+
+static CVector vecHeadCamOffset(0.06f, 0.05f, 0.0f);
+
+void
+CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, float)
+{
+ // static int DontLookThroughWorldFixer = 0; // unused
+ static CVector InitialHeadPos;
+
+ if(Mode != MODE_SNIPER_RUNABOUT)
+ FOV = DefaultFOV;
+ TheCamera.m_1rstPersonRunCloseToAWall = false;
+ if(CamTargetEntity->m_rwObject == nil)
+ return;
+
+ if(CamTargetEntity->IsPed()){
+ // static bool FailedTestTwelveFramesAgo = false; // unused
+ RwV3d HeadPos = vecHeadCamOffset;
+ CVector TargetCoors;
+
+ // needs fix for SKINNING
+ RwFrame *frm = ((CPed*)CamTargetEntity)->GetNodeFrame(PED_HEAD);
+ while(frm){
+ RwV3dTransformPoints(&HeadPos, &HeadPos, 1, RwFrameGetMatrix(frm));
+ frm = RwFrameGetParent(frm);
+ if(frm == RpClumpGetFrame(CamTargetEntity->GetClump()))
+ frm = nil;
+ }
+
+ if(ResetStatics){
+ Beta = TargetOrientation;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = TargetOrientation;
+ if(CamTargetEntity->IsPed()){ // useless check
+ Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
+ // FailedTestTwelveFramesAgo = false;
+ m_bCollisionChecksOn = true;
+ }
+ // DontLookThroughWorldFixer = false;
+ m_vecBufferedPlayerBodyOffset = HeadPos;
+ InitialHeadPos = HeadPos;
+ }
+
+ m_vecBufferedPlayerBodyOffset.y = HeadPos.y;
+
+ if(TheCamera.m_bHeadBob){
+ m_vecBufferedPlayerBodyOffset.x =
+ TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.x +
+ (1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.x;
+ m_vecBufferedPlayerBodyOffset.z =
+ TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.z +
+ (1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.z;
+ HeadPos = RwV3d(CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset);
+ }else{
+ float HeadDelta = (HeadPos - InitialHeadPos).Magnitude2D();
+ CVector Fwd = CamTargetEntity->GetForward();
+ Fwd.z = 0.0f;
+ Fwd.Normalise();
+ HeadPos = RwV3d(HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition());
+ HeadPos.z += 0.59f;
+ }
+ Source = HeadPos;
+
+ // unused:
+ // ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&MidPos, PED_MID);
+ // Source - MidPos;
+
+ // Look around
+ bool UseMouse = false;
+ float MouseX = CPad::GetPad(0)->GetMouseX();
+ float MouseY = CPad::GetPad(0)->GetMouseY();
+ float LookLeftRight, LookUpDown;
+ if(MouseX != 0.0f || MouseY != 0.0f){
+ UseMouse = true;
+ LookLeftRight = -3.0f*MouseX;
+ LookUpDown = 4.0f*MouseY;
+ }else{
+ LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
+ LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
+ }
+ if(UseMouse){
+ Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
+ Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
+ }else{
+ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
+ float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
+ Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
+ Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+ }
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+ TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+ TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source += Front*0.4f;
+
+ TheCamera.m_AlphaForPlayerAnim1rstPerson = Alpha;
+
+ GetVectorsReadyForRW();
+
+ float Heading = Front.Heading();
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
+ TheCamera.pTargetEntity->SetHeading(Heading);
+ TheCamera.pTargetEntity->GetMatrix().UpdateRW();
+
+ if(Mode == MODE_SNIPER_RUNABOUT){
+ // no mouse wheel FOV buffering here like in normal sniper mode
+ if(CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()){
+ if(CPad::GetPad(0)->SniperZoomOut())
+ FOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
+ else
+ FOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
+ }
+
+ TheCamera.SetMotionBlur(180, 255, 180, 120, MBLUR_SNIPER);
+
+ if(FOV > DefaultFOV)
+ FOV = DefaultFOV;
+ if(FOV < 15.0f)
+ FOV = 15.0f;
+ }
+ }
+
+ ResetStatics = false;
+ RwCameraSetNearClipPlane(Scene.camera, 0.05f);
+}
+
+void
+CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ if(CamTargetEntity->m_rwObject == nil)
+ return;
+
+#ifdef FIX_BUGS
+ if(!CamTargetEntity->IsPed())
+ return;
+#endif
+
+ static bool FailedTestTwelveFramesAgo = false;
+ RwV3d HeadPos;
+ CVector TargetCoors;
+ TargetCoors = CameraTarget;
+
+ static float TargetFOV = 0.0f;
+
+ if(ResetStatics){
+ Beta = TargetOrientation;
+ Alpha = 0.0f;
+ m_fInitialPlayerOrientation = TargetOrientation;
+ FailedTestTwelveFramesAgo = false;
+ // static DPadVertical unused
+ // static DPadHorizontal unused
+ m_bCollisionChecksOn = true;
+ FOVSpeed = 0.0f;
+ TargetFOV = FOV;
+ ResetStatics = false;
+ }
+
+ ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
+ Source = HeadPos;
+ Source.z += 0.1f;
+ Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
+ Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
+
+ // Look around
+ bool UseMouse = false;
+ float MouseX = CPad::GetPad(0)->GetMouseX();
+ float MouseY = CPad::GetPad(0)->GetMouseY();
+ float LookLeftRight, LookUpDown;
+ if(MouseX != 0.0f || MouseY != 0.0f){
+ UseMouse = true;
+ LookLeftRight = -3.0f*MouseX;
+ LookUpDown = 4.0f*MouseY;
+ }else{
+ LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
+ LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
+ }
+ if(UseMouse){
+ Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
+ Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
+ }else{
+ float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
+ float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
+ Beta += SQR(LookLeftRight/100.0f)*xdir/17.5 * FOV/80.0f * CTimer::GetTimeStep();
+ Alpha += SQR(LookUpDown/150.0f)*ydir/14.0f * FOV/80.0f * CTimer::GetTimeStep();
+ }
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+ if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
+ if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
+
+ TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
+ TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
+ TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
+
+ UseMouse = false;
+ int ZoomInButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN);
+ int ZoomOutButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT);
+ // TODO: enum? this should be mouse wheel up and down
+ if(ZoomInButton == 4 || ZoomInButton == 5 || ZoomOutButton == 4 || ZoomOutButton == 5){
+ if(CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetMouseWheelDown()){
+ if(CPad::GetPad(0)->SniperZoomIn()){
+ TargetFOV = FOV - 10.0f;
+ UseMouse = true;
+ }
+ if(CPad::GetPad(0)->SniperZoomOut()){
+ TargetFOV = FOV + 10.0f;
+ UseMouse = true;
+ }
+ }
+ }
+ if((CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()) && !UseMouse){
+ if(CPad::GetPad(0)->SniperZoomOut()){
+ FOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
+ TargetFOV = FOV;
+ FOVSpeed = 0.0f;
+ }else{
+ FOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
+ TargetFOV = FOV;
+ FOVSpeed = 0.0f;
+ }
+ }else{
+ if(Abs(TargetFOV - FOV) > 0.5f)
+ WellBufferMe(TargetFOV, &FOV, &FOVSpeed, 0.5f, 0.25f, false);
+ else
+ FOVSpeed = 0.0f;
+ }
+
+ TheCamera.SetMotionBlur(180, 255, 180, 120, MBLUR_SNIPER);
+
+ if(FOV > DefaultFOV)
+ FOV = DefaultFOV;
+ if(FOV < 15.0f)
+ FOV = 15.0f;
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source += Front*0.4f;
+
+ if(m_bCollisionChecksOn){
+ if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ CVector TestPoint;
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else{
+ TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
+ TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
+ TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
+ if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ FailedTestTwelveFramesAgo = true;
+ }else
+ FailedTestTwelveFramesAgo = false;
+ }
+ }
+ }
+
+ if(FailedTestTwelveFramesAgo)
+ RwCameraSetNearClipPlane(Scene.camera, 0.4f);
+ Source -= Front*0.4f;
+
+ GetVectorsReadyForRW();
+ float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
+}
+
+void
+CCam::Process_Syphon(const CVector &CameraTarget, float, float, float)
+{
+ FOV = DefaultFOV;
+
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ static bool CameraObscured = false;
+ // unused FailedClippingTestPrevously
+ static float BetaOffset = DEGTORAD(18.0f);
+ // unused AngleToGoTo
+ // unused AngleToGoToSpeed
+ // unused DistBetweenPedAndPlayerPreviouslyOn
+ static float HeightDown = -0.5f;
+ static float PreviousDistForInter;
+ CVector TargetCoors;
+ CVector2D vDist;
+ float fDist, fAimingDist;
+ float TargetAlpha;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ TargetCoors = CameraTarget;
+
+ if(TheCamera.Cams[TheCamera.ActiveCam].Mode != MODE_SYPHON)
+ return;
+
+ vDist = Source - TargetCoors;
+ fDist = vDist.Magnitude();
+ if(fDist == 0.0f)
+ Source = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
+ else
+ Source = TargetCoors + CVector(vDist.x/fDist * 1.7f, vDist.y/fDist * 1.7f, 0.0f);
+ if(fDist > 1.7f)
+ fDist = 1.7f;
+
+ Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+ float NewBeta = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y) + PI;
+ if(ResetStatics){
+ CameraObscured = false;
+ float TestBeta1 = NewBeta - BetaOffset - Beta;
+ float TestBeta2 = NewBeta + BetaOffset - Beta;
+ MakeAngleLessThan180(TestBeta1);
+ MakeAngleLessThan180(TestBeta2);
+ if(Abs(TestBeta1) < Abs(TestBeta2))
+ BetaOffset = -BetaOffset;
+ // some unuseds
+ ResetStatics = false;
+ }
+ Beta = NewBeta + BetaOffset;
+ Source = TargetCoors;
+ Source.x += 1.7f*Cos(Beta);
+ Source.y += 1.7f*Sin(Beta);
+ TargetCoors.z += m_fSyphonModeTargetZOffSet;
+ fAimingDist = (TheCamera.m_cvecAimingTargetCoors - TargetCoors).Magnitude2D();
+ if(fAimingDist < 6.5f)
+ fAimingDist = 6.5f;
+ TargetAlpha = CGeneral::GetATanOfXY(fAimingDist, TheCamera.m_cvecAimingTargetCoors.z - TargetCoors.z);
+ while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
+ while(TargetAlpha < -PI) TargetAlpha += 2*PI;
+
+ // inlined
+ WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true);
+
+ Source.z += fDist*Sin(Alpha) + fDist*0.2f;
+ if(Source.z < TargetCoors.z + HeightDown)
+ Source.z = TargetCoors.z + HeightDown;
+
+ CameraObscured = CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true);
+ // PreviousDistForInter unused
+ if(CameraObscured){
+ PreviousDistForInter = (TargetCoors - colPoint.point).Magnitude2D();
+ Source = colPoint.point;
+ }else
+ PreviousDistForInter = 1.7f;
+
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ m_fMinDistAwayFromCamWhenInterPolating = Front.Magnitude2D();
+ if(m_fMinDistAwayFromCamWhenInterPolating < 1.1f)
+ RwCameraSetNearClipPlane(Scene.camera, max(m_fMinDistAwayFromCamWhenInterPolating - 0.35f, 0.05f));
+ Front.Normalise();
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float)
+{
+ FOV = DefaultFOV;
+
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ CVector TargetCoors = CameraTarget;
+ CVector vDist;
+ float fDist, TargetDist;
+ float zOffset;
+ float AimingAngle;
+ CColPoint colPoint;
+ CEntity *entity;
+
+ TargetDist = TheCamera.m_fPedZoomValueSmooth * 0.5f + 4.0f;
+ vDist = Source - TargetCoors;
+ fDist = vDist.Magnitude2D();
+ zOffset = TargetDist - 2.65f;
+ if(zOffset < 0.0f)
+ zOffset = 0.0f;
+ if(zOffset == 0.0f)
+ Source = TargetCoors + CVector(1.0f, 1.0f, zOffset);
+ else
+ Source = TargetCoors + CVector(vDist.x/fDist*TargetDist, vDist.y/fDist*TargetDist, zOffset);
+
+ AimingAngle = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y);
+ while(AimingAngle >= PI) AimingAngle -= 2*PI;
+ while(AimingAngle < -PI) AimingAngle += 2*PI;
+
+ if(TheCamera.PlayerWeaponMode.Mode == MODE_SYPHON)
+ Beta = AimingAngle + m_fPlayerInFrontSyphonAngleOffSet;
+
+ Source.x = TargetCoors.x;
+ Source.y = TargetCoors.y;
+ Source.x += Cos(Beta) * TargetDist;
+ Source.y += Sin(Beta) * TargetDist;
+
+ if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
+ Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
+ fDist = (TargetCoors - colPoint.point).Magnitude2D();
+ Source.x = TargetCoors.x;
+ Source.y = TargetCoors.y;
+ Source.x += Cos(Beta) * fDist;
+ Source.y += Sin(Beta) * fDist;
+ }
+
+ TargetCoors = CameraTarget;
+ TargetCoors.z += m_fSyphonModeTargetZOffSet;
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ if(!CamTargetEntity->IsVehicle()){
+ ResetStatics = false;
+ return;
+ }
+
+ CVector TargetCoors = CameraTarget;
+ float DeltaBeta = 0.0f;
+ static CColPoint colPoint;
+ CEntity *entity;
+ static float TargetWhenChecksWereOn = 0.0f;
+ static float CenterObscuredWhenChecksWereOn = 0.0f;
+ static float WaterZAddition = 2.75f;
+ float WaterLevel = 0.0f;
+ float s, c;
+ float Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
+ FOV = DefaultFOV;
+
+ if(ResetStatics){
+ CenterObscuredWhenChecksWereOn = 0.0f;
+ TargetWhenChecksWereOn = 0.0f;
+ Beta = TargetOrientation + PI;
+ }
+
+ CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterLevel);
+ WaterLevel += WaterZAddition;
+ static float FixerForGoingBelowGround = 0.4f;
+ if(-FixerForGoingBelowGround < TargetCoors.z-WaterLevel)
+ WaterLevel += TargetCoors.z-WaterLevel - FixerForGoingBelowGround;
+
+ bool Obscured;
+ if(m_bCollisionChecksOn || ResetStatics){
+ CVector TestPoint;
+ // Weird calculations here, also casting bool to float...
+ c = Cos(TargetOrientation);
+ s = Sin(TargetOrientation);
+ TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
+ (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
+ TargetCoors;
+ TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
+ float Test1 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
+
+ c = Cos(TargetOrientation + 0.8f);
+ s = Sin(TargetOrientation + DEGTORAD(40.0f));
+ TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
+ (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
+ TargetCoors;
+ TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
+ float Test2 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
+
+ c = Cos(TargetOrientation - 0.8);
+ s = Sin(TargetOrientation - DEGTORAD(40.0f));
+ TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
+ (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
+ TargetCoors;
+ TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
+ float Test3 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
+
+ if(Test2 == 0.0f){
+ DeltaBeta = TargetOrientation - Beta - DEGTORAD(40.0f);
+ if(ResetStatics)
+ Beta = TargetOrientation - DEGTORAD(40.0f);
+ }else if(Test3 == 0.0f){
+ DeltaBeta = TargetOrientation - Beta + DEGTORAD(40.0f);
+ if(ResetStatics)
+ Beta = TargetOrientation + DEGTORAD(40.0f);
+ }else if(Test1 == 0.0f){
+ DeltaBeta = 0.0f;
+ }else if(Test2 != 0.0f && Test3 != 0.0f && Test1 != 0.0f){
+ if(ResetStatics)
+ Beta = TargetOrientation;
+ DeltaBeta = TargetOrientation - Beta;
+ }
+
+ c = Cos(Beta);
+ s = Sin(Beta);
+ TestPoint.x = TheCamera.CarZoomValueSmooth * -c +
+ (TheCamera.CarZoomValueSmooth + 7.0f) * -c +
+ TargetCoors.x;
+ TestPoint.y = TheCamera.CarZoomValueSmooth * -s +
+ (TheCamera.CarZoomValueSmooth + 7.0f) * -s +
+ TargetCoors.y;
+ TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
+ Obscured = CWorld::ProcessLineOfSight(TestPoint, TargetCoors, colPoint, entity, true, false, false, true, false, true, true);
+ CenterObscuredWhenChecksWereOn = Obscured;
+
+ // now DeltaBeta == TargetWhenChecksWereOn - Beta, which we need for WellBufferMe below
+ TargetWhenChecksWereOn = DeltaBeta + Beta;
+ }else{
+ // DeltaBeta = TargetWhenChecksWereOn - Beta; // unneeded since we don't inline WellBufferMe
+ Obscured = CenterObscuredWhenChecksWereOn != 0.0f;
+ }
+
+ if(Obscured){
+ CWorld::ProcessLineOfSight(Source, TargetCoors, colPoint, entity, true, false, false, true, false, true, true);
+ Source = colPoint.point;
+ }else{
+ // inlined
+ WellBufferMe(TargetWhenChecksWereOn, &Beta, &BetaSpeed, 0.07f, 0.015f, true);
+
+ s = Sin(Beta);
+ c = Cos(Beta);
+ Source = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
+ (TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
+ TargetCoors;
+ Source.z = WaterLevel + TheCamera.CarZoomValueSmooth;
+ }
+
+ if(TheCamera.CarZoomValueSmooth < 0.05f){
+ static float AmountUp = 2.2f;
+ TargetCoors.z += AmountUp * (0.0f - TheCamera.CarZoomValueSmooth);
+ }
+ TargetCoors.z += TheCamera.CarZoomValueSmooth + 0.5f;
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ GetVectorsReadyForRW();
+ ResetStatics = false;
+}
+
+void
+CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ if(!CamTargetEntity->IsPed())
+ return;
+
+ FOV = DefaultFOV;
+ float BetaLeft, BetaRight, DeltaBetaLeft, DeltaBetaRight;
+ float BetaFix;
+ float Dist;
+ float BetaMaxSpeed = 0.015f;
+ float BetaAcceleration = 0.007f;
+ static bool PreviouslyFailedBuildingChecks = false;
+ float TargetCamHeight;
+ CVector TargetCoors;
+
+ m_fMinDistAwayFromCamWhenInterPolating = 4.0f;
+ Front = Source - CameraTarget;
+ Beta = CGeneral::GetATanOfXY(Front.x, Front.y);
+ while(TargetOrientation >= PI) TargetOrientation -= 2*PI;
+ while(TargetOrientation < -PI) TargetOrientation += 2*PI;
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+ // Figure out Beta
+ BetaLeft = TargetOrientation - HALFPI;
+ BetaRight = TargetOrientation + HALFPI;
+ DeltaBetaLeft = Beta - BetaLeft;
+ DeltaBetaRight = Beta - BetaRight;
+ while(DeltaBetaLeft >= PI) DeltaBetaLeft -= 2*PI;
+ while(DeltaBetaLeft < -PI) DeltaBetaLeft += 2*PI;
+ while(DeltaBetaRight >= PI) DeltaBetaRight -= 2*PI;
+ while(DeltaBetaRight < -PI) DeltaBetaRight += 2*PI;
+
+ if(ResetStatics){
+ if(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))
+ m_fTargetBeta = DeltaBetaLeft;
+ else
+ m_fTargetBeta = DeltaBetaRight;
+ m_fBufferedTargetOrientation = TargetOrientation;
+ m_fBufferedTargetOrientationSpeed = 0.0f;
+ m_bCollisionChecksOn = true;
+ BetaSpeed = 0.0f;
+ }else if(CPad::GetPad(0)->WeaponJustDown()){
+ if(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))
+ m_fTargetBeta = DeltaBetaLeft;
+ else
+ m_fTargetBeta = DeltaBetaRight;
+ }
+
+ // Check collisions
+ BetaFix = 0.0f;
+ Dist = Front.Magnitude2D();
+ if(m_bCollisionChecksOn || PreviouslyFailedBuildingChecks){
+ BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.25f, 0.0f, true, false, false, true, false);
+ if(BetaFix == 0.0f){
+ BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, DEGTORAD(24.0f), true, false, false, true, false);
+ if(BetaFix == 0.0f)
+ BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, -DEGTORAD(24.0f), true, false, false, true, false);
+ }
+ }
+ if(BetaFix != 0.0f){
+ BetaMaxSpeed = 0.1f;
+ PreviouslyFailedBuildingChecks = true;
+ BetaAcceleration = 0.025f;
+ m_fTargetBeta = Beta + BetaFix;
+ }
+ WellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true);
+
+ Source = CameraTarget + 4.0f*CVector(Cos(Beta), Sin(Beta), 0.0f);
+ Source.z -= 0.5f;
+
+ WellBufferMe(TargetOrientation, &m_fBufferedTargetOrientation, &m_fBufferedTargetOrientationSpeed, 0.07f, 0.004f, true);
+ TargetCoors = CameraTarget + 0.5f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f);
+
+ TargetCamHeight = CameraTarget.z - Source.z + max(m_fPedBetweenCameraHeightOffset, m_fRoadOffSet + m_fDimensionOfHighestNearCar) - 0.5f;
+ if(TargetCamHeight > m_fCamBufferedHeight)
+ WellBufferMe(TargetCamHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.15f, 0.04f, false);
+ else
+ WellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.08f, 0.0175f, false);
+ Source.z += m_fCamBufferedHeight;
+
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ GetVectorsReadyForRW();
+
+ ResetStatics = false;
+}
+
+/*
+// Spline format is this, but game doesn't seem to use any kind of struct:
+struct Spline
+{
+ float numFrames;
+ struct {
+ float time;
+ float f[3]; // CVector for Vector spline
+ } frames[1]; // numFrames
+};
+*/
+
+// These two functions are pretty ugly
+
+#define MS(t) (uint32)((t)*1000.0f)
+
+void
+FindSplinePathPositionFloat(float *out, float *spline, uint32 time, uint32 &marker)
+{
+ // marker is at time
+ uint32 numFrames = spline[0];
+ uint32 timeDelta = MS(spline[marker] - spline[marker-4]);
+ uint32 endTime = MS(spline[4*(numFrames-1) + 1]);
+ if(time < endTime){
+ bool canAdvance = true;
+ if((marker-1)/4 > numFrames){
+ canAdvance = false;
+ marker = 4*(numFrames-1) + 1;
+ }
+ // skipping over small time deltas apparently?
+ while(timeDelta <= 75 && canAdvance){
+ marker += 4;
+ if((marker-1)/4 > numFrames){
+ canAdvance = false;
+ marker = 4*(numFrames-1) + 1;
+ }
+ timeDelta = (spline[marker] - spline[marker-4]) * 1000.0f;
+ }
+ }
+ float a = ((float)time - (float)MS(spline[marker-4])) / (float)MS(spline[marker] - spline[marker-4]);
+ a = clamp(a, 0.0f, 1.0f);
+ float b = 1.0f - a;
+ *out = b*b*b * spline[marker-3] +
+ 3.0f*a*b*b * spline[marker-1] +
+ 3.0f*a*a*b * spline[marker+2] +
+ a*a*a * spline[marker+1];
+}
+
+void
+FindSplinePathPositionVector(CVector *out, float *spline, uint32 time, uint32 &marker)
+{
+ // marker is at time
+ uint32 numFrames = spline[0];
+ uint32 timeDelta = MS(spline[marker] - spline[marker-10]);
+ uint32 endTime = MS(spline[10*(numFrames-1) + 1]);
+ if(time < endTime){
+ bool canAdvance = true;
+ if((marker-1)/10 > numFrames){
+ canAdvance = false;
+ marker = 10*(numFrames-1) + 1;
+ }
+ // skipping over small time deltas apparently?
+ while(timeDelta <= 75 && canAdvance){
+ marker += 10;
+ if((marker-1)/10 > numFrames){
+ canAdvance = false;
+ marker = 10*(numFrames-1) + 1;
+ }
+ timeDelta = (spline[marker] - spline[marker-10]) * 1000.0f;
+ }
+ }
+
+ if((marker-1)/10 > numFrames){
+ printf("Arraymarker %i \n", marker);
+ printf("Path zero %i \n", numFrames);
+ }
+
+ float a = ((float)time - (float)MS(spline[marker-10])) / (float)MS(spline[marker] - spline[marker-10]);
+ a = clamp(a, 0.0f, 1.0f);
+ float b = 1.0f - a;
+ out->x =
+ b*b*b * spline[marker-9] +
+ 3.0f*a*b*b * spline[marker-3] +
+ 3.0f*a*a*b * spline[marker+4] +
+ a*a*a * spline[marker+1];
+ out->y =
+ b*b*b * spline[marker-8] +
+ 3.0f*a*b*b * spline[marker-2] +
+ 3.0f*a*a*b * spline[marker+5] +
+ a*a*a * spline[marker+2];
+ out->z =
+ b*b*b * spline[marker-7] +
+ 3.0f*a*b*b * spline[marker-1] +
+ 3.0f*a*a*b * spline[marker+6] +
+ a*a*a * spline[marker+3];
+ *out += TheCamera.m_vecCutSceneOffset;
+}
+
+void
+CCam::Process_FlyBy(const CVector&, float, float, float)
+{
+ float UpAngle = 0.0f;
+ static float FirstFOVValue = 0.0f;
+ static float PsuedoFOV;
+ static uint32 ArrayMarkerFOV;
+ static uint32 ArrayMarkerUp;
+ static uint32 ArrayMarkerSource;
+ static uint32 ArrayMarkerFront;
+
+ if(TheCamera.m_bcutsceneFinished)
+ return;
+
+ Up = CVector(0.0f, 0.0f, 1.0f);
+ if(TheCamera.m_bStartingSpline)
+ m_fTimeElapsedFloat += CTimer::GetTimeStepInMilliseconds();
+ else{
+ m_fTimeElapsedFloat = 0.0f;
+ m_uiFinishTime = MS(TheCamera.m_arrPathArray[2].m_arr_PathData[10*((int)TheCamera.m_arrPathArray[2].m_arr_PathData[0]-1) + 1]);
+ TheCamera.m_bStartingSpline = true;
+ FirstFOVValue = TheCamera.m_arrPathArray[0].m_arr_PathData[2];
+ PsuedoFOV = TheCamera.m_arrPathArray[0].m_arr_PathData[2];
+ ArrayMarkerFOV = 5;
+ ArrayMarkerUp = 5;
+ ArrayMarkerSource = 11;
+ ArrayMarkerFront = 11;
+ }
+
+ float fTime = m_fTimeElapsedFloat;
+ uint32 uiFinishTime = m_uiFinishTime;
+ uint32 uiTime = fTime;
+ if(uiTime < uiFinishTime){
+ TheCamera.m_fPositionAlongSpline = (float) uiTime / uiFinishTime;
+
+ while(uiTime >= (TheCamera.m_arrPathArray[2].m_arr_PathData[ArrayMarkerSource] - TheCamera.m_arrPathArray[2].m_arr_PathData[1])*1000.0f)
+ ArrayMarkerSource += 10;
+ FindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);
+
+ while(uiTime >= (TheCamera.m_arrPathArray[3].m_arr_PathData[ArrayMarkerFront] - TheCamera.m_arrPathArray[3].m_arr_PathData[1])*1000.0f)
+ ArrayMarkerFront += 10;
+ FindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);
+
+ while(uiTime >= (TheCamera.m_arrPathArray[1].m_arr_PathData[ArrayMarkerUp] - TheCamera.m_arrPathArray[1].m_arr_PathData[1])*1000.0f)
+ ArrayMarkerUp += 4;
+ FindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);
+ UpAngle = DEGTORAD(UpAngle) + HALFPI;
+ Up.x = Cos(UpAngle);
+ Up.z = Sin(UpAngle);
+
+ while(uiTime >= (TheCamera.m_arrPathArray[0].m_arr_PathData[ArrayMarkerFOV] - TheCamera.m_arrPathArray[0].m_arr_PathData[1])*1000.0f)
+ ArrayMarkerFOV += 4;
+ FindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);
+
+ m_cvecTargetCoorsForFudgeInter = Front;
+ Front = Front - Source;
+ Front.Normalise();
+ CVector Left = CrossProduct(Up, Front);
+ Up = CrossProduct(Front, Left);
+ Up.Normalise();
+ FOV = PsuedoFOV;
+ }else{
+ // end
+ ArrayMarkerSource = (TheCamera.m_arrPathArray[2].m_arr_PathData[0] - 1)*10 + 1;
+ ArrayMarkerFront = (TheCamera.m_arrPathArray[3].m_arr_PathData[0] - 1)*10 + 1;
+ ArrayMarkerUp = (TheCamera.m_arrPathArray[1].m_arr_PathData[0] - 1)*4 + 1;
+ ArrayMarkerFOV = (TheCamera.m_arrPathArray[0].m_arr_PathData[0] - 1)*4 + 1;
+
+ FindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);
+ FindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);
+ FindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);
+ UpAngle = DEGTORAD(UpAngle) + HALFPI;
+ Up.x = Cos(UpAngle);
+ Up.z = Sin(UpAngle);
+ FindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);
+
+ TheCamera.m_fPositionAlongSpline = 1.0f;
+ ArrayMarkerFOV = 0;
+ ArrayMarkerUp = 0;
+ ArrayMarkerSource = 0;
+ ArrayMarkerFront = 0;
+
+ m_cvecTargetCoorsForFudgeInter = Front;
+ Front = Front - Source;
+ Front.Normalise();
+ CVector Left = CrossProduct(Up, Front);
+ Up = CrossProduct(Front, Left);
+ Up.Normalise();
+ FOV = PsuedoFOV;
+ }
+}
+
+void
+CCam::Process_WheelCam(const CVector&, float, float, float)
+{
+ FOV = DefaultFOV;
+
+ if(CamTargetEntity->IsPed()){
+ // what? ped with wheels or what?
+ Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-0.3f, -0.5f, 0.1f));
+ Source += CamTargetEntity->GetPosition();
+ Front = CVector(1.0f, 0.0f, 0.0f);
+ }else{
+ Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));
+ Source += CamTargetEntity->GetPosition();
+ Front = CamTargetEntity->GetForward();
+ }
+
+ CVector NewUp(0.0f, 0.0f, 1.0f);
+ CVector Left = CrossProduct(Front, NewUp);
+ Left.Normalise();
+ NewUp = CrossProduct(Left, Front);
+
+ float Roll = Cos((CTimer::GetTimeInMilliseconds()&0x1FFFF)/(float)0x1FFFF * TWOPI);
+ Up = Cos(Roll*0.4f)*NewUp + Sin(Roll*0.4f)*Left;
+}
+
+void
+CCam::Process_Fixed(const CVector &CameraTarget, float, float, float)
+{
+ Source = m_cvecCamFixedModeSource;
+ Front = CameraTarget - Source;
+ m_cvecTargetCoorsForFudgeInter = CameraTarget;
+ GetVectorsReadyForRW();
+
+ Up = CVector(0.0f, 0.0f, 1.0f) + m_cvecCamFixedModeUpOffSet;
+ Up.Normalise();
+ CVector Right = CrossProduct(Front, Up);
+ Right.Normalise();
+ Up = CrossProduct(Right, Front);
+
+ FOV = DefaultFOV;
+ if(TheCamera.m_bUseSpecialFovTrain)
+ FOV = TheCamera.m_fFovForTrain;
+
+ if(CMenuManager::m_ControlMethod == 0 && Using3rdPersonMouseCam()){
+ CPed *player = FindPlayerPed();
+ if(player && player->CanStrafeOrMouseControl()){
+ float Heading = Front.Heading();
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
+ ((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
+ TheCamera.pTargetEntity->SetHeading(Heading);
+ TheCamera.pTargetEntity->GetMatrix().UpdateRW();
+ }
+ }
+}
+
+void
+CCam::Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ CColPoint colPoint;
+ CEntity *entity = nil;
+
+ FOV = DefaultFOV;
+ Source = CameraTarget;
+ Source.x += -4.5f*Cos(TargetOrientation);
+ Source.y += -4.5f*Sin(TargetOrientation);
+ Source.z = m_vecLastAboveWaterCamPosition.z + 4.0f;
+
+ m_cvecTargetCoorsForFudgeInter = CameraTarget;
+ Front = CameraTarget - Source;
+ Front.Normalise();
+ if(CWorld::ProcessLineOfSight(CameraTarget, Source, colPoint, entity, true, false, false, true, false, true, true))
+ Source = colPoint.point;
+ GetVectorsReadyForRW();
+ Front = CameraTarget - Source;
+ Front.Normalise();
+}
+
+// unused
+void
+CCam::Process_Circle(const CVector &CameraTarget, float, float, float)
+{
+ FOV = DefaultFOV;
+
+ Front.x = Cos(0.7f) * Cos((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI);
+ Front.y = Cos(0.7f) * Sin((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI);
+ Front.z = -Sin(0.7f);
+ Source = CameraTarget - 4.0f*Front;
+ Source.z += 1.0f;
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float)
+{
+ Source = m_cvecCamFixedModeSource;
+ m_cvecTargetCoorsForFudgeInter = CameraTarget;
+ m_cvecTargetCoorsForFudgeInter.z += m_fSyphonModeTargetZOffSet;
+ Front = CameraTarget - Source;
+ Front.z += m_fSyphonModeTargetZOffSet;
+
+ GetVectorsReadyForRW();
+
+ Up += m_cvecCamFixedModeUpOffSet;
+ Up.Normalise();
+ CVector Left = CrossProduct(Up, Front);
+ Left.Normalise();
+ Front = CrossProduct(Left, Up);
+ Front.Normalise();
+ FOV = DefaultFOV;
+}
+
+#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))
+
+
+void
+CCam::Process_Debug(const CVector&, float, float, float)
+{
+ static float Speed = 0.0f;
+ static float PanSpeedX = 0.0f;
+ static float PanSpeedY = 0.0f;
+ CVector TargetCoors;
+
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ FOV = DefaultFOV;
+ Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
+ Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
+ if(CPad::GetPad(0)->GetLeftMouse()){
+ Alpha += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);
+ Beta -= DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);
+ }
+
+ TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 3.0f;
+ TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 3.0f;
+ TargetCoors.z = Source.z + Sin(Alpha) * 3.0f;
+
+ if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
+ if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
+
+ if(CPad::GetPad(1)->GetSquare() || KEYDOWN('W'))
+ Speed += 0.1f;
+ else if(CPad::GetPad(1)->GetCross() || KEYDOWN('S'))
+ Speed -= 0.1f;
+ else
+ Speed = 0.0f;
+ if(Speed > 70.0f) Speed = 70.0f;
+ if(Speed < -70.0f) Speed = -70.0f;
+
+
+ if(KEYDOWN(rsRIGHT) || KEYDOWN('D'))
+ PanSpeedX += 0.1f;
+ else if(KEYDOWN(rsLEFT) || KEYDOWN('A'))
+ PanSpeedX -= 0.1f;
+ else
+ PanSpeedX = 0.0f;
+ if(PanSpeedX > 70.0f) PanSpeedX = 70.0f;
+ if(PanSpeedX < -70.0f) PanSpeedX = -70.0f;
+
+
+ if(KEYDOWN(rsUP))
+ PanSpeedY += 0.1f;
+ else if(KEYDOWN(rsDOWN))
+ PanSpeedY -= 0.1f;
+ else
+ PanSpeedY = 0.0f;
+ if(PanSpeedY > 70.0f) PanSpeedY = 70.0f;
+ if(PanSpeedY < -70.0f) PanSpeedY = -70.0f;
+
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source = Source + Front*Speed;
+
+ Up = CVector{ 0.0f, 0.0f, 1.0f };
+ CVector Right = CrossProduct(Front, Up);
+ Up = CrossProduct(Right, Front);
+ Source = Source + Up*PanSpeedY + Right*PanSpeedX;
+
+ if(Source.z < -450.0f)
+ Source.z = -450.0f;
+
+ if(CPad::GetPad(1)->GetRightShoulder2JustDown() || KEYJUSTDOWN(rsENTER)){
+ if(FindPlayerVehicle())
+ FindPlayerVehicle()->Teleport(Source);
+ else
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition() = Source;
+ }
+
+ // stay inside sectors
+ while(CWorld::GetSectorX(Source.x) > 95.0f)
+ Source.x -= 1.0f;
+ while(CWorld::GetSectorX(Source.x) < 5.0f)
+ Source.x += 1.0f;
+ while(CWorld::GetSectorY(Source.y) > 95.0f)
+ Source.y -= 1.0f;
+ while(CWorld::GetSectorY(Source.y) < 5.0f)
+ Source.y += 1.0f;
+ GetVectorsReadyForRW();
+
+ CPad::GetPad(0)->DisablePlayerControls = PLAYERCONTROL_DISABLED_1;
+
+ if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
+ 12.0f, 0.0f, 0.0f, -12.0f,
+ 128, 128, 128, 128, 1000.0f, false, 1.0f);
+
+ if(CHud::m_Wants_To_Draw_Hud){
+ char str[256];
+ sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
+ sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
+ sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
+ }
+}
+#else
+void
+CCam::Process_Debug(const CVector&, float, float, float)
+{
+ static float Speed = 0.0f;
+ CVector TargetCoors;
+
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ FOV = DefaultFOV;
+ Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
+ Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
+
+ TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 3.0f;
+ TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 3.0f;
+ TargetCoors.z = Source.z + Sin(Alpha) * 3.0f;
+
+ if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
+ if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
+
+ if(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())
+ Speed += 0.1f;
+ else if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())
+ Speed -= 0.1f;
+ else
+ Speed = 0.0f;
+ if(Speed > 70.0f) Speed = 70.0f;
+ if(Speed < -70.0f) Speed = -70.0f;
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source = Source + Front*Speed;
+
+ if(Source.z < -450.0f)
+ Source.z = -450.0f;
+
+ if(CPad::GetPad(1)->GetRightShoulder2JustDown()){
+ if(FindPlayerVehicle())
+ FindPlayerVehicle()->Teleport(Source);
+ else
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition() = Source;
+
+ }
+
+ // stay inside sectors
+ while(CWorld::GetSectorX(Source.x) > 95.0f)
+ Source.x -= 1.0f;
+ while(CWorld::GetSectorX(Source.x) < 5.0f)
+ Source.x += 1.0f;
+ while(CWorld::GetSectorY(Source.y) > 95.0f)
+ Source.y -= 1.0f;
+ while(CWorld::GetSectorY(Source.y) < 5.0f)
+ Source.y += 1.0f;
+ GetVectorsReadyForRW();
+
+ if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
+ 12.0f, 0.0f, 0.0f, -12.0f,
+ 128, 128, 128, 128, 1000.0f, false, 1.0f);
+
+ if(CHud::m_Wants_To_Draw_Hud){
+ char str[256];
+ sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
+ sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
+ sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
+ }
+}
+#endif
+
+void
+CCam::Process_Editor(const CVector&, float, float, float)
+{
+ static float Speed = 0.0f;
+ CVector TargetCoors;
+
+ if(ResetStatics){
+ Source = CVector(796.0f, -937.0, 40.0f);
+ CamTargetEntity = nil;
+ }
+ ResetStatics = false;
+
+ RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ FOV = DefaultFOV;
+ Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
+ Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
+
+ if(CamTargetEntity && CSceneEdit::m_bCameraFollowActor){
+ TargetCoors = CamTargetEntity->GetPosition();
+ }else if(CSceneEdit::m_bRecording){
+ TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 7.0f;
+ TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 7.0f;
+ TargetCoors.z = Source.z + Sin(Alpha) * 7.0f;
+ }else
+ TargetCoors = CSceneEdit::m_vecCamHeading + Source;
+ CSceneEdit::m_vecCurrentPosition = TargetCoors;
+ CSceneEdit::m_vecCamHeading = TargetCoors - Source;
+
+ if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
+ if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
+
+ if(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())
+ Speed += 0.1f;
+ else if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())
+ Speed -= 0.1f;
+ else
+ Speed = 0.0f;
+ if(Speed > 70.0f) Speed = 70.0f;
+ if(Speed < -70.0f) Speed = -70.0f;
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ Source = Source + Front*Speed;
+
+ if(Source.z < -450.0f)
+ Source.z = -450.0f;
+
+ if(CPad::GetPad(1)->GetRightShoulder2JustDown()){
+ if(FindPlayerVehicle())
+ FindPlayerVehicle()->Teleport(Source);
+ else
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition() = Source;
+
+ }
+
+ // stay inside sectors
+ while(CWorld::GetSectorX(Source.x) > 95.0f)
+ Source.x -= 1.0f;
+ while(CWorld::GetSectorX(Source.x) < 5.0f)
+ Source.x += 1.0f;
+ while(CWorld::GetSectorY(Source.y) > 95.0f)
+ Source.y -= 1.0f;
+ while(CWorld::GetSectorY(Source.y) < 5.0f)
+ Source.y += 1.0f;
+ GetVectorsReadyForRW();
+
+ if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
+ CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
+ 12.0f, 0.0f, 0.0f, -12.0f,
+ 128, 128, 128, 128, 1000.0f, false, 1.0f);
+
+ if(CHud::m_Wants_To_Draw_Hud){
+ char str[256];
+ sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
+ sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
+ sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
+ }
+}
+
+void
+CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
+{
+ CVector TargetCoors = CameraTarget;
+ float Angle = Atan2(Front.x, Front.y);
+ FOV = DefaultFOV;
+
+ Angle += CPad::GetPad(0)->GetLeftStickX()/1280.0f;
+ if(Distance < 10.0f)
+ Distance += CPad::GetPad(0)->GetLeftStickY()/1000.0f;
+ else
+ Distance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f;
+ if(Distance < 1.5f)
+ Distance = 1.5f;
+
+ Front.x = Cos(0.3f) * Sin(Angle);
+ Front.y = Cos(0.3f) * Cos(Angle);
+ Front.z = -Sin(0.3f);
+ Source = CameraTarget - Distance*Front;
+
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::ProcessPedsDeadBaby(void)
+{
+ float Distance = 0.0f;
+ static bool SafeToRotate = false;
+ CVector TargetDist, TestPoint;
+
+ FOV = DefaultFOV;
+ TargetDist = Source - CamTargetEntity->GetPosition();
+ Distance = TargetDist.Magnitude();
+ Beta = CGeneral::GetATanOfXY(TargetDist.x, TargetDist.y);
+ while(Beta >= PI) Beta -= 2*PI;
+ while(Beta < -PI) Beta += 2*PI;
+
+ if(ResetStatics){
+ TestPoint = CamTargetEntity->GetPosition() +
+ CVector(4.0f * Cos(Alpha) * Cos(Beta),
+ 4.0f * Cos(Alpha) * Sin(Beta),
+ 4.0f * Sin(Alpha));
+ bool Safe1 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
+
+ TestPoint = CamTargetEntity->GetPosition() +
+ CVector(4.0f * Cos(Alpha) * Cos(Beta + DEGTORAD(120.0f)),
+ 4.0f * Cos(Alpha) * Sin(Beta + DEGTORAD(120.0f)),
+ 4.0f * Sin(Alpha));
+ bool Safe2 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
+
+ TestPoint = CamTargetEntity->GetPosition() +
+ CVector(4.0f * Cos(Alpha) * Cos(Beta - DEGTORAD(120.0f)),
+ 4.0f * Cos(Alpha) * Sin(Beta - DEGTORAD(120.0f)),
+ 4.0f * Sin(Alpha));
+ bool Safe3 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
+
+ SafeToRotate = Safe1 && Safe2 && Safe3;
+
+ ResetStatics = false;
+ }
+
+ if(SafeToRotate)
+ WellBufferMe(Beta + DEGTORAD(175.0f), &Beta, &BetaSpeed, 0.015f, 0.007f, true);
+
+ WellBufferMe(DEGTORAD(89.5f), &Alpha, &AlphaSpeed, 0.015f, 0.07f, true);
+ WellBufferMe(35.0f, &Distance, &DistanceSpeed, 0.006f, 0.007f, false);
+
+ Source = CamTargetEntity->GetPosition() +
+ CVector(Distance * Cos(Alpha) * Cos(Beta),
+ Distance * Cos(Alpha) * Sin(Beta),
+ Distance * Sin(Alpha));
+ m_cvecTargetCoorsForFudgeInter = CamTargetEntity->GetPosition();
+ Front = CamTargetEntity->GetPosition() - Source;
+ Front.Normalise();
+ GetVectorsReadyForRW();
+}
+
+bool
+CCam::ProcessArrestCamOne(void)
+{
+ FOV = 45.0f;
+ if(ResetStatics)
+ return true;
+
+#ifdef FIX_BUGS
+ if(!CamTargetEntity->IsPed())
+ return true;
+#endif
+
+ bool found;
+ float Ground;
+ CVector PlayerCoors = TheCamera.pTargetEntity->GetPosition();
+ CVector CopCoors = ((CPlayerPed*)TheCamera.pTargetEntity)->m_pArrestingCop->GetPosition();
+ Beta = CGeneral::GetATanOfXY(PlayerCoors.x - CopCoors.x, PlayerCoors.y - CopCoors.y);
+
+ Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f);
+ Source.z += 6.0f;
+ Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found);
+ if(!found){
+ Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found);
+ if(!found)
+ return false;
+ }
+ Source.z = Ground + 0.25f;
+ if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true)){
+ Beta += DEGTORAD(115.0f);
+ Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f);
+ Source.z += 6.0f;
+ Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found);
+ if(!found){
+ Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found);
+ if(!found)
+ return false;
+ }
+ Source.z = Ground + 0.25f;
+
+ CopCoors.z += 0.35f;
+ Front = CopCoors - Source;
+ if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true))
+ return false;
+ }
+ CopCoors.z += 0.35f;
+ m_cvecTargetCoorsForFudgeInter = CopCoors;
+ Front = CopCoors - Source;
+ ResetStatics = false;
+ GetVectorsReadyForRW();
+ return true;
+}
+
+bool
+CCam::ProcessArrestCamTwo(void)
+{
+ CPed *player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ if(!ResetStatics)
+ return true;
+ ResetStatics = false;
+
+ CVector TargetCoors, ToCamera;
+ float BetaOffset;
+ float SourceX, SourceY;
+ CCam *ActiveCam = &TheCamera.Cams[TheCamera.ActiveCam];
+ if(&ActiveCam[1] == this){
+ SourceX = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.x;
+ SourceY = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.y;
+ }else{
+ SourceX = ActiveCam[1].Source.x;
+ SourceY = ActiveCam[1].Source.y;
+ }
+
+ for(int i = 0; i <= 1; i++){
+ int Dir = i == 0 ? 1 : -1;
+
+ TargetCoors = player->GetPosition();
+ Beta = CGeneral::GetATanOfXY(TargetCoors.x-SourceX, TargetCoors.y-SourceY);
+ BetaOffset = DEGTORAD(Dir*80);
+ Source = TargetCoors + 11.5f*CVector(Cos(Beta+BetaOffset), Sin(Beta+BetaOffset), 0.0f);
+
+ ToCamera = Source - TargetCoors;
+ ToCamera.Normalise();
+ TargetCoors.x += 0.4f*ToCamera.x;
+ TargetCoors.y += 0.4f*ToCamera.y;
+ if(CWorld::GetIsLineOfSightClear(Source, TargetCoors, true, true, false, true, false, true, true)){
+ Source.z += 5.5f;
+ TargetCoors += CVector(-0.8f*ToCamera.x, -0.8f*ToCamera.y, 2.2f);
+ m_cvecTargetCoorsForFudgeInter = TargetCoors;
+ Front = TargetCoors - Source;
+ ResetStatics = false;
+ GetVectorsReadyForRW();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/*
+ * Unused PS2 cams
+ */
+
+void
+CCam::Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ static float AngleToBinned = 0.0f;
+ static float StartingAngleLastChange = 0.0f;
+ static float FixedTargetOrientation = 0.0f;
+ static float DeadZoneReachedOnePrevious;
+
+ FOV = DefaultFOV; // missing in game
+
+ bool FixOrientation = true;
+ if(ResetStatics){
+ Rotating = false;
+ DeadZoneReachedOnePrevious = 0.0f;
+ FixedTargetOrientation = 0.0f;
+ ResetStatics = false;
+ }
+
+ CVector TargetCoors = CameraTarget;
+
+ float StickX = CPad::GetPad(0)->GetRightStickX();
+ float StickY = CPad::GetPad(0)->GetRightStickY();
+ float StickAngle;
+ if(StickX != 0.0 || StickY != 0.0f) // BUG: game checks StickX twice
+ StickAngle = CGeneral::GetATanOfXY(StickX, StickY); // result unused?
+ else
+ FixOrientation = false;
+
+ CVector Dist = Source - TargetCoors;
+ Source.z = TargetCoors.z + 0.75f;
+ float Length = Dist.Magnitude2D();
+ if(Length > 2.5f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
+ }else if(Length < 2.4f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
+ }
+
+ Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
+ if(CPad::GetPad(0)->GetLeftShoulder1()){
+ FixedTargetOrientation = TargetOrientation;
+ Rotating = true;
+ }
+
+ if(FixOrientation){
+ Rotating = true;
+ FixedTargetOrientation = StickX/128.0f + Beta - PI;
+ }
+
+ if(Rotating){
+ Dist = Source - TargetCoors;
+ Length = Dist.Magnitude2D();
+ // inlined
+ WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
+
+ Source.x = TargetCoors.x + Length*Cos(Beta);
+ Source.y = TargetCoors.y + Length*Sin(Beta);
+
+ float DeltaBeta = FixedTargetOrientation+PI - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(Abs(DeltaBeta) < 0.06f)
+ Rotating = false;
+ }
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ CVector Front2 = Front;
+ Front2.Normalise(); // What?
+ // FIX: the meaning of this value must have changed somehow
+ Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
+// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
+
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ static float AngleToBinned = 0.0f;
+ static float StartingAngleLastChange = 0.0f;
+ static float FixedTargetOrientation;
+ static float DeadZoneReachedOnePrevious;
+ static uint32 TimeOfLastChange;
+ uint32 Time;
+ bool DontBind = false; // BUG: left uninitialized
+
+ FOV = DefaultFOV; // missing in game
+
+ if(ResetStatics){
+ Rotating = false;
+ DeadZoneReachedOnePrevious = 0.0f;
+ FixedTargetOrientation = 0.0f;
+ ResetStatics = false;
+ DontBind = false;
+ }
+
+ CVector TargetCoors = CameraTarget;
+
+ CVector Dist = Source - TargetCoors;
+ Source.z = TargetCoors.z + 0.75f;
+ float Length = Dist.Magnitude2D();
+ if(Length > 2.5f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
+ }else if(Length < 2.4f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
+ }
+
+ Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
+
+ float StickX = CPad::GetPad(0)->GetLeftStickX();
+ float StickY = CPad::GetPad(0)->GetLeftStickY();
+ float StickAngle;
+ if(StickX != 0.0 || StickY != 0.0f){
+ StickAngle = CGeneral::GetATanOfXY(StickX, StickY);
+ while(StickAngle >= PI) StickAngle -= 2*PI;
+ while(StickAngle < -PI) StickAngle += 2*PI;
+ }else
+ StickAngle = 1000.0f;
+
+ if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){
+ DontBind = true;
+ Time = CTimer::GetTimeInMilliseconds();
+ }
+
+ if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){
+ if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){
+ FixedTargetOrientation = TargetOrientation;
+ Rotating = true;
+ TimeOfLastChange = CTimer::GetTimeInMilliseconds();
+ }
+ }
+
+ // These two together don't make much sense.
+ // Only prevents rotation for one frame
+ AngleToBinned = StickAngle;
+ if(DontBind)
+ TimeOfLastChange = Time;
+
+ if(Rotating){
+ Dist = Source - TargetCoors;
+ Length = Dist.Magnitude2D();
+ // inlined
+ WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
+
+ Source.x = TargetCoors.x + Length*Cos(Beta);
+ Source.y = TargetCoors.y + Length*Sin(Beta);
+
+ float DeltaBeta = FixedTargetOrientation+PI - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(Abs(DeltaBeta) < 0.06f)
+ Rotating = false;
+ }
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ CVector Front2 = Front;
+ Front2.Normalise(); // What?
+ // FIX: the meaning of this value must have changed somehow
+ Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
+// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
+
+ GetVectorsReadyForRW();
+}
+
+void
+CCam::Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float)
+{
+ static float AngleToBinned = 0.0f;
+ static float StartingAngleLastChange = 0.0f;
+ static float FixedTargetOrientation;
+ static float DeadZoneReachedOnePrevious;
+ static uint32 TimeOfLastChange;
+ uint32 Time;
+ bool DontBind = false;
+
+ FOV = DefaultFOV; // missing in game
+
+ if(ResetStatics){
+ Rotating = false;
+ DeadZoneReachedOnePrevious = 0.0f;
+ FixedTargetOrientation = 0.0f;
+ ResetStatics = false;
+ }
+
+ CVector TargetCoors = CameraTarget;
+
+ CVector Dist = Source - TargetCoors;
+ Source.z = TargetCoors.z + 0.75f;
+ float Length = Dist.Magnitude2D();
+ if(Length > 2.5f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
+ }else if(Length < 2.4f){
+ Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
+ Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
+ }
+
+ Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
+
+ float StickX = CPad::GetPad(0)->GetLeftStickX();
+ float StickY = CPad::GetPad(0)->GetLeftStickY();
+ float StickAngle;
+ if(StickX != 0.0 || StickY != 0.0f){
+ StickAngle = CGeneral::GetATanOfXY(StickX, StickY);
+ while(StickAngle >= PI) StickAngle -= 2*PI;
+ while(StickAngle < -PI) StickAngle += 2*PI;
+ }else
+ StickAngle = 1000.0f;
+
+ if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){
+ DontBind = true;
+ Time = CTimer::GetTimeInMilliseconds();
+ }
+
+ if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){
+ if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){
+ FixedTargetOrientation = TargetOrientation;
+ Rotating = true;
+ TimeOfLastChange = CTimer::GetTimeInMilliseconds();
+ }
+ }
+
+ if(CPad::GetPad(0)->GetLeftShoulder1JustDown()){
+ FixedTargetOrientation = TargetOrientation;
+ Rotating = true;
+ TimeOfLastChange = CTimer::GetTimeInMilliseconds();
+ }
+
+ // These two together don't make much sense.
+ // Only prevents rotation for one frame
+ AngleToBinned = StickAngle;
+ if(DontBind)
+ TimeOfLastChange = Time;
+
+ if(Rotating){
+ Dist = Source - TargetCoors;
+ Length = Dist.Magnitude2D();
+ // inlined
+ WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
+
+ Source.x = TargetCoors.x + Length*Cos(Beta);
+ Source.y = TargetCoors.y + Length*Sin(Beta);
+
+ float DeltaBeta = FixedTargetOrientation+PI - Beta;
+ while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
+ while(DeltaBeta < -PI) DeltaBeta += 2*PI;
+ if(Abs(DeltaBeta) < 0.06f)
+ Rotating = false;
+ }
+
+ Front = TargetCoors - Source;
+ Front.Normalise();
+ CVector Front2 = Front;
+ Front2.Normalise(); // What?
+ // FIX: the meaning of this value must have changed somehow
+ Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
+// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
+
+ GetVectorsReadyForRW();
+}
+
+STARTPATCHES
+ InjectHook(0x456F40, WellBufferMe, PATCH_JUMP);
+ InjectHook(0x458410, &CCam::Init, PATCH_JUMP);
+ InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP);
+ InjectHook(0x457710, &CCam::DoAverageOnVector, PATCH_JUMP);
+ InjectHook(0x458060, &CCam::GetPedBetaAngleForClearView, PATCH_JUMP);
+ InjectHook(0x457210, &CCam::Cam_On_A_String_Unobscured, PATCH_JUMP);
+ InjectHook(0x457A80, &CCam::FixCamWhenObscuredByVehicle, PATCH_JUMP);
+ InjectHook(0x457B90, &CCam::FixCamIfObscured, PATCH_JUMP);
+ InjectHook(0x465DA0, &CCam::RotCamIfInFrontCar, PATCH_JUMP);
+ InjectHook(0x4662D0, &CCam::WorkOutCamHeightWeeCar, PATCH_JUMP);
+ InjectHook(0x466650, &CCam::WorkOutCamHeight, PATCH_JUMP);
+ InjectHook(0x458600, &CCam::LookBehind, PATCH_JUMP);
+ InjectHook(0x458C40, &CCam::LookLeft, PATCH_JUMP);
+ InjectHook(0x458FB0, &CCam::LookRight, PATCH_JUMP);
+ InjectHook(0x4574C0, &CCam::ClipIfPedInFrontOfPlayer, PATCH_JUMP);
+ InjectHook(0x459300, &CCam::KeepTrackOfTheSpeed, PATCH_JUMP);
+ InjectHook(0x458580, &CCam::IsTargetInWater, PATCH_JUMP);
+ InjectHook(0x4570C0, &CCam::AvoidWallsTopDownPed, PATCH_JUMP);
+ InjectHook(0x4595B0, &CCam::PrintMode, PATCH_JUMP);
+
+ InjectHook(0x467400, &CCam::ProcessSpecialHeightRoutines, PATCH_JUMP);
+ InjectHook(0x4596A0, &CCam::Process, PATCH_JUMP);
+ InjectHook(0x45E3A0, &CCam::Process_FollowPed, PATCH_JUMP);
+ InjectHook(0x45FF70, &CCam::Process_FollowPedWithMouse, PATCH_JUMP);
+ InjectHook(0x45BE60, &CCam::Process_BehindCar, PATCH_JUMP);
+ InjectHook(0x45C090, &CCam::Process_Cam_On_A_String, PATCH_JUMP);
+ InjectHook(0x463EB0, &CCam::Process_TopDown, PATCH_JUMP);
+ InjectHook(0x464390, &CCam::Process_TopDownPed, PATCH_JUMP);
+ InjectHook(0x461AF0, &CCam::Process_Rocket, PATCH_JUMP);
+ InjectHook(0x460E00, &CCam::Process_M16_1stPerson, PATCH_JUMP);
+ InjectHook(0x459FA0, &CCam::Process_1stPerson, PATCH_JUMP);
+ InjectHook(0x462420, &CCam::Process_Sniper, PATCH_JUMP);
+ InjectHook(0x463130, &CCam::Process_Syphon, PATCH_JUMP);
+ InjectHook(0x463A70, &CCam::Process_Syphon_Crim_In_Front, PATCH_JUMP);
+ InjectHook(0x45B470, &CCam::Process_BehindBoat, PATCH_JUMP);
+ InjectHook(0x45D2F0, &CCam::Process_Fight_Cam, PATCH_JUMP);
+ InjectHook(0x45DC20, &CCam::Process_FlyBy, PATCH_JUMP);
+ InjectHook(0x464D10, &CCam::Process_WheelCam, PATCH_JUMP);
+ InjectHook(0x45DA20, &CCam::Process_Fixed, PATCH_JUMP);
+ InjectHook(0x461940, &CCam::Process_Player_Fallen_Water, PATCH_JUMP);
+ InjectHook(0x45C400, &CCam::Process_Circle, PATCH_JUMP);
+ InjectHook(0x462FC0, &CCam::Process_SpecialFixedForSyphon, PATCH_JUMP);
+ InjectHook(0x45CCC0, &CCam::Process_Debug, PATCH_JUMP);
+ InjectHook(0x4656C0, &CCam::ProcessPedsDeadBaby, PATCH_JUMP);
+ InjectHook(0x465000, &CCam::ProcessArrestCamOne, PATCH_JUMP);
+ InjectHook(0x4653C0, &CCam::ProcessArrestCamTwo, PATCH_JUMP);
+
+ InjectHook(0x456CE0, &FindSplinePathPositionFloat, PATCH_JUMP);
+ InjectHook(0x4569A0, &FindSplinePathPositionVector, PATCH_JUMP);
+
+ InjectHook(0x473250, &CCamera::dtor, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 75e52c5f..3f7ed286 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -13,8 +13,6 @@
#include "MBlur.h"
#include "Camera.h"
-const float DefaultFOV = 70.0f; // beta: 80.0f
-
CCamera &TheCamera = *(CCamera*)0x6FACF8;
bool &CCamera::m_bUseMouse3rdPerson = *(bool *)0x5F03D8;
@@ -38,6 +36,15 @@ CCamera::GetFading()
return m_bFading;
}
+int
+CCamera::GetFadingDirection()
+{
+ if(m_bFading)
+ return m_iFadingDirection == FADE_IN ? FADE_IN : FADE_OUT;
+ else
+ return FADE_NONE;
+}
+
bool
CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
{
@@ -182,1148 +189,6 @@ CCamera::ClearPlayerWeaponMode()
PlayerWeaponMode.Duration = 0.0f;
}
-
-/*
- *
- * CCam
- *
- */
-
-
-// MaxSpeed is a limit of how fast the value is allowed to change. 1.0 = to Target in up to 1ms
-// Acceleration is how fast the speed will change to MaxSpeed. 1.0 = to MaxSpeed in 1ms
-void
-WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle)
-{
- float Delta = Target - *CurrentValue;
-
- if(IsAngle){
- while(Delta >= PI) Delta -= 2*PI;
- while(Delta < -PI) Delta += 2*PI;
- }
-
- float TargetSpeed = Delta * MaxSpeed;
- // Add or subtract absolute depending on sign, genius!
-// if(TargetSpeed - *CurrentSpeed > 0.0f)
-// *CurrentSpeed += Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
-// else
-// *CurrentSpeed -= Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
- // this is simpler:
- *CurrentSpeed += Acceleration * (TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
-
- // Clamp speed if we overshot
- if(TargetSpeed < 0.0f && *CurrentSpeed < TargetSpeed)
- *CurrentSpeed = TargetSpeed;
- else if(TargetSpeed > 0.0f && *CurrentSpeed > TargetSpeed)
- *CurrentSpeed = TargetSpeed;
-
- *CurrentValue += *CurrentSpeed * min(10.0f, CTimer::GetTimeStep());
-}
-
-void
-CCam::GetVectorsReadyForRW(void)
-{
- CVector right;
- Up = CVector(0.0f, 0.0f, 1.0f);
- Front.Normalise();
- if(Front.x == 0.0f && Front.y == 0.0f){
- Front.x = 0.0001f;
- Front.y = 0.0001f;
- }
- right = CrossProduct(Front, Up);
- right.Normalise();
- Up = CrossProduct(right, Front);
-}
-
-// This code is really bad. wtf R*?
-CVector
-CCam::DoAverageOnVector(const CVector &vec)
-{
- int i;
- CVector Average = { 0.0f, 0.0f, 0.0f };
-
- if(ResetStatics){
- m_iRunningVectorArrayPos = 0;
- m_iRunningVectorCounter = 1;
- }
-
- // TODO: make this work with NUMBER_OF_VECTORS_FOR_AVERAGE != 2
- if(m_iRunningVectorCounter == 3){
- m_arrPreviousVectors[0] = m_arrPreviousVectors[1];
- m_arrPreviousVectors[1] = vec;
- }else
- m_arrPreviousVectors[m_iRunningVectorArrayPos] = vec;
-
- for(i = 0; i <= m_iRunningVectorArrayPos; i++)
- Average += m_arrPreviousVectors[i];
- Average /= i;
-
- m_iRunningVectorArrayPos++;
- m_iRunningVectorCounter++;
- if(m_iRunningVectorArrayPos >= NUMBER_OF_VECTORS_FOR_AVERAGE)
- m_iRunningVectorArrayPos = NUMBER_OF_VECTORS_FOR_AVERAGE-1;
- if(m_iRunningVectorCounter > NUMBER_OF_VECTORS_FOR_AVERAGE+1)
- m_iRunningVectorCounter = NUMBER_OF_VECTORS_FOR_AVERAGE+1;
-
- return Average;
-}
-
-// Rotate Beta in direction opposite of BetaOffset in 5 deg. steps.
-// Return the first angle for which Beta + BetaOffset + Angle has a clear view.
-// i.e. BetaOffset is a safe zone so that Beta + Angle is really clear.
-// If BetaOffset == 0, try both directions.
-float
-CCam::GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
-{
- CColPoint point;
- CEntity *ent = nil;
- CVector ToSource;
- float a;
-
- // This would be so much nicer if we just got the step variable before the loop...R*
-
- for(a = 0.0f; a <= PI; a += DEGTORAD(5.0f)){
- if(BetaOffset <= 0.0f){
- ToSource = CVector(Cos(Beta + BetaOffset + a), Sin(Beta + BetaOffset + a), 0.0f)*Dist;
- if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
- point, ent, checkBuildings, checkVehicles, checkPeds,
- checkObjects, checkDummies, true, true))
- return a;
- }
- if(BetaOffset >= 0.0f){
- ToSource = CVector(Cos(Beta + BetaOffset - a), Sin(Beta + BetaOffset - a), 0.0f)*Dist;
- if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
- point, ent, checkBuildings, checkVehicles, checkPeds,
- checkObjects, checkDummies, true, true))
- return -a;
- }
- }
- return 0.0f;
-}
-
-static float DefaultAcceleration = 0.045f;
-static float DefaultMaxStep = 0.15f;
-
-void
-CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float)
-{
- const float GroundDist = 1.85f;
-
- CVector TargetCoors, Dist, IdealSource;
- float Length = 0.0f;
- float LateralLeft = 0.0f;
- float LateralRight = 0.0f;
- float Center = 0.0f;
- static bool PreviouslyObscured;
- static bool PickedASide;
- static float FixedTargetOrientation = 0.0f;
- float AngleToGoTo = 0.0f;
- float BetaOffsetAvoidBuildings = 0.45f; // ~25 deg
- float BetaOffsetGoingBehind = 0.45f;
- bool GoingBehind = false;
- bool Obscured = false;
- bool BuildingCheckObscured = false;
- bool HackPlayerOnStoppingTrain = false;
- static int TimeIndicatedWantedToGoDown = 0;
- static bool StartedCountingForGoDown = false;
- float DeltaBeta;
-
- m_bFixingBeta = false;
- bBelowMinDist = false;
- bBehindPlayerDesired = false;
-
- assert(CamTargetEntity->IsPed());
-
- // CenterDist should be > LateralDist because we don't have an angle for safety in this case
- float CenterDist, LateralDist;
- float AngleToGoToSpeed;
- if(m_fCloseInPedHeightOffsetSpeed > 0.00001f){
- LateralDist = 0.55f;
- CenterDist = 1.25f;
- BetaOffsetAvoidBuildings = 0.9f; // ~50 deg
- BetaOffsetGoingBehind = 0.9f;
- AngleToGoToSpeed = 0.88254666f;
- }else{
- LateralDist = 0.8f;
- CenterDist = 1.35f;
- if(TheCamera.PedZoomIndicator == 1.0f || TheCamera.PedZoomIndicator == 4.0f){
- LateralDist = 1.25f;
- CenterDist = 1.6f;
- }
- AngleToGoToSpeed = 0.43254671f;
- }
-
- FOV = DefaultFOV;
-
- if(ResetStatics){
- Rotating = false;
- m_bCollisionChecksOn = true;
- FixedTargetOrientation = 0.0f;
- PreviouslyObscured = false;
- PickedASide = false;
- StartedCountingForGoDown = false;
- AngleToGoTo = 0.0f;
- // unused LastAngleWithNoPickedASide
- }
-
-
- TargetCoors = CameraTarget;
- IdealSource = Source;
- TargetCoors.z += m_fSyphonModeTargetZOffSet;
-
- CVector TempTargetCoors;
- TempTargetCoors = DoAverageOnVector(TargetCoors);
- TargetCoors = TempTargetCoors;
- // Add this unknown offset, but later it's removed again
- TargetCoors.z += m_fUnknownZOffSet;
-
- Dist.x = IdealSource.x - TargetCoors.x;
- Dist.y = IdealSource.y - TargetCoors.y;
- Length = Dist.Magnitude2D();
-
- // Cam on a string. With a fixed distance. Zoom in/out is done later.
- if(Length != 0.0f)
- IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * GroundDist;
- else
- IdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
-
- // TODO: what's transition beta?
- if(TheCamera.m_bUseTransitionBeta && ResetStatics){
- CVector VecDistance;
- IdealSource.x = TargetCoors.x + GroundDist*Cos(m_fTransitionBeta);
- IdealSource.y = TargetCoors.y + GroundDist*Sin(m_fTransitionBeta);
- Beta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y);
- }else
- Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
-
- if(TheCamera.m_bCamDirectlyBehind){
- m_bCollisionChecksOn = true;
- Beta = TargetOrientation + PI;
- }
-
- if(FindPlayerVehicle())
- if(FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)
- HackPlayerOnStoppingTrain = true;
-
- if(TheCamera.m_bCamDirectlyInFront){
- m_bCollisionChecksOn = true;
- Beta = TargetOrientation;
- }
-
- while(Beta >= PI) Beta -= 2.0f * PI;
- while(Beta < -PI) Beta += 2.0f * PI;
-
- // BUG? is this ever used?
- // The values seem to be roughly m_fPedZoomValueSmooth + 1.85
- if(ResetStatics){
- if(TheCamera.PedZoomIndicator == 1.0f) m_fRealGroundDist = 2.090556f;
- if(TheCamera.PedZoomIndicator == 2.0f) m_fRealGroundDist = 3.34973f;
- if(TheCamera.PedZoomIndicator == 3.0f) m_fRealGroundDist = 4.704914f;
- if(TheCamera.PedZoomIndicator == 4.0f) m_fRealGroundDist = 2.090556f;
- }
- // And what is this? It's only used for collision and rotation it seems
- float RealGroundDist;
- if(TheCamera.PedZoomIndicator == 1.0f) RealGroundDist = 2.090556f;
- if(TheCamera.PedZoomIndicator == 2.0f) RealGroundDist = 3.34973f;
- if(TheCamera.PedZoomIndicator == 3.0f) RealGroundDist = 4.704914f;
- if(TheCamera.PedZoomIndicator == 4.0f) RealGroundDist = 2.090556f;
- if(m_fCloseInPedHeightOffset > 0.00001f)
- RealGroundDist = 1.7016f;
-
-
- bool Shooting = false;
- CPed *ped = (CPed*)CamTargetEntity;
- if(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
- if(CPad::GetPad(0)->GetWeapon())
- Shooting = true;
- if(ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||
- ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)
- Shooting = false;
-
-
- if(m_fCloseInPedHeightOffset > 0.00001f)
- TargetCoors.z -= m_fUnknownZOffSet;
-
- // Figure out if and where we want to rotate
-
- if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
-
- // Center cam behind player
-
- GoingBehind = true;
- m_bCollisionChecksOn = true;
- float OriginalBeta = Beta;
- // Set Beta behind player
- Beta = TargetOrientation + PI;
- TargetCoors.z -= 0.1f;
-
- AngleToGoTo = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
- if(AngleToGoTo != 0.0f){
- if(AngleToGoTo < 0.0f)
- AngleToGoTo -= AngleToGoToSpeed;
- else
- AngleToGoTo += AngleToGoToSpeed;
- }else{
- float LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetGoingBehind, true, false, false, true, false);
- float LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetGoingBehind, true, false, false, true, false);
- if(LateralLeft == 0.0f && LateralRight != 0.0f)
- AngleToGoTo += LateralRight;
- else if(LateralLeft != 0.0f && LateralRight == 0.0f)
- AngleToGoTo += LateralLeft;
- }
-
- TargetCoors.z += 0.1f;
- Beta = OriginalBeta;
-
- if(PickedASide){
- if(AngleToGoTo == 0.0f)
- FixedTargetOrientation = TargetOrientation + PI;
- Rotating = true;
- }else{
- FixedTargetOrientation = TargetOrientation + PI + AngleToGoTo;
- Rotating = true;
- PickedASide = true;
- }
- }else{
-
- // Rotate cam to avoid clipping into buildings
-
- TargetCoors.z -= 0.1f;
-
- Center = GetPedBetaAngleForClearView(TargetCoors, CenterDist * RealGroundDist, 0.0f, true, false, false, true, false);
- if(m_bCollisionChecksOn || PreviouslyObscured || Center != 0.0f || m_fCloseInPedHeightOffset > 0.00001f){
- if(Center != 0.0f){
- AngleToGoTo = Center;
- }else{
- LateralLeft = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, BetaOffsetAvoidBuildings, true, false, false, true, false);
- LateralRight = GetPedBetaAngleForClearView(TargetCoors, LateralDist * RealGroundDist, -BetaOffsetAvoidBuildings, true, false, false, true, false);
- if(LateralLeft == 0.0f && LateralRight != 0.0f){
- AngleToGoTo += LateralRight;
- if(m_fCloseInPedHeightOffset > 0.0f)
- RwCameraSetNearClipPlane(Scene.camera, 0.7f);
- }else if(LateralLeft != 0.0f && LateralRight == 0.0f){
- AngleToGoTo += LateralLeft;
- if(m_fCloseInPedHeightOffset > 0.0f)
- RwCameraSetNearClipPlane(Scene.camera, 0.7f);
- }
- }
- if(LateralLeft != 0.0f || LateralRight != 0.0f || Center != 0.0f)
- BuildingCheckObscured = true;
- }
-
- TargetCoors.z += 0.1f;
- }
-
- if(m_fCloseInPedHeightOffset > 0.00001f)
- TargetCoors.z += m_fUnknownZOffSet;
-
-
- // Have to fix to avoid collision
-
- if(AngleToGoTo != 0.0f){
- Obscured = true;
- Rotating = true;
- if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
- if(!PickedASide)
- FixedTargetOrientation = Beta + AngleToGoTo; // can this even happen?
- }else
- FixedTargetOrientation = Beta + AngleToGoTo;
-
- // This calculation is only really used to figure out how fast to rotate out of collision
-
- m_fAmountFractionObscured = 1.0f;
- CVector PlayerPos = FindPlayerPed()->GetPosition();
- float RotationDist = (AngleToGoTo == Center ? CenterDist : LateralDist) * RealGroundDist;
- // What's going on here? - AngleToGoTo?
- CVector RotatedSource = PlayerPos + CVector(Cos(Beta - AngleToGoTo), Sin(Beta - AngleToGoTo), 0.0f) * RotationDist;
-
- CColPoint colpoint;
- CEntity *entity;
- if(CWorld::ProcessLineOfSight(PlayerPos, RotatedSource, colpoint, entity, true, false, false, true, false, false, false)){
- if((PlayerPos - RotatedSource).Magnitude() != 0.0f)
- m_fAmountFractionObscured = (PlayerPos - colpoint.point).Magnitude() / (PlayerPos - RotatedSource).Magnitude();
- else
- m_fAmountFractionObscured = 1.0f;
- }
- }
- if(m_fAmountFractionObscured < 0.0f) m_fAmountFractionObscured = 0.0f;
- if(m_fAmountFractionObscured > 1.0f) m_fAmountFractionObscured = 1.0f;
-
-
-
- // Figure out speed values for Beta rotation
-
- float Acceleration, MaxSpeed;
- static float AccelerationMult = 0.35f;
- static float MaxSpeedMult = 0.85f;
- static float AccelerationMultClose = 0.7f;
- static float MaxSpeedMultClose = 1.6f;
- float BaseAcceleration = 0.025f;
- float BaseMaxSpeed = 0.09f;
- if(m_fCloseInPedHeightOffset > 0.00001f){
- if(AngleToGoTo == 0.0f){
- BaseAcceleration = 0.022f;
- BaseMaxSpeed = 0.04f;
- }else{
- BaseAcceleration = DefaultAcceleration;
- BaseMaxSpeed = DefaultMaxStep;
- }
- }
- if(AngleToGoTo == 0.0f){
- Acceleration = BaseAcceleration;
- MaxSpeed = BaseMaxSpeed;
- }else if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !Shooting){
- Acceleration = 0.051f;
- MaxSpeed = 0.18f;
- }else if(m_fCloseInPedHeightOffset > 0.00001f){
- Acceleration = BaseAcceleration + AccelerationMultClose*sq(m_fAmountFractionObscured - 1.05f);
- MaxSpeed = BaseMaxSpeed + MaxSpeedMultClose*sq(m_fAmountFractionObscured - 1.05f);
- }else{
- Acceleration = DefaultAcceleration + AccelerationMult*sq(m_fAmountFractionObscured - 1.05f);
- MaxSpeed = DefaultMaxStep + MaxSpeedMult*sq(m_fAmountFractionObscured - 1.05f);
- }
- static float AccelerationLimit = 0.3f;
- static float MaxSpeedLimit = 0.65f;
- if(Acceleration > AccelerationLimit) Acceleration = AccelerationLimit;
- if(MaxSpeed > MaxSpeedLimit) MaxSpeed = MaxSpeedLimit;
-
-
- int MoveState = ((CPed*)CamTargetEntity)->m_nMoveState;
- if(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL &&
- !CPad::GetPad(0)->ForceCameraBehindPlayer() && !Obscured && !Shooting){
- Rotating = false;
- BetaSpeed = 0.0f;
- }
-
- // Now do the Beta rotation
-
- float Distance = (IdealSource - TargetCoors).Magnitude2D();
- m_fDistanceBeforeChanges = Distance;
-
- if(Rotating){
- m_bFixingBeta = true;
-
- while(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI;
- while(FixedTargetOrientation < -PI) FixedTargetOrientation += 2*PI;
-
- while(Beta >= PI) Beta -= 2*PI;
- while(Beta < -PI) Beta += 2*PI;
-
-
-/*
- // This is inlined WellBufferMe
- DeltaBeta = FixedTargetOrientation - Beta;
- while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
- while(DeltaBeta < -PI) DeltaBeta += 2*PI;
-
- float ReqSpeed = DeltaBeta * MaxSpeed;
- // Add or subtract absolute depending on sign, genius!
- if(ReqSpeed - BetaSpeed > 0.0f)
- BetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
- else
- BetaSpeed -= SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
- // this would be simpler:
- // BetaSpeed += SpeedStep * (ReqSpeed - BetaSpeed) * CTimer::ms_fTimeStep;
-
- if(ReqSpeed < 0.0f && BetaSpeed < ReqSpeed)
- BetaSpeed = ReqSpeed;
- else if(ReqSpeed > 0.0f && BetaSpeed > ReqSpeed)
- BetaSpeed = ReqSpeed;
-
- Beta += BetaSpeed * min(10.0f, CTimer::GetTimeStep());
-*/
- WellBufferMe(FixedTargetOrientation, &Beta, &BetaSpeed, MaxSpeed, Acceleration, true);
-
- if(ResetStatics){
- Beta = FixedTargetOrientation;
- BetaSpeed = 0.0f;
- }
-
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
-
- // Check if we can stop rotating
- DeltaBeta = FixedTargetOrientation - Beta;
- while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
- while(DeltaBeta < -PI) DeltaBeta += 2*PI;
- if(Abs(DeltaBeta) < DEGTORAD(1.0f) && !bBehindPlayerDesired){
- // Stop rotation
- PickedASide = false;
- Rotating = false;
- BetaSpeed = 0.0f;
- }
- }
-
-
- if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront ||
- HackPlayerOnStoppingTrain || Rotating){
- if(TheCamera.m_bCamDirectlyBehind){
- Beta = TargetOrientation + PI;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
- }
- if(TheCamera.m_bCamDirectlyInFront){
- Beta = TargetOrientation;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
- }
- if(HackPlayerOnStoppingTrain){
- Beta = TargetOrientation + PI;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
- m_fDimensionOfHighestNearCar = 0.0f;
- m_fCamBufferedHeight = 0.0f;
- m_fCamBufferedHeightSpeed = 0.0f;
- }
- // Beta and Source already set in the rotation code
- }else{
- Source = IdealSource;
- BetaSpeed = 0.0f;
- }
-
- // Subtract m_fUnknownZOffSet from both?
- TargetCoors.z -= m_fUnknownZOffSet;
- Source.z = IdealSource.z - m_fUnknownZOffSet;
-
- // Apply zoom now
- // m_fPedZoomValueSmooth makes the cam go down the further out it is
- // 0.25 -> 0.20 for nearest dist
- // 1.50 -> -0.05 for mid dist
- // 2.90 -> -0.33 for far dist
- Source.z += (2.5f - TheCamera.m_fPedZoomValueSmooth)*0.2f - 0.25f;
- // Zoom out camera
- Front = TargetCoors - Source;
- Front.Normalise();
- Source -= Front * TheCamera.m_fPedZoomValueSmooth;
- // and then we move up again
- // -0.375
- // 0.25
- // 0.95
- Source.z += (TheCamera.m_fPedZoomValueSmooth - 1.0f)*0.5f + m_fCloseInPedHeightOffset;
-
-
- // Process height offset to avoid peds and cars
-
- float TargetZOffSet = m_fUnknownZOffSet + m_fDimensionOfHighestNearCar;
- TargetZOffSet = max(TargetZOffSet, m_fPedBetweenCameraHeightOffset);
- float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z;
-
- if(TargetHeight > m_fCamBufferedHeight){
- // Have to go up
- if(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight)
- WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false);
- else if(TargetZOffSet == m_fUnknownZOffSet && TargetZOffSet > m_fCamBufferedHeight){
- // TODO: figure this out
- bool foo = false;
- switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched)
- case SURFACE_GRASS:
- case SURFACE_DIRT:
- case SURFACE_PAVEMENT:
- case SURFACE_STEEL:
- case SURFACE_TIRE:
- case SURFACE_STONE:
- foo = true;
- if(foo)
- WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.4f, 0.05f, false);
- else
- WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
- }else
- WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
- StartedCountingForGoDown = false;
- }else{
- // Have to go down
- if(StartedCountingForGoDown){
- if(CTimer::GetTimeInMilliseconds() != TimeIndicatedWantedToGoDown){
- if(TargetHeight > 0.0f)
- WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
- else
- WellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
- }
- }else{
- StartedCountingForGoDown = true;
- TimeIndicatedWantedToGoDown = CTimer::GetTimeInMilliseconds();
- }
- }
-
- Source.z += m_fCamBufferedHeight;
-
-
- // Clip Source if necessary
-
- bool ClipSource = m_fCloseInPedHeightOffset > 0.00001f && m_fCamBufferedHeight > 0.001f;
- if(GoingBehind || ResetStatics || ClipSource){
- CColPoint colpoint;
- CEntity *entity;
- if(CWorld::ProcessLineOfSight(TargetCoors, Source, colpoint, entity, true, false, false, true, false, true, true)){
- Source = colpoint.point;
- if((TargetCoors - Source).Magnitude2D() < 1.0f)
- RwCameraSetNearClipPlane(Scene.camera, 0.05f);
- }
- }
-
- TargetCoors.z += min(1.0f, m_fCamBufferedHeight/2.0f);
- m_cvecTargetCoorsForFudgeInter = TargetCoors;
-
- Front = TargetCoors - Source;
- m_fRealGroundDist = Front.Magnitude2D();
- m_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist;
- Front.Normalise();
- GetVectorsReadyForRW();
- TheCamera.m_bCamDirectlyBehind = false;
- TheCamera.m_bCamDirectlyInFront = false;
- PreviouslyObscured = BuildingCheckObscured;
-
- ResetStatics = false;
-}
-
-void
-CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float)
-{
- FOV = DefaultFOV;
-
- if(!CamTargetEntity->IsVehicle())
- return;
-
- CVector TargetCoors = CameraTarget;
- TargetCoors.z -= 0.2f;
- CA_MAX_DISTANCE = 9.95f;
- CA_MIN_DISTANCE = 8.5f;
-
- CVector Dist = Source - TargetCoors;
- float Length = Dist.Magnitude2D();
- m_fDistanceBeforeChanges = Length;
- if(Length < 0.002f)
- Length = 0.002f;
- Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
- if(Length > CA_MAX_DISTANCE){
- Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
- Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
- }else if(Length < CA_MIN_DISTANCE){
- Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
- Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
- }
- TargetCoors.z += 0.8f;
-
- WorkOutCamHeightWeeCar(TargetCoors, TargetOrientation);
- RotCamIfInFrontCar(TargetCoors, TargetOrientation);
- FixCamIfObscured(TargetCoors, 1.2f, TargetOrientation);
-
- Front = TargetCoors - Source;
- m_cvecTargetCoorsForFudgeInter = TargetCoors;
- ResetStatics = false;
- GetVectorsReadyForRW();
-}
-
-void
-CCam::WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation)
-{
- CColPoint colpoint;
- CEntity *ent;
- float TargetZOffSet = 0.0f;
- static bool PreviouslyFailedRoadHeightCheck = false;
- static float RoadHeightFix = 0.0f;
- static float RoadHeightFixSpeed = 0.0f;
-
- if(ResetStatics){
- RoadHeightFix = 0.0f;
- RoadHeightFixSpeed = 0.0f;
- Alpha = DEGTORAD(25.0f);
- AlphaSpeed = 0.0f;
- }
- float AlphaTarget = DEGTORAD(25.0f);
- if(CCullZones::CamNoRain() || CCullZones::PlayerNoRain())
- AlphaTarget = DEGTORAD(14.0f);
- WellBufferMe(AlphaTarget, &Alpha, &AlphaSpeed, 0.1f, 0.05f, true);
- Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);
-
- if(FindPlayerVehicle()){
- m_fUnknownZOffSet = 0.0f;
- bool FoundRoad = false;
- bool FoundRoof = false;
- float RoadZ = 0.0f;
- float RoofZ = 0.0f;
-
- if(CWorld::ProcessVerticalLine(Source, -1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
- ent->IsBuilding()){
- FoundRoad = true;
- RoadZ = colpoint.point.z;
- }
-
- if(FoundRoad){
- if(Source.z - RoadZ < 0.9f){
- PreviouslyFailedRoadHeightCheck = true;
- TargetZOffSet = RoadZ + 0.9f - Source.z;
- }else{
- if(m_bCollisionChecksOn)
- PreviouslyFailedRoadHeightCheck = false;
- else
- TargetZOffSet = 0.0f;
- }
- }else{
- if(CWorld::ProcessVerticalLine(Source, 1000.0f, colpoint, ent, true, false, false, false, false, false, nil) &&
- ent->IsBuilding()){
- FoundRoof = true;
- RoofZ = colpoint.point.z;
- }
- if(FoundRoof){
- if(Source.z - RoofZ < 0.9f){
- PreviouslyFailedRoadHeightCheck = true;
- TargetZOffSet = RoofZ + 0.9f - Source.z;
- }else{
- if(m_bCollisionChecksOn)
- PreviouslyFailedRoadHeightCheck = false;
- else
- TargetZOffSet = 0.0f;
- }
- }
- }
- }
-
- if(TargetZOffSet > RoadHeightFix)
- RoadHeightFix = TargetZOffSet;
- else
- WellBufferMe(TargetZOffSet, &RoadHeightFix, &RoadHeightFixSpeed, 0.27f, 0.1f, false);
-
- if((colpoint.surfaceB == SURFACE_DEFAULT || colpoint.surfaceB >= SURFACE_METAL6) &&
- colpoint.surfaceB != SURFACE_STEEL && colpoint.surfaceB != SURFACE_STONE &&
- RoadHeightFix > 1.4f)
- RoadHeightFix = 1.4f;
-
- Source.z += RoadHeightFix;
-}
-
-void
-CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight)
-{
- static float LastTargetAlphaWithCollisionOn = 0.0f;
- static float LastTopAlphaSpeed = 0.0f;
- static float LastAlphaSpeedStep = 0.0f;
- static bool PreviousNearCheckNearClipSmall = false;
-
- bool CamClear = true;
- float ModeAlpha = 0.0f;
-
- if(ResetStatics){
- LastTargetAlphaWithCollisionOn = 0.0f;
- LastTopAlphaSpeed = 0.0f;
- LastAlphaSpeedStep = 0.0f;
- PreviousNearCheckNearClipSmall = false;
- }
-
- float TopAlphaSpeed = 0.15f;
- float AlphaSpeedStep = 0.015f;
-
- float zoomvalue = TheCamera.CarZoomValueSmooth;
- if(zoomvalue < 0.1f)
- zoomvalue = 0.1f;
- if(TheCamera.CarZoomIndicator == 1.0f)
- ModeAlpha = CGeneral::GetATanOfXY(23.0f, zoomvalue); // near
- else if(TheCamera.CarZoomIndicator == 2.0f)
- ModeAlpha = CGeneral::GetATanOfXY(10.8f, zoomvalue); // mid
- else if(TheCamera.CarZoomIndicator == 3.0f)
- ModeAlpha = CGeneral::GetATanOfXY(7.0f, zoomvalue); // far
-
-
- float Length = (Source - TargetCoors).Magnitude2D();
- if(m_bCollisionChecksOn){ // there's another variable (on PC) but it's uninitialised
- CVector Forward = CamTargetEntity->GetForward();
- float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);
- // this shouldn't be necessary....
- while(CarAlpha >= PI) CarAlpha -= 2*PI;
- while(CarAlpha < -PI) CarAlpha += 2*PI;
-
- while(Beta >= PI) Beta -= 2*PI;
- while(Beta < -PI) Beta += 2*PI;
-
- float deltaBeta = Beta - TargetOrientation;
- while(deltaBeta >= PI) deltaBeta -= 2*PI;
- while(deltaBeta < -PI) deltaBeta += 2*PI;
-
- float BehindCarNess = Cos(deltaBeta); // 1 if behind car, 0 if side, -1 if in front
- CarAlpha = -CarAlpha * BehindCarNess;
- if(CarAlpha < -0.01f)
- CarAlpha = -0.01f;
-
- float DeltaAlpha = CarAlpha - Alpha;
- while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
- while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
- // What's this?? wouldn't it make more sense to clamp?
- float AngleLimit = DEGTORAD(1.8f);
- if(DeltaAlpha < -AngleLimit)
- DeltaAlpha += AngleLimit;
- else if(DeltaAlpha > AngleLimit)
- DeltaAlpha -= AngleLimit;
- else
- DeltaAlpha = 0.0f;
-
- // Now the collision
-
- float TargetAlpha = 0.0f;
- bool FoundRoofCenter = false;
- bool FoundRoofSide1 = false;
- bool FoundRoofSide2 = false;
- bool FoundCamRoof = false;
- bool FoundCamGround = false;
- float CamRoof = 0.0f;
- float CarBottom = TargetCoors.z - TargetHeight/2.0f;
-
- // Check car center
- float CarRoof = CWorld::FindRoofZFor3DCoord(TargetCoors.x, TargetCoors.y, CarBottom, &FoundRoofCenter);
-
- // Check sides of the car
- Forward = CamTargetEntity->GetForward(); // we actually still have that...
- Forward.Normalise(); // shouldn't be necessary
- float CarSideAngle = CGeneral::GetATanOfXY(Forward.x, Forward.y) + PI/2.0f;
- float SideX = 2.5f * Cos(CarSideAngle);
- float SideY = 2.5f * Sin(CarSideAngle);
- CWorld::FindRoofZFor3DCoord(TargetCoors.x + SideX, TargetCoors.y + SideY, CarBottom, &FoundRoofSide1);
- CWorld::FindRoofZFor3DCoord(TargetCoors.x - SideX, TargetCoors.y - SideY, CarBottom, &FoundRoofSide2);
-
- // Now find out at what height we'd like to place the camera
- float CamGround = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, TargetCoors.z + Length*Sin(Alpha + ModeAlpha) + m_fCloseInCarHeightOffset, &FoundCamGround);
- float CamTargetZ = 0.0f;
- if(FoundCamGround){
- // This is the normal case
- CamRoof = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamGround + TargetHeight, &FoundCamRoof);
- CamTargetZ = CamGround + TargetHeight*1.5f + 0.1f;
- }else{
- FoundCamRoof = false;
- CamTargetZ = TargetCoors.z;
- }
-
- if(FoundRoofCenter && !FoundCamRoof && (FoundRoofSide1 || FoundRoofSide2)){
- // Car is under something but camera isn't
- // This seems weird...
- TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, CarRoof - CamTargetZ - 1.5f);
- CamClear = false;
- }
- if(FoundCamRoof){
- // Camera is under something
- float roof = FoundRoofCenter ? min(CamRoof, CarRoof) : CamRoof;
- // Same weirdness again?
- TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, roof - CamTargetZ - 1.5f);
- CamClear = false;
- }
- while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
- while(TargetAlpha < -PI) TargetAlpha += 2*PI;
- if(TargetAlpha < DEGTORAD(-7.0f))
- TargetAlpha = DEGTORAD(-7.0f);
-
- // huh?
- if(TargetAlpha > ModeAlpha)
- CamClear = true;
- // Camera is contrained by collision in some way
- PreviousNearCheckNearClipSmall = false;
- if(!CamClear){
- PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
-
- DeltaAlpha = TargetAlpha - (Alpha + ModeAlpha);
- while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
- while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
-
- TopAlphaSpeed = 0.3f;
- AlphaSpeedStep = 0.03f;
- }
-
- // Now do things if CamClear...but what is that anyway?
- float CamZ = TargetCoors.z + Length*Sin(Alpha + DeltaAlpha + ModeAlpha) + m_fCloseInCarHeightOffset;
- bool FoundGround, FoundRoof;
- float CamGround2 = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, CamZ, &FoundGround);
- if(FoundGround){
- if(CamClear)
- if(CamZ - CamGround2 < 1.5f){
- PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
-
- float a;
- if(Length == 0.0f || CamGround2 + 1.5f - TargetCoors.z == 0.0f)
- a = Alpha;
- else
- a = CGeneral::GetATanOfXY(Length, CamGround2 + 1.5f - TargetCoors.z);
- while(a > PI) a -= 2*PI;
- while(a < -PI) a += 2*PI;
- DeltaAlpha = a - Alpha;
- }
- }else{
- if(CamClear){
- float CamRoof2 = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamZ, &FoundRoof);
- if(FoundRoof && CamZ - CamRoof2 < 1.5f){
- PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
-
- if(CamRoof2 > TargetCoors.z + 3.5f)
- CamRoof2 = TargetCoors.z + 3.5f;
-
- float a;
- if(Length == 0.0f || CamRoof2 + 1.5f - TargetCoors.z == 0.0f)
- a = Alpha;
- else
- a = CGeneral::GetATanOfXY(Length, CamRoof2 + 1.5f - TargetCoors.z);
- while(a > PI) a -= 2*PI;
- while(a < -PI) a += 2*PI;
- DeltaAlpha = a - Alpha;
- }
- }
- }
-
- LastTargetAlphaWithCollisionOn = DeltaAlpha + Alpha;
- LastTopAlphaSpeed = TopAlphaSpeed;
- LastAlphaSpeedStep = AlphaSpeedStep;
- }else{
- if(PreviousNearCheckNearClipSmall)
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
- }
-
- WellBufferMe(LastTargetAlphaWithCollisionOn, &Alpha, &AlphaSpeed, LastTopAlphaSpeed, LastAlphaSpeedStep, true);
-
- Source.z = TargetCoors.z + Sin(Alpha + ModeAlpha)*Length + m_fCloseInCarHeightOffset;
-}
-
-// Rotate cam behind the car when the car is moving forward
-bool
-CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
-{
- bool MovingForward = false;
- CPhysical *phys = (CPhysical*)CamTargetEntity;
-
- float ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
- if(ForwardSpeed > 0.02f)
- MovingForward = true;
-
- float Dist = (Source - TargetCoors).Magnitude2D();
-
- float DeltaBeta = TargetOrientation - Beta;
- while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
- while(DeltaBeta < -PI) DeltaBeta += 2*PI;
-
- if(Abs(DeltaBeta) > DEGTORAD(20.0f) && MovingForward && TheCamera.m_uiTransitionState == 0)
- m_bFixingBeta = true;
-
- CPad *pad = CPad::GetPad(0);
- if(!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))
- if(DirectionWasLooking != LOOKING_FORWARD)
- TheCamera.m_bCamDirectlyBehind = true;
-
- if(!m_bFixingBeta && !TheCamera.m_bUseTransitionBeta && !TheCamera.m_bCamDirectlyBehind && !TheCamera.m_bCamDirectlyInFront)
- return false;
-
- bool SetBeta = false;
- if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront || TheCamera.m_bUseTransitionBeta)
- if(&TheCamera.Cams[TheCamera.ActiveCam] == this)
- SetBeta = true;
-
- if(m_bFixingBeta || SetBeta){
- WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, 0.15f, 0.007f, true);
-
- if(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this)
- Beta = TargetOrientation;
- if(TheCamera.m_bCamDirectlyInFront && &TheCamera.Cams[TheCamera.ActiveCam] == this)
- Beta = TargetOrientation + PI;
- if(TheCamera.m_bUseTransitionBeta && &TheCamera.Cams[TheCamera.ActiveCam] == this)
- Beta = m_fTransitionBeta;
-
- Source.x = TargetCoors.x - Cos(Beta)*Dist;
- Source.y = TargetCoors.y - Sin(Beta)*Dist;
-
- // Check if we're done
- DeltaBeta = TargetOrientation - Beta;
- while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
- while(DeltaBeta < -PI) DeltaBeta += 2*PI;
- if(Abs(DeltaBeta) < DEGTORAD(2.0f))
- m_bFixingBeta = false;
- }
- TheCamera.m_bCamDirectlyBehind = false;
- TheCamera.m_bCamDirectlyInFront = false;
- return true;
-}
-
-// Move the cam to avoid clipping through buildings
-bool
-CCam::FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation)
-{
- CVector Target = TargetCoors;
- bool UseEntityPos = false;
- CVector EntityPos;
- static CColPoint colPoint;
- static bool LastObscured = false;
-
- if(Mode == MODE_BEHINDCAR)
- Target.z += TargetHeight/2.0f;
- if(Mode == MODE_CAM_ON_A_STRING){
- UseEntityPos = true;
- Target.z += TargetHeight/2.0f;
- EntityPos = CamTargetEntity->GetPosition();
- }
-
- CVector TempSource = Source;
-
- bool Obscured1 = false;
- bool Obscured2 = false;
- bool Fix1 = false;
- float Dist1 = 0.0f;
- float Dist2 = 0.0f;
- CEntity *ent;
- if(m_bCollisionChecksOn || LastObscured){
- Obscured1 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
- if(Obscured1){
- Dist1 = (Target - colPoint.point).Magnitude2D();
- Fix1 = true;
- if(UseEntityPos)
- Obscured1 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
- }else if(m_bFixingBeta){
- float d = (TempSource - Target).Magnitude();
- TempSource.x = Target.x - d*Cos(TargetOrientation);
- TempSource.y = Target.y - d*Sin(TargetOrientation);
-
- // same check again
- Obscured2 = CWorld::ProcessLineOfSight(Target, TempSource, colPoint, ent, true, false, false, true, false, true, true);
- if(Obscured2){
- Dist2 = (Target - colPoint.point).Magnitude2D();
- if(UseEntityPos)
- Obscured2 = CWorld::ProcessLineOfSight(EntityPos, TempSource, colPoint, ent, true, false, false, true, false, true, true);
- }
- }
- LastObscured = Obscured1 || Obscured2;
- }
-
- // nothing to do
- if(!LastObscured)
- return false;
-
- if(Fix1){
- Source.x = Target.x - Cos(Beta)*Dist1;
- Source.y = Target.y - Sin(Beta)*Dist1;
- if(Mode == MODE_BEHINDCAR)
- Source = colPoint.point;
- }else{
- WellBufferMe(Dist2, &m_fDistanceBeforeChanges, &DistanceSpeed, 0.2f, 0.025f, false);
- Source.x = Target.x - Cos(Beta)*m_fDistanceBeforeChanges;
- Source.y = Target.y - Sin(Beta)*m_fDistanceBeforeChanges;
- }
-
- if(ResetStatics){
- m_fDistanceBeforeChanges = (Source - Target).Magnitude2D();
- DistanceSpeed = 0.0f;
- Source.x = colPoint.point.x;
- Source.y = colPoint.point.y;
- }
- return true;
-}
-
-void
-CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float)
-{
- if(!CamTargetEntity->IsVehicle())
- return;
-
- FOV = DefaultFOV;
-
- if(ResetStatics){
- AlphaSpeed = 0.0f;
- if(TheCamera.m_bIdleOn)
- TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds();
- }
-
- CBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
- CVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min;
- float BaseDist = Dimensions.Magnitude2D();
-
- CVector TargetCoors = CameraTarget;
- TargetCoors.z += Dimensions.z - 0.1f; // final
- Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
- while(Alpha >= PI) Alpha -= 2*PI;
- while(Alpha < -PI) Alpha += 2*PI;
- while(Beta >= PI) Beta -= 2*PI;
- while(Beta < -PI) Beta += 2*PI;
-
- m_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D();
-
- Cam_On_A_String_Unobscured(TargetCoors, BaseDist);
- WorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z);
- RotCamIfInFrontCar(TargetCoors, TargetOrientation);
- FixCamIfObscured(TargetCoors, Dimensions.z, TargetOrientation);
- FixCamWhenObscuredByVehicle(TargetCoors);
-
- m_cvecTargetCoorsForFudgeInter = TargetCoors;
- Front = TargetCoors - Source;
- Front.Normalise();
- GetVectorsReadyForRW();
- ResetStatics = false;
-}
-
-// Basic Cam on a string algorithm
-void
-CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)
-{
- CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth;
- CA_MIN_DISTANCE = min(BaseDist*0.6f, 3.5f);
-
- CVector Dist = Source - TargetCoors;
-
- if(ResetStatics)
- Source = TargetCoors + Dist*(CA_MAX_DISTANCE + 1.0f);
-
- float Length = Dist.Magnitude2D();
- if(Length < 0.001f){
- // This probably shouldn't happen. reset view
- CVector Forward = CamTargetEntity->GetForward();
- Forward.z = 0.0f;
- Forward.Normalise();
- Source = TargetCoors - Forward*CA_MAX_DISTANCE;
- Dist = Source - TargetCoors;
- Length = Dist.Magnitude2D();
- }
-
- if(Length > CA_MAX_DISTANCE){
- Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
- Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
- }else if(Length < CA_MIN_DISTANCE){
- Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
- Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
- }
-}
-
-void
-CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)
-{
- // BUG? is this never reset
- static float HeightFixerCarsObscuring = 0.0f;
- static float HeightFixerCarsObscuringSpeed = 0.0f;
- CColPoint colPoint;
- CEntity *entity;
-
- float HeightTarget = 0.0f;
- if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, false, true, false, false, false, false, false)){
- CBaseModelInfo *mi = CModelInfo::GetModelInfo(entity->GetModelIndex());
- HeightTarget = mi->GetColModel()->boundingBox.max.z + 1.0f + TargetCoors.z - Source.z;
- if(HeightTarget < 0.0f)
- HeightTarget = 0.0f;
- }
- WellBufferMe(HeightTarget, &HeightFixerCarsObscuring, &HeightFixerCarsObscuringSpeed, 0.2f, 0.025f, false);
- Source.z += HeightFixerCarsObscuring;
-}
-
-bool
-CCam::Using3rdPersonMouseCam()
-{
- return CCamera::m_bUseMouse3rdPerson &&
- (Mode == MODE_FOLLOWPED ||
- TheCamera.m_bPlayerIsInGarage &&
- FindPlayerPed() && FindPlayerPed()->m_nPedState != PED_DRIVING &&
- Mode != MODE_TOPDOWN && this->CamTargetEntity == FindPlayerPed());
-}
-
-bool
-CCam::GetWeaponFirstPersonOn()
-{
- CEntity *target = this->CamTargetEntity;
- if (target && target->IsPed())
- return ((CPed*)target)->GetWeapon()->m_bAddRotOffset;
-
- return false;
-}
-
float
CCamera::Find3rdPersonQuickAimPitch(void)
{
@@ -1478,22 +343,4 @@ STARTPATCHES
InjectHook(0x46B560, &CCamera::FinishCutscene, PATCH_JUMP);
InjectHook(0x46FF30, &CCamera::SetZoomValueFollowPedScript, PATCH_JUMP);
InjectHook(0x46FF90, &CCamera::SetZoomValueCamStringScript, PATCH_JUMP);
-
-
- InjectHook(0x456F40, WellBufferMe, PATCH_JUMP);
- InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP);
- InjectHook(0x457710, &CCam::DoAverageOnVector, PATCH_JUMP);
- InjectHook(0x458060, &CCam::GetPedBetaAngleForClearView, PATCH_JUMP);
- InjectHook(0x457210, &CCam::Cam_On_A_String_Unobscured, PATCH_JUMP);
- InjectHook(0x457A80, &CCam::FixCamWhenObscuredByVehicle, PATCH_JUMP);
- InjectHook(0x457B90, &CCam::FixCamIfObscured, PATCH_JUMP);
- InjectHook(0x465DA0, &CCam::RotCamIfInFrontCar, PATCH_JUMP);
- InjectHook(0x4662D0, &CCam::WorkOutCamHeightWeeCar, PATCH_JUMP);
- InjectHook(0x466650, &CCam::WorkOutCamHeight, PATCH_JUMP);
-
- InjectHook(0x45E3A0, &CCam::Process_FollowPed, PATCH_JUMP);
- InjectHook(0x45BE60, &CCam::Process_BehindCar, PATCH_JUMP);
- InjectHook(0x45C090, &CCam::Process_Cam_On_A_String, PATCH_JUMP);
-
- InjectHook(0x473250, &CCamera::dtor, PATCH_JUMP);
ENDPATCHES
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 980af5c1..982620a3 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -5,6 +5,8 @@ class CEntity;
class CPed;
class CAutomobile;
+extern int16 &DebugCamMode;
+
#define NUMBER_OF_VECTORS_FOR_AVERAGE 2
struct CCam
@@ -66,17 +68,17 @@ struct CCam
bool m_bTheHeightFixerVehicleIsATrain;
bool LookBehindCamWasInFront;
bool LookingBehind;
- bool LookingLeft; // 32
+ bool LookingLeft;
bool LookingRight;
bool ResetStatics; //for interpolation type stuff to work
bool Rotating;
int16 Mode; // CameraMode
- uint32 m_uiFinishTime; // 52
+ uint32 m_uiFinishTime;
int m_iDoCollisionChecksOnFrameNum;
int m_iDoCollisionCheckEveryNumOfFrames;
- int m_iFrameNumWereAt; // 64
+ int m_iFrameNumWereAt;
int m_iRunningVectorArrayPos;
int m_iRunningVectorCounter;
int DirectionWasLooking;
@@ -85,9 +87,9 @@ struct CCam
float f_Roll; //used for adding a slight roll to the camera in the
float f_rollSpeed;
float m_fSyphonModeTargetZOffSet;
- float m_fUnknownZOffSet;
+ float m_fRoadOffSet;
float m_fAmountFractionObscured;
- float m_fAlphaSpeedOverOneFrame; // 100
+ float m_fAlphaSpeedOverOneFrame;
float m_fBetaSpeedOverOneFrame;
float m_fBufferedTargetBeta;
float m_fBufferedTargetOrientation;
@@ -95,7 +97,7 @@ struct CCam
float m_fCamBufferedHeight;
float m_fCamBufferedHeightSpeed;
float m_fCloseInPedHeightOffset;
- float m_fCloseInPedHeightOffsetSpeed; // 132
+ float m_fCloseInPedHeightOffsetSpeed;
float m_fCloseInCarHeightOffset;
float m_fCloseInCarHeightOffsetSpeed;
float m_fDimensionOfHighestNearCar;
@@ -103,7 +105,7 @@ struct CCam
float m_fFovSpeedOverOneFrame;
float m_fMinDistAwayFromCamWhenInterPolating;
float m_fPedBetweenCameraHeightOffset;
- float m_fPlayerInFrontSyphonAngleOffSet; // 164
+ float m_fPlayerInFrontSyphonAngleOffSet;
float m_fRadiusForDead;
float m_fRealGroundDist; //used for follow ped mode
float m_fTargetBeta;
@@ -111,7 +113,7 @@ struct CCam
float m_fTransitionBeta;
float m_fTrueBeta;
- float m_fTrueAlpha; // 200
+ float m_fTrueAlpha;
float m_fInitialPlayerOrientation; //used for first person
float Alpha;
@@ -120,34 +122,25 @@ struct CCam
float FOVSpeed;
float Beta;
float BetaSpeed;
- float Distance; // 232
+ float Distance;
float DistanceSpeed;
float CA_MIN_DISTANCE;
float CA_MAX_DISTANCE;
float SpeedVar;
- // ped onfoot zoom distance
- float m_fTargetZoomGroundOne;
- float m_fTargetZoomGroundTwo; // 256
- float m_fTargetZoomGroundThree;
- // ped onfoot alpha angle offset
- float m_fTargetZoomOneZExtra;
- float m_fTargetZoomTwoZExtra;
- float m_fTargetZoomThreeZExtra;
-
- float m_fTargetZoomZCloseIn;
- float m_fMinRealGroundDist;
- float m_fTargetCloseInDist;
-
- CVector m_cvecTargetCoorsForFudgeInter; // 360
- CVector m_cvecCamFixedModeVector; // 372
- CVector m_cvecCamFixedModeSource; // 384
- CVector m_cvecCamFixedModeUpOffSet; // 396
- CVector m_vecLastAboveWaterCamPosition; //408 //helper for when the player has gone under the water
- CVector m_vecBufferedPlayerBodyOffset; // 420
+ CVector m_cvecSourceSpeedOverOneFrame;
+ CVector m_cvecTargetSpeedOverOneFrame;
+ CVector m_cvecUpOverOneFrame;
+
+ CVector m_cvecTargetCoorsForFudgeInter;
+ CVector m_cvecCamFixedModeVector;
+ CVector m_cvecCamFixedModeSource;
+ CVector m_cvecCamFixedModeUpOffSet;
+ CVector m_vecLastAboveWaterCamPosition; //helper for when the player has gone under the water
+ CVector m_vecBufferedPlayerBodyOffset;
// The three vectors that determine this camera for this frame
- CVector Front; // 432 // Direction of looking in
+ CVector Front; // Direction of looking in
CVector Source; // Coors in world space
CVector SourceBeforeLookBehind;
CVector Up; // Just that
@@ -162,6 +155,10 @@ struct CCam
bool m_bFirstPersonRunAboutActive;
+ CCam(void) { Init(); }
+ void Init(void);
+ void Process(void);
+ void ProcessSpecialHeightRoutines(void);
void GetVectorsReadyForRW(void);
CVector DoAverageOnVector(const CVector &vec);
float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies);
@@ -171,13 +168,59 @@ struct CCam
bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation);
void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);
void FixCamWhenObscuredByVehicle(const CVector &TargetCoors);
- bool Using3rdPersonMouseCam();
- bool GetWeaponFirstPersonOn();
-
- void Process_Debug(float *vec, float a, float b, float c);
+ void LookBehind(void);
+ void LookLeft(void);
+ void LookRight(void);
+ void ClipIfPedInFrontOfPlayer(void);
+ void KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov);
+ bool Using3rdPersonMouseCam(void);
+ bool GetWeaponFirstPersonOn(void);
+ bool IsTargetInWater(const CVector &CamCoors);
+ void AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit);
+ void PrintMode(void);
+
+ void Process_Debug(const CVector&, float, float, float);
+ void Process_Editor(const CVector&, float, float, float);
+ void Process_ModelView(const CVector &CameraTarget, float, float, float);
void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar);
+ void Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_Rocket(const CVector &CameraTarget, float, float, float);
+ void Process_M16_1stPerson(const CVector &CameraTarget, float, float, float);
+ void Process_1stPerson(const CVector &CameraTarget, float, float, float);
+ void Process_1rstPersonPedOnPC(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_Sniper(const CVector &CameraTarget, float, float, float);
+ void Process_Syphon(const CVector &CameraTarget, float, float, float);
+ void Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float);
+ void Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_FlyBy(const CVector&, float, float, float);
+ void Process_WheelCam(const CVector&, float, float, float);
+ void Process_Fixed(const CVector &CameraTarget, float, float, float);
+ void Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_Circle(const CVector &CameraTarget, float, float, float);
+ void Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float);
+ void ProcessPedsDeadBaby(void);
+ bool ProcessArrestCamOne(void);
+ bool ProcessArrestCamTwo(void);
+
+ /* Some of the unused PS2 cams */
+ void Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float, float, float);
+ void Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float);
+ void Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float);
+ // TODO:
+ // CCam::Process_CushyPillows_Arse
+ // CCam::Process_Look_At_Cars
+ // CCam::Process_CheesyZoom
+ // CCam::Process_Aiming
+ // CCam::Process_Bill // same as BehindCar due to unused variables
+ // CCam::Process_Im_The_Passenger_Woo_Woo
+ // CCam::Process_Blood_On_The_Tracks
+ // CCam::Process_Cam_Running_Side_Train
+ // CCam::Process_Cam_On_Train_Roof
};
static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
@@ -223,6 +266,7 @@ enum
FADE_OUT = 0,
FADE_IN,
+ FADE_NONE
};
enum
@@ -445,8 +489,8 @@ uint32 unknown;
uint32 m_fScriptTimeForInterPolation;
-int16 m_iFadingDirection;
-int m_iModeObbeCamIsInForCar;
+ int16 m_iFadingDirection;
+ int m_iModeObbeCamIsInForCar;
int16 m_iModeToGoTo;
int16 m_iMusicFadingDirection;
int16 m_iTypeOfSwitch;
@@ -493,6 +537,7 @@ int m_iModeObbeCamIsInForCar;
void TakeControlNoEntity(const CVector&, int16, int32);
void SetCamPositionForFixedMode(const CVector&, const CVector&);
bool GetFading();
+ int GetFadingDirection();
void Init();
void SetRwCamera(RwCamera*);
@@ -525,8 +570,12 @@ static_assert(offsetof(CCamera, m_uiTransitionState) == 0x89, "CCamera: error");
static_assert(offsetof(CCamera, m_uiTimeTransitionStart) == 0x94, "CCamera: error");
static_assert(offsetof(CCamera, m_BlurBlue) == 0x9C, "CCamera: error");
static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error");
+static_assert(offsetof(CCamera, pToGarageWeAreIn) == 0x690, "CCamera: error");
+static_assert(offsetof(CCamera, m_PreviousCameraPosition) == 0x6B0, "CCamera: error");
static_assert(offsetof(CCamera, m_vecCutSceneOffset) == 0x6F8, "CCamera: error");
+static_assert(offsetof(CCamera, m_arrPathArray) == 0x7a8, "CCamera: error");
static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
+
extern CCamera &TheCamera;
-void CamShakeNoPos(CCamera*, float); \ No newline at end of file
+void CamShakeNoPos(CCamera*, float);
diff --git a/src/core/Debug.cpp b/src/core/Debug.cpp
index bdcbaf04..2b713198 100644
--- a/src/core/Debug.cpp
+++ b/src/core/Debug.cpp
@@ -89,3 +89,49 @@ CDebug::DebugDisplayTextBuffer()
}
#endif
}
+
+
+// custom
+
+CDebug::ScreenStr CDebug::ms_aScreenStrs[MAX_SCREEN_STRS];
+int CDebug::ms_nScreenStrs;
+
+void
+CDebug::DisplayScreenStrings()
+{
+ int i;
+
+
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(1.0f, 1.0f);
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ CFont::SetJustifyOff();
+ CFont::SetRightJustifyWrap(0.0f);
+ CFont::SetWrapx(9999.0f);
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_BANK);
+
+ for(i = 0; i < ms_nScreenStrs; i++){
+ AsciiToUnicode(ms_aScreenStrs[i].str, gUString);
+ CFont::SetColor(CRGBA(0, 0, 0, 255));
+ CFont::PrintString(ms_aScreenStrs[i].x, ms_aScreenStrs[i].y, gUString);
+ CFont::SetColor(CRGBA(255, 255, 255, 255));
+ CFont::PrintString(ms_aScreenStrs[i].x+1, ms_aScreenStrs[i].y+1, gUString);
+ }
+ CFont::DrawFonts();
+
+ ms_nScreenStrs = 0;
+}
+
+void
+CDebug::PrintAt(const char *str, int x, int y)
+{
+ if(ms_nScreenStrs >= MAX_SCREEN_STRS)
+ return;
+ strncpy(ms_aScreenStrs[ms_nScreenStrs].str, str, 256);
+ ms_aScreenStrs[ms_nScreenStrs].x = x*12;
+ ms_aScreenStrs[ms_nScreenStrs].y = y*22;
+ ms_nScreenStrs++;
+}
diff --git a/src/core/Debug.h b/src/core/Debug.h
index 444a0cf5..d169a0b4 100644
--- a/src/core/Debug.h
+++ b/src/core/Debug.h
@@ -6,15 +6,29 @@ class CDebug
{
MAX_LINES = 15,
MAX_STR_LEN = 80,
+
+ MAX_SCREEN_STRS = 100,
};
static int16 ms_nCurrentTextLine;
static char ms_aTextBuffer[MAX_LINES][MAX_STR_LEN];
+ // custom
+ struct ScreenStr {
+ int x, y;
+ char str[256];
+ };
+ static ScreenStr ms_aScreenStrs[MAX_SCREEN_STRS];
+ static int ms_nScreenStrs;
+
public:
static void DebugInitTextBuffer();
static void DebugDisplayTextBuffer();
static void DebugAddText(const char *str);
+
+ // custom
+ static void PrintAt(const char *str, int x, int y);
+ static void DisplayScreenStrings();
};
extern bool gbDebugStuffInRelease;
diff --git a/src/core/Pad.h b/src/core/Pad.h
index 09691128..fec21df3 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -399,6 +399,8 @@ public:
bool GetLeftShoulder2JustDown() { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); }
bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }
bool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); }
+ bool GetLeftShockJustDown() { return !!(NewState.LeftShock && !OldState.LeftShock); }
+ bool GetRightShockJustDown() { return !!(NewState.RightShock && !OldState.RightShock); }
bool GetStartJustDown() { return !!(NewState.Start && !OldState.Start); }
bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }
bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }
@@ -422,6 +424,10 @@ public:
bool GetLeftShoulder2(void) { return !!NewState.LeftShoulder2; }
bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; }
bool GetRightShoulder2(void) { return !!NewState.RightShoulder2; }
+ int16 GetLeftStickX(void) { return NewState.LeftStickX; }
+ int16 GetLeftStickY(void) { return NewState.LeftStickY; }
+ int16 GetRightStickX(void) { return NewState.RightStickX; }
+ int16 GetRightStickY(void) { return NewState.RightStickY; }
bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }
};
diff --git a/src/core/World.cpp b/src/core/World.cpp
index cbceb292..1dda1056 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -20,11 +20,12 @@
#include "Replay.h"
#include "Population.h"
+CColPoint *gaTempSphereColPoints = (CColPoint*)0x6E64C0; // [32]
+
CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60;
CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C;
CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608;
uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64;
-CColPoint &CWorld::ms_testSpherePoint = *(CColPoint*)0x6E64C0;
uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61;
CPlayerInfo (&CWorld::Players)[NUMPLAYERS] = *(CPlayerInfo (*)[NUMPLAYERS])*(uintptr*)0x9412F0;
@@ -609,9 +610,9 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo
}
void
-CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects)
+CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects)
{
- float distSqr = distance * distance;
+ float radiusSqr = radius * radius;
float objDistSqr;
for (CPtrNode *node = list.first; node; node = node->next) {
@@ -625,7 +626,7 @@ CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float dist
else
objDistSqr = diff.MagnitudeSqr();
- if (objDistSqr < distSqr && *nextObject < lastObject) {
+ if (objDistSqr < radiusSqr && *nextObject < lastObject) {
if (objects) {
objects[*nextObject] = object;
}
@@ -636,22 +637,22 @@ CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float dist
}
void
-CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
+CWorld::FindObjectsInRange(CVector &centre, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
{
- int minX = GetSectorIndexX(centre.x - distance);
+ int minX = GetSectorIndexX(centre.x - radius);
if (minX <= 0) minX = 0;
- int minY = GetSectorIndexY(centre.y - distance);
+ int minY = GetSectorIndexY(centre.y - radius);
if (minY <= 0) minY = 0;
- int maxX = GetSectorIndexX(centre.x + distance);
+ int maxX = GetSectorIndexX(centre.x + radius);
#ifdef FIX_BUGS
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
- int maxY = GetSectorIndexY(centre.y + distance);
+ int maxY = GetSectorIndexY(centre.y + radius);
#ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
@@ -665,48 +666,48 @@ CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short
for(int curX = minX; curX <= maxX; curX++) {
CSector *sector = GetSector(curX, curY);
if (checkBuildings) {
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
}
if (checkVehicles) {
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, ignoreZ, nextObject, lastObject, objects);
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
}
if (checkPeds) {
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
}
if (checkObjects) {
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
}
if (checkDummies) {
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, ignoreZ, nextObject, lastObject, objects);
- FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
}
}
}
}
CEntity*
-CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects)
+CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects)
{
CEntity* foundE = nil;
- int minX = GetSectorIndexX(centre.x - distance);
+ int minX = GetSectorIndexX(centre.x - radius);
if (minX <= 0) minX = 0;
- int minY = GetSectorIndexY(centre.y - distance);
+ int minY = GetSectorIndexY(centre.y - radius);
if (minY <= 0) minY = 0;
- int maxX = GetSectorIndexX(centre.x + distance);
+ int maxX = GetSectorIndexX(centre.x + radius);
#ifdef FIX_BUGS
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
- int maxY = GetSectorIndexY(centre.y + distance);
+ int maxY = GetSectorIndexY(centre.y + radius);
#ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
@@ -719,47 +720,47 @@ CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityTo
for (int curX = minX; curX <= maxX; curX++) {
CSector* sector = GetSector(curX, curY);
if (checkBuildings) {
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
}
if (checkVehicles) {
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
}
if (checkPeds) {
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
}
if (checkObjects) {
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, entityToIgnore, ignoreSomeObjects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius, entityToIgnore, ignoreSomeObjects);
if (foundE)
return foundE;
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, entityToIgnore, ignoreSomeObjects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, entityToIgnore, ignoreSomeObjects);
if (foundE)
return foundE;
}
if (checkDummies) {
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
- foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, entityToIgnore, false);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE)
return foundE;
}
@@ -806,7 +807,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
if (e->GetBoundRadius() + radius > distance) {
CColModel *eCol = CModelInfo::GetModelInfo(e->m_modelIndex)->GetColModel();
int collidedSpheres = CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(),
- *eCol, &ms_testSpherePoint, nil, nil);
+ *eCol, gaTempSphereColPoints, nil, nil);
if (collidedSpheres != 0 ||
(e->IsVehicle() && ((CVehicle*)e)->m_vehType == VEHICLE_TYPE_CAR &&
diff --git a/src/core/World.h b/src/core/World.h
index 1ad65ac4..4b19e629 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -60,8 +60,6 @@ class CWorld
static uint16 &ms_nCurrentScanCode;
public:
- static CColPoint& ms_testSpherePoint;
-
static uint8 &PlayerInFocus;
static CPlayerInfo (&Players)[NUMPLAYERS];
static CEntity *&pIgnoreEntity;
@@ -101,7 +99,7 @@ public:
static bool GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
static bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
- static CEntity *TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects);
+ static CEntity *TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects);
static CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool);
static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**);
static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
@@ -141,6 +139,8 @@ public:
static void Process();
};
+extern CColPoint *gaTempSphereColPoints;
+
class CPlayerPed;
class CVehicle;
CPlayerPed *FindPlayerPed(void);
diff --git a/src/core/config.h b/src/core/config.h
index ff779946..8b7b5a18 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -204,3 +204,5 @@ enum Config {
#define VC_PED_PORTS // various ports from VC's CPed, mostly subtle
// #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward
#define CANCELLABLE_CAR_ENTER
+
+#define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 2a15e20e..663b09da 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -325,6 +325,7 @@ DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16
void
DoRWStuffEndOfFrame(void)
{
+ CDebug::DisplayScreenStrings(); // custom
CDebug::DebugDisplayTextBuffer();
// FlushObrsPrintfs();
RwCameraEndUpdate(Scene.camera);
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 6f0a4682..0301a98a 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -20,6 +20,7 @@
#include "debugmenu_public.h"
#include "Particle.h"
#include "Console.h"
+#include "Debug.h"
#include <vector>
#include <list>
@@ -114,13 +115,16 @@ SpawnCar(int id)
CStreaming::LoadAllRequestedModels(false);
if(CStreaming::HasModelLoaded(id)){
playerpos = FindPlayerCoors();
- int node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);
- if(node < 0)
- return;
+ int node;
+ if(!CModelInfo::IsBoatModel(id)){
+ node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);
+ if(node < 0)
+ return;
+ }
CVehicle *v;
if(CModelInfo::IsBoatModel(id))
- return;
+ v = new CBoat(id, RANDOM_VEHICLE);
else
v = new CAutomobile(id, RANDOM_VEHICLE);
@@ -130,7 +134,11 @@ SpawnCar(int id)
if(carCol2)
DebugMenuEntrySetAddress(carCol2, &v->m_currentColour2);
- v->GetPosition() = ThePaths.m_pathNodes[node].pos;
+ if(CModelInfo::IsBoatModel(id))
+ v->GetPosition() = TheCamera.GetPosition() + TheCamera.GetForward()*15.0f;
+ else
+ v->GetPosition() = ThePaths.m_pathNodes[node].pos;
+
v->GetPosition().z += 4.0f;
v->SetOrientation(0.0f, 0.0f, 3.49f);
v->m_status = STATUS_ABANDONED;
@@ -197,6 +205,12 @@ PlaceOnRoad(void)
((CAutomobile*)veh)->PlaceOnRoadProperly();
}
+static void
+ResetCamStatics(void)
+{
+ TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
+}
+
static const char *carnames[] = {
"landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony",
"mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer",
@@ -358,7 +372,17 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
-
+
+ extern bool PrintDebugCode;
+ extern int16 &DebugCamMode;
+ DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil);
+ DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil);
+ DebugMenuAddCmd("Cam", "Normal", []() { DebugCamMode = 0; });
+ DebugMenuAddCmd("Cam", "Follow Ped With Bind", []() { DebugCamMode = CCam::MODE_FOLLOW_PED_WITH_BIND; });
+ DebugMenuAddCmd("Cam", "Reaction", []() { DebugCamMode = CCam::MODE_REACTION; });
+ DebugMenuAddCmd("Cam", "Chris", []() { DebugCamMode = CCam::MODE_CHRIS; });
+ DebugMenuAddCmd("Cam", "Reset Statics", ResetCamStatics);
+
CTweakVars::AddDBG("Debug");
}
}
@@ -433,7 +457,8 @@ void re3_debug(const char *format, ...)
vsprintf_s(re3_buff, re3_buffsize, format, va);
va_end(va);
- printf("%s", re3_buff);
+// printf("%s", re3_buff);
+ CDebug::DebugAddText(re3_buff);
}
void re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...)
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index ae24faa3..c8e8c4e4 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -12177,11 +12177,11 @@ CPed::PlacePedOnDryLand(void)
if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
return false;
- CVector potentialGroundDist = CWorld::ms_testSpherePoint.point - GetPosition();
+ CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
potentialGroundDist.z = 0.0f;
potentialGroundDist.Normalise();
- CVector posToCheck = 0.5f * potentialGroundDist + CWorld::ms_testSpherePoint.point;
+ CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
posToCheck.z = 3.0f + waterLevel;
if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, false)) {
diff --git a/src/render/Font.cpp b/src/render/Font.cpp
index 7a16ad03..d7b4b5d8 100644
--- a/src/render/Font.cpp
+++ b/src/render/Font.cpp
@@ -94,7 +94,7 @@ CFont::Initialise(void)
SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80));
SetBackGroundOnlyTextOff();
SetPropOn();
- SetFontStyle(0);
+ SetFontStyle(FONT_BANK);
SetRightJustifyWrap(0.0f);
SetAlphaFade(255.0f);
SetDropShadowPosition(0);
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index f0134062..52930067 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -115,47 +115,43 @@ void CHud::Draw()
return;
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
- bool Mode_RunAround = 0;
- bool Mode_FirstPerson = 0;
+ bool DrawCrossHair = 0;
+ bool DrawCrossHairPC = 0;
int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType;
int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
- if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_EDITOR)
- Mode_FirstPerson = 1;
- if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
- Mode_RunAround = 1;
+ if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON)
+ DrawCrossHair = 1;
+ if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
+ DrawCrossHairPC = 1;
/*
Draw Crosshairs
*/
- if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() &&
+ (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) {
if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER)
- Mode_RunAround = 1;
+ DrawCrossHairPC = 1;
}
}
- if (Mode_FirstPerson || Mode_RunAround) {
+ if (DrawCrossHair || DrawCrossHairPC) {
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
- int32 SpriteBrightLikeADiamond = SpriteBrightness + 1;
- if (SpriteBrightLikeADiamond > 30)
- SpriteBrightLikeADiamond = 30;
-
- SpriteBrightness = SpriteBrightLikeADiamond;
+ SpriteBrightness = min(SpriteBrightness+1, 30);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
- float fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023) * 0.0061328127);
+ float fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023)/1024.0f * 6.28f);
float fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f);
CRect rect;
+ if (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) {
#ifndef ASPECT_RATIO_SCALE
- if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX;
float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY;
#else
- if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
float f3rdX = (((TheCamera.m_f3rdPersonCHairMultX - 0.5f) / ((CDraw::GetAspectRatio()) / (DEFAULT_ASPECT_RATIO))) + 0.5f) * SCREEN_WIDTH;
float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY + SCREEN_SCALE_Y(-2.0f);
#endif
@@ -179,14 +175,14 @@ void CHud::Draw()
else {
if (Mode == CCam::MODE_M16_1STPERSON ||
Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
- Mode == CCam::MODE_EDITOR) {
+ Mode == CCam::MODE_HELICANNON_1STPERSON) {
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f);
rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f);
rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f);
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
}
- else if (Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
+ else if (Mode == CCam::MODE_1STPERSON_RUNABOUT) {
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f * 0.7f);
rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f * 0.7f);
@@ -194,17 +190,18 @@ void CHud::Draw()
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
}
- else if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_SNIPER_RUNABOUT) {
+ else if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRocketSightTex->raster);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex));
CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255);
}
else {
+ // Sniper
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f);
rect.right = SCREEN_WIDTH / 2;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index ff9f5755..d7834065 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -645,6 +645,9 @@ CRenderer::ScanWorld(void)
m_loadingPriority = false;
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
+#ifdef FIX_BUGS
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||
+#endif
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
CRect rect;
int x1, x2, y1, y2;
@@ -756,6 +759,9 @@ CRenderer::RequestObjectsInFrustum(void)
RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix);
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
+#ifdef FIX_BUGS
+ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||
+#endif
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
CRect rect;
int x1, x2, y1, y2;