summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/AnimViewer.cpp2
-rw-r--r--src/core/Cam.cpp125
-rw-r--r--src/core/Camera.cpp3404
-rw-r--r--src/core/Camera.h224
-rw-r--r--src/core/CutsceneMgr.h1
-rw-r--r--src/core/FrontEndControls.cpp1881
-rw-r--r--src/core/FrontEndControls.h712
-rw-r--r--src/core/Frontend.cpp8
-rw-r--r--src/core/Frontend.h2
-rw-r--r--src/core/Pad.h2
-rw-r--r--src/core/Stats.cpp70
-rw-r--r--src/core/Stats.h18
-rw-r--r--src/core/config.h6
-rw-r--r--src/core/re3.cpp6
14 files changed, 6115 insertions, 346 deletions
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index 20a0098d..1086db20 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -294,7 +294,7 @@ CAnimViewer::Update(void)
}
newEntity->GetPosition() = CVector(0.0f, 0.0f, 0.0f);
CWorld::Add(newEntity);
- TheCamera.TakeControl(pTarget, CCam::MODE_MODELVIEW, JUMP_CUT, CAM_CONTROLLER_1);
+ TheCamera.TakeControl(pTarget, CCam::MODE_MODELVIEW, JUMP_CUT, CAMCONTROL_SCRIPT);
}
if (pTarget->m_type == ENTITY_TYPE_VEHICLE || pTarget->m_type == ENTITY_TYPE_PED || pTarget->m_type == ENTITY_TYPE_OBJECT) {
((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index dd1b5ce2..5b7a53e9 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -31,8 +31,7 @@ bool PrintDebugCode = false;
int16 &DebugCamMode = *(int16*)0x95CCF2;
#ifdef FREE_CAM
-bool bFreePadCam = false;
-bool bFreeMouseCam = false;
+bool CCamera::bFreeCam = false;
int nPreviousMode = -1;
#endif
@@ -146,7 +145,7 @@ CCam::Process(void)
Process_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#ifdef FREE_CAM
- if(bFreePadCam)
+ if(CCamera::bFreeCam)
Process_FollowPed_Rotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
@@ -187,7 +186,7 @@ CCam::Process(void)
break;
case MODE_CAM_ON_A_STRING:
#ifdef FREE_CAM
- if(bFreeMouseCam || bFreePadCam)
+ if(CCamera::bFreeCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
@@ -204,7 +203,7 @@ CCam::Process(void)
break;
case MODE_BEHINDBOAT:
#ifdef FREE_CAM
- if (bFreeMouseCam || bFreePadCam)
+ if (CCamera::bFreeCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
@@ -267,7 +266,7 @@ CCam::Process(void)
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?
+ if(TheCamera.m_uiTransitionState == 0)
KeepTrackOfTheSpeed(Source, m_cvecTargetCoorsForFudgeInter, Up, m_fTrueAlpha, m_fTrueBeta, FOV);
// Look Behind, Left, Right
@@ -421,11 +420,11 @@ CCam::ProcessSpecialHeightRoutines(void)
float DistScale = (2.1f - dist)/2.1f;
if(Mode == MODE_FOLLOWPED){
- if(TheCamera.PedZoomIndicator == 1.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_1)
Offset = 0.45*DistScale + PedZDist;
- if(TheCamera.PedZoomIndicator == 2.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_2)
Offset = 0.35*DistScale + PedZDist;
- if(TheCamera.PedZoomIndicator == 3.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_3)
Offset = 0.25*DistScale + PedZDist;
if(Abs(CGeneral::GetRadianAngleBetweenPoints(CamToPed.x, CamToPed.y, CamToTarget.x, CamToTarget.y)) > HALFPI)
Offset += 0.3f;
@@ -575,11 +574,11 @@ CCam::ProcessSpecialHeightRoutines(void)
m_fRoadOffSet = 1.4f;
}else{
if(Mode == MODE_FOLLOWPED){
- if(TheCamera.PedZoomIndicator == 1.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_1)
m_fRoadOffSet += 0.2f;
- if(TheCamera.PedZoomIndicator == 2.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_2)
m_fRoadOffSet += 0.5f;
- if(TheCamera.PedZoomIndicator == 3.0f)
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_3)
m_fRoadOffSet += 0.95f;
}
}
@@ -628,7 +627,7 @@ CCam::LookBehind(void)
DeltaBeta = TargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
- if(DirectionWasLooking == LOOKING_BEHIND)
+ if(DirectionWasLooking != LOOKING_BEHIND)
LookBehindCamWasInFront = DeltaBeta <= -HALFPI || DeltaBeta >= HALFPI;
if(LookBehindCamWasInFront)
TargetOrientation += PI;
@@ -636,7 +635,7 @@ CCam::LookBehind(void)
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);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
Source = colPoint.point;
}
Source.z += 1.0f;
@@ -800,7 +799,7 @@ CCam::ClipIfPedInFrontOfPlayer(void)
if(Abs(DeltaAngle) < HALFPI){
fDist = Sqrt(SQR(vDist.x) + SQR(vDist.y));
if(fDist < 1.25f){
- Near = 0.9f - (1.25f - fDist);
+ Near = DEFAULT_NEAR - (1.25f - fDist);
if(Near < 0.05f)
Near = 0.05f;
RwCameraSetNearClipPlane(Scene.camera, Near);
@@ -1044,7 +1043,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
}else{
LateralDist = 0.8f;
CenterDist = 1.35f;
- if(TheCamera.PedZoomIndicator == 1.0f || TheCamera.PedZoomIndicator == 4.0f){
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 || TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN){
LateralDist = 1.25f;
CenterDist = 1.6f;
}
@@ -1082,7 +1081,6 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
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);
@@ -1111,17 +1109,17 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
// 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;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_1) m_fRealGroundDist = 2.090556f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) m_fRealGroundDist = 3.34973f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) m_fRealGroundDist = 4.704914f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) m_fRealGroundDist = 2.090556f;
}
// 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(TheCamera.PedZoomIndicator == CAM_ZOOM_1) RealGroundDist = 2.090556f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_2) RealGroundDist = 3.34973f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_3) RealGroundDist = 4.704914f;
+ if(TheCamera.PedZoomIndicator == CAM_ZOOM_TOPDOWN) RealGroundDist = 2.090556f;
if(m_fCloseInPedHeightOffset > 0.00001f)
RealGroundDist = 1.7016f;
@@ -1292,8 +1290,8 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
// Now do the Beta rotation
- float Distance = (IdealSource - TargetCoors).Magnitude2D();
- m_fDistanceBeforeChanges = Distance;
+ float RotDistance = (IdealSource - TargetCoors).Magnitude2D();
+ m_fDistanceBeforeChanges = RotDistance;
if(Rotating){
m_bFixingBeta = true;
@@ -1334,8 +1332,8 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
BetaSpeed = 0.0f;
}
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
+ Source.x = TargetCoors.x + RotDistance * Cos(Beta);
+ Source.y = TargetCoors.y + RotDistance * Sin(Beta);
// Check if we can stop rotating
DeltaBeta = FixedTargetOrientation - Beta;
@@ -1354,18 +1352,18 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl
HackPlayerOnStoppingTrain || Rotating){
if(TheCamera.m_bCamDirectlyBehind){
Beta = TargetOrientation + PI;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
+ Source.x = TargetCoors.x + RotDistance * Cos(Beta);
+ Source.y = TargetCoors.y + RotDistance * Sin(Beta);
}
if(TheCamera.m_bCamDirectlyInFront){
Beta = TargetOrientation;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
+ Source.x = TargetCoors.x + RotDistance * Cos(Beta);
+ Source.y = TargetCoors.y + RotDistance * Sin(Beta);
}
if(HackPlayerOnStoppingTrain){
Beta = TargetOrientation + PI;
- Source.x = TargetCoors.x + Distance * Cos(Beta);
- Source.y = TargetCoors.y + Distance * Sin(Beta);
+ Source.x = TargetCoors.x + RotDistance * Cos(Beta);
+ Source.y = TargetCoors.y + RotDistance * Sin(Beta);
m_fDimensionOfHighestNearCar = 0.0f;
m_fCamBufferedHeight = 0.0f;
m_fCamBufferedHeightSpeed = 0.0f;
@@ -1551,7 +1549,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
// SA code
#ifdef FREE_CAM
- if((bFreeMouseCam && Alpha > 0.0f) || (!bFreeMouseCam && Alpha > fBaseDist))
+ if((CCamera::bFreeCam && Alpha > 0.0f) || (!CCamera::bFreeCam && Alpha > fBaseDist))
#else
if(Alpha > fBaseDist) // comparing an angle against a distance?
#endif
@@ -1586,14 +1584,14 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
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)
+ if(PedColDist < DEFAULT_NEAR + 0.3f)
RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
}else{
- RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, 0.9f));
+ RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, DEFAULT_NEAR));
}
}else{
Source = colPoint.point;
- if(PedColDist < 0.9f + 0.3f)
+ if(PedColDist < DEFAULT_NEAR + 0.3f)
RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
}
}
@@ -1640,7 +1638,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
CPed *player = FindPlayerPed();
float PlayerDist = (Source - player->GetPosition()).Magnitude();
if(PlayerDist < 2.75f)
- Near = PlayerDist/2.75f * 0.9f - 0.3f;
+ Near = PlayerDist/2.75f * DEFAULT_NEAR - 0.3f;
RwCameraSetNearClipPlane(Scene.camera, max(Near, 0.1f));
}
}
@@ -1800,11 +1798,11 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa
float zoomvalue = TheCamera.CarZoomValueSmooth;
if(zoomvalue < 0.1f)
zoomvalue = 0.1f;
- if(TheCamera.CarZoomIndicator == 1.0f)
+ if(TheCamera.CarZoomIndicator == CAM_ZOOM_1)
ModeAlpha = CGeneral::GetATanOfXY(23.0f, zoomvalue); // near
- else if(TheCamera.CarZoomIndicator == 2.0f)
+ else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)
ModeAlpha = CGeneral::GetATanOfXY(10.8f, zoomvalue); // mid
- else if(TheCamera.CarZoomIndicator == 3.0f)
+ else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)
ModeAlpha = CGeneral::GetATanOfXY(7.0f, zoomvalue); // far
@@ -1900,7 +1898,7 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa
PreviousNearCheckNearClipSmall = false;
if(!CamClear){
PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
DeltaAlpha = TargetAlpha - (Alpha + ModeAlpha);
while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
@@ -1918,7 +1916,7 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa
if(CamClear)
if(CamZ - CamGround2 < 1.5f){
PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
float a;
if(Length == 0.0f || CamGround2 + 1.5f - TargetCoors.z == 0.0f)
@@ -1934,7 +1932,7 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa
float CamRoof2 = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, CamZ, &FoundRoof);
if(FoundRoof && CamZ - CamRoof2 < 1.5f){
PreviousNearCheckNearClipSmall = true;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
if(CamRoof2 > TargetCoors.z + 3.5f)
CamRoof2 = TargetCoors.z + 3.5f;
@@ -1956,7 +1954,7 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa
LastAlphaSpeedStep = AlphaSpeedStep;
}else{
if(PreviousNearCheckNearClipSmall)
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
}
WellBufferMe(LastTargetAlphaWithCollisionOn, &Alpha, &AlphaSpeed, LastTopAlphaSpeed, LastAlphaSpeedStep, true);
@@ -3204,7 +3202,8 @@ CCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, f
static float WaterZAddition = 2.75f;
float WaterLevel = 0.0f;
float s, c;
- float Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
+
+ Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
FOV = DefaultFOV;
if(ResetStatics){
@@ -3717,7 +3716,7 @@ CCam::Process_Debug(const CVector&, float, float, float)
static float PanSpeedY = 0.0f;
CVector TargetCoors;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
@@ -3814,7 +3813,7 @@ CCam::Process_Debug(const CVector&, float, float, float)
static float Speed = 0.0f;
CVector TargetCoors;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
@@ -3887,7 +3886,7 @@ CCam::Process_Editor(const CVector&, float, float, float)
}
ResetStatics = false;
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
@@ -4465,11 +4464,14 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
- if(bFreeMouseCam && (MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
+/*
+ if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
UseMouse = true;
LookLeftRight = -2.5f*MouseX;
LookUpDown = 4.0f*MouseY;
- }else{
+ }else
+*/
+ {
LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
}
@@ -4553,14 +4555,14 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
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)
+ if(PedColDist < DEFAULT_NEAR + 0.3f)
RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
}else{
- RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, 0.9f));
+ RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, DEFAULT_NEAR));
}
}else{
Source = colPoint.point;
- if(PedColDist < 0.9f + 0.3f)
+ if(PedColDist < DEFAULT_NEAR + 0.3f)
RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f));
}
}
@@ -4922,7 +4924,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
bool mouseChangesBeta = false;
// FIX: Disable mouse movement in drive-by, it's buggy. Original SA bug.
- if (bFreeMouseCam && CCamera::m_bUseMouse3rdPerson && !pad->ArePlayerControlsDisabled() && nextDirectionIsForward) {
+ if (/*bFreeMouseCam &&*/ CCamera::m_bUseMouse3rdPerson && !pad->ArePlayerControlsDisabled() && nextDirectionIsForward) {
float mouseY = pad->GetMouseY() * 2.0f;
float mouseX = pad->GetMouseX() * -2.0f;
@@ -5093,10 +5095,10 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
} else {
if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false)) {
float lessClip = obstacleCamDist - 0.35f;
- if (lessClip <= 0.9f)
+ if (lessClip <= DEFAULT_NEAR)
RwCameraSetNearClipPlane(Scene.camera, lessClip);
else
- RwCameraSetNearClipPlane(Scene.camera, 0.9f);
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
} else {
obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude();
Source = foundCol.point;
@@ -5238,9 +5240,6 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation,
#endif
STARTPATCHES
-#ifdef FREE_CAM
- Nop(0x468E7B, 0x468E90-0x468E7B); // disable first person
-#endif
InjectHook(0x456F40, WellBufferMe, PATCH_JUMP);
InjectHook(0x458410, &CCam::Init, PATCH_JUMP);
InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP);
@@ -5290,6 +5289,4 @@ STARTPATCHES
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 3f7ed286..e5bc09c8 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -4,277 +4,2903 @@
#include "Draw.h"
#include "World.h"
#include "Vehicle.h"
+#include "Train.h"
+#include "Automobile.h"
#include "Ped.h"
#include "PlayerPed.h"
+#include "Wanted.h"
#include "Pad.h"
+#include "ControllerConfig.h"
#include "General.h"
#include "ZoneCull.h"
#include "SurfaceTable.h"
+#include "WaterLevel.h"
+#include "World.h"
+#include "Garages.h"
+#include "Replay.h"
+#include "CutsceneMgr.h"
+#include "Renderer.h"
#include "MBlur.h"
+#include "Text.h"
+#include "Hud.h"
+#include "DMAudio.h"
+#include "FileMgr.h"
+#include "Frontend.h"
+#include "SceneEdit.h"
+#include "Pools.h"
+#include "Debug.h"
#include "Camera.h"
+enum
+{
+ // car
+ OBBE_WHEEL,
+ OBBE_1,
+ OBBE_2,
+ OBBE_3,
+ OBBE_1STPERSON, // unused
+ OBBE_5,
+ OBBE_ONSTRING,
+ OBBE_COPCAR,
+ OBBE_COPCAR_WHEEL,
+ // ped
+ OBBE_9,
+ OBBE_10,
+ OBBE_11,
+ OBBE_12,
+ OBBE_13,
+
+ OBBE_INVALID
+};
+
+// abbreviate a few things
+#define PLAYER (CWorld::Players[CWorld::PlayerInFocus].m_pPed)
+// NB: removed explicit TheCamera from all functions
+
CCamera &TheCamera = *(CCamera*)0x6FACF8;
bool &CCamera::m_bUseMouse3rdPerson = *(bool *)0x5F03D8;
+bool &bDidWeProcessAnyCinemaCam = *(bool*)0x95CD46;
-WRAPPER void CCamera::CamShake(float strength, float x, float y, float z) { EAXJMP(0x46B200); }
-WRAPPER void CCamera::DrawBordersForWideScreen(void) { EAXJMP(0x46B430); }
-WRAPPER void CCamera::CalculateDerivedValues(void) { EAXJMP(0x46EEA0); }
-WRAPPER void CCamera::Restore(void) { EAXJMP(0x46F990); }
-WRAPPER void CamShakeNoPos(CCamera*, float) { EAXJMP(0x46B100); }
-WRAPPER void CCamera::TakeControl(CEntity*, int16, int16, int32) { EAXJMP(0x471500); }
-WRAPPER void CCamera::TakeControlNoEntity(const CVector&, int16, int32) { EAXJMP(0x4715B0); }
-WRAPPER void CCamera::Init(void) { EAXJMP(0x46BAD0); }
-WRAPPER void CCamera::Process(void) { EAXJMP(0x46D3F0); }
-WRAPPER void CCamera::LoadPathSplines(int file) { EAXJMP(0x46D1D0); }
-WRAPPER void CCamera::RestoreWithJumpCut(void) { EAXJMP(0x46FAE0); };
-WRAPPER void CCamera::SetPercentAlongCutScene(float) { EAXJMP(0x46FE20); };
-WRAPPER void CCamera::SetParametersForScriptInterpolation(float, float, int32) { EAXJMP(0x46FDE0); }
+#ifdef IMPROVED_CAMERA
+#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)
+#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k)
+#define CTRLJUSTDOWN(key) \
+ ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \
+ (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))
+#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))
+#endif
-bool
-CCamera::GetFading()
+void
+CCamera::Init(void)
{
- return m_bFading;
+ memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh?
+
+ m_pRwCamera = nil;
+ m_1rstPersonRunCloseToAWall = false;
+ m_fPositionAlongSpline = 0.0f;
+ m_bCameraJustRestored = false;
+ Cams[0].Init();
+ Cams[1].Init();
+ Cams[2].Init();
+ Cams[0].Mode = CCam::MODE_FOLLOWPED;
+ Cams[1].Mode = CCam::MODE_FOLLOWPED;
+ unknown = 0;
+ m_bJustJumpedOutOf1stPersonBecauseOfTarget = 0;
+ ClearPlayerWeaponMode();
+ m_bInATunnelAndABigVehicle = false;
+ m_iModeObbeCamIsInForCar = OBBE_INVALID;
+ Cams[0].CamTargetEntity = nil;
+ Cams[1].CamTargetEntity = nil;
+ Cams[2].CamTargetEntity = nil;
+ Cams[0].m_fCamBufferedHeight = 0.0f;
+ Cams[0].m_fCamBufferedHeightSpeed = 0.0f;
+ Cams[1].m_fCamBufferedHeight = 0.0f;
+ Cams[1].m_fCamBufferedHeightSpeed = 0.0f;
+ Cams[0].m_bCamLookingAtVector = false;
+ Cams[1].m_bCamLookingAtVector = false;
+ Cams[2].m_bCamLookingAtVector = false;
+ Cams[0].m_fPlayerVelocity = 0.0f;
+ Cams[1].m_fPlayerVelocity = 0.0f;
+ Cams[2].m_fPlayerVelocity = 0.0f;
+ m_bHeadBob = false;
+ m_fFractionInterToStopMovingTarget = 0.25f;
+ m_fFractionInterToStopCatchUpTarget = 0.75f;
+ m_fGaitSwayBuffer = 0.85f;
+ m_bScriptParametersSetForInterPol = false;
+ m_uiCamShakeStart = 0;
+ m_fCamShakeForce = 0.0f;
+ m_iModeObbeCamIsInForCar = OBBE_INVALID;
+ m_bIgnoreFadingStuffForMusic = false;
+ m_bWaitForInterpolToFinish = false;
+ pToGarageWeAreIn = nil;
+ pToGarageWeAreInForHackAvoidFirstPerson = nil;
+ m_bPlayerIsInGarage = false;
+ m_bJustCameOutOfGarage = false;
+ m_fNearClipScript = DEFAULT_NEAR;
+ m_bUseNearClipScript = false;
+ m_vecDoingSpecialInterPolation = false;
+ m_bAboveGroundTrainNodesLoaded = false;
+ m_bBelowGroundTrainNodesLoaded = false;
+ m_WideScreenOn = false;
+ m_fFOV_Wide_Screen = 0.0f;
+ m_bRestoreByJumpCut = false;
+ CarZoomIndicator = 2.0f;
+ PedZoomIndicator = 2.0f;
+ CarZoomValueSmooth = 0.0f;
+ m_fPedZoomValueSmooth = 0.0f;
+ pTargetEntity = nil;
+ if(FindPlayerVehicle())
+ pTargetEntity = FindPlayerVehicle();
+ else
+ pTargetEntity = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ m_bInitialNodeFound = false;
+ m_ScreenReductionPercentage = 0.0f;
+ m_ScreenReductionSpeed = 0.0f;
+ m_WideScreenOn = false;
+ m_bWantsToSwitchWidescreenOff = false;
+ WorldViewerBeingUsed = false;
+ PlayerExhaustion = 1.0f;
+ DebugCamMode = CCam::MODE_NONE;
+ m_PedOrientForBehindOrInFront = 0.0f;
+ if(!FrontEndMenuManager.m_bStartGameLoading){
+ m_bFading = false;
+ CDraw::FadeValue = 0;
+ m_fFLOATingFade = 0.0f;
+ m_bMusicFading = false;
+ m_fTimeToFadeMusic = 0.0f;
+ m_fFLOATingFadeMusic = 0.0f;
+ }
+ m_bMoveCamToAvoidGeom = false;
+ if(FrontEndMenuManager.m_bStartGameLoading)
+ m_bMoveCamToAvoidGeom = true;
+ m_bStartingSpline = false;
+ m_iTypeOfSwitch = INTERPOLATION;
+ m_bUseScriptZoomValuePed = false;
+ m_bUseScriptZoomValueCar = false;
+ m_fPedZoomValueScript = 0.0f;
+ m_fCarZoomValueScript = 0.0f;
+ m_bUseSpecialFovTrain = false;
+ m_fFovForTrain = 70.0f; // or DefaultFOV from Cam.cpp
+ m_iModeToGoTo = CCam::MODE_FOLLOWPED;
+ m_bJust_Switched = false;
+ m_bUseTransitionBeta = false;
+ m_matrix.SetScale(1.0f);
+ m_bTargetJustBeenOnTrain = false;
+ m_bInitialNoNodeStaticsSet = false;
+ m_uiLongestTimeInMill = 5000;
+ m_uiTimeLastChange = 0;
+ m_uiTimeWeEnteredIdle = 0;
+ m_bIdleOn = false;
+ LODDistMultiplier = 1.0f;
+ m_bCamDirectlyBehind = false;
+ m_bCamDirectlyInFront = false;
+ m_motionBlur = 0;
+ m_bGarageFixedCamPositionSet = false;
+ SetMotionBlur(255, 255, 255, 0, 0);
+ m_bCullZoneChecksOn = false;
+ m_bFailedCullZoneTestPreviously = false;
+ m_iCheckCullZoneThisNumFrames = 6;
+ m_iZoneCullFrameNumWereAt = 0;
+ m_CameraAverageSpeed = 0.0f;
+ m_CameraSpeedSoFar = 0.0f;
+ m_PreviousCameraPosition = CVector(0.0f, 0.0f, 0.0f);
+ m_iWorkOutSpeedThisNumFrames = 4;
+ m_iNumFramesSoFar = 0;
+ m_bJustInitalised = true;
+ m_uiTransitionState = 0;
+ m_uiTimeTransitionStart = 0;
+ m_bLookingAtPlayer = true;
+ m_fMouseAccelHorzntl = 0.0025f;
+ m_fMouseAccelVertical = 0.003f;
+ m_f3rdPersonCHairMultX = 0.53f;
+ m_f3rdPersonCHairMultY = 0.4f;
}
-int
-CCamera::GetFadingDirection()
+void
+CCamera::Process(void)
{
+ // static bool InterpolatorNotInitialised = true; // unused
+ static float PlayerMinDist = 1.6f; // not on PS2
+ static bool WasPreviouslyInterSyhonFollowPed = false; // only written
+ float FOV = 0.0f;
+ float oldBeta, newBeta;
+ float deltaBeta = 0.0f;
+ bool lookLRBVehicle = false;
+ CVector CamFront, CamUp, CamSource, Target;
+
+ m_bJust_Switched = false;
+ m_RealPreviousCameraPosition = GetPosition();
+
+ // Update target entity
+ if(m_bLookingAtPlayer || m_bTargetJustBeenOnTrain || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)
+ UpdateTargetEntity();
+ if(pTargetEntity == nil)
+ pTargetEntity = FindPlayerPed();
+ if(Cams[ActiveCam].CamTargetEntity == nil)
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ if(Cams[(ActiveCam+1)%2].CamTargetEntity == nil)
+ Cams[(ActiveCam+1)%2].CamTargetEntity = pTargetEntity;
+
+ CamControl();
if(m_bFading)
- return m_iFadingDirection == FADE_IN ? FADE_IN : FADE_OUT;
+ ProcessFade();
+ if(m_bMusicFading)
+ ProcessMusicFade();
+ if(m_WideScreenOn)
+ ProcessWideScreenOn();
+
+#ifdef IMPROVED_CAMERA
+ if(CPad::GetPad(1)->GetCircleJustDown() || CTRLJUSTDOWN('B')){
+#else
+ if(CPad::GetPad(1)->GetCircleJustDown()){
+#endif
+ WorldViewerBeingUsed = !WorldViewerBeingUsed;
+ if(WorldViewerBeingUsed)
+ InitialiseCameraForDebugMode();
+ else
+ CPad::m_bMapPadOneToPadTwo = false;
+ }
+
+ RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
+
+ if(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f)
+ oldBeta = 0.0f;
else
- return FADE_NONE;
-}
+ oldBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
-bool
-CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
-{
- RwV3d c;
- c = *(RwV3d*)&center;
- RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
- if(c.y + radius < CDraw::GetNearClipZ()) return false;
- if(c.y - radius > CDraw::GetFarClipZ()) return false;
- if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false;
- if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > radius) return false;
- if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > radius) return false;
- if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > radius) return false;
- return true;
+ Cams[ActiveCam].Process();
+ Cams[ActiveCam].ProcessSpecialHeightRoutines();
+
+ if(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f)
+ newBeta = 0.0f;
+ else
+ newBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+
+
+ // Stop transition when it's done
+ if(m_uiTransitionState != 0){
+/*
+ // PS2:
+ if(!m_bWaitForInterpolToFinish){
+ Cams[(ActiveCam+1)%2].Process();
+ Cams[(ActiveCam+1)%2].ProcessSpecialHeightRoutines();
+ }
+*/
+ // not PS2 (done in CamControl there it seems)
+ if(CTimer::GetTimeInMilliseconds() > m_uiTransitionDuration+m_uiTimeTransitionStart){
+ m_uiTransitionState = 0;
+ m_vecDoingSpecialInterPolation = false;
+ m_bWaitForInterpolToFinish = false;
+ }
+ }
+
+ if(m_bUseNearClipScript)
+ RwCameraSetNearClipPlane(Scene.camera, m_fNearClipScript);
+
+ deltaBeta = newBeta - oldBeta;
+ while(deltaBeta >= PI) deltaBeta -= 2*PI;
+ while(deltaBeta < -PI) deltaBeta += 2*PI;
+ if(Abs(deltaBeta) > 0.3f)
+ m_bJust_Switched = true;
+
+ // Debug stuff
+ if(!gbModelViewer)
+ Cams[ActiveCam].PrintMode();
+ if(WorldViewerBeingUsed)
+ Cams[2].Process();
+
+ if(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && pTargetEntity->IsVehicle())
+ lookLRBVehicle = true;
+
+ if(m_uiTransitionState != 0 && !lookLRBVehicle){
+ // Process transition
+ // different on PS2
+
+ uint32 currentTime = CTimer::GetTimeInMilliseconds() - m_uiTimeTransitionStart;
+ if(currentTime >= m_uiTransitionDuration)
+ currentTime = m_uiTransitionDuration;
+ float fractionInter = (float) currentTime / m_uiTransitionDuration;
+
+ if(fractionInter <= m_fFractionInterToStopMovingTarget){
+ float inter;
+ if(m_fFractionInterToStopMovingTarget == 0.0f)
+ inter = 0.0f;
+ else
+ inter = (m_fFractionInterToStopMovingTarget - fractionInter)/m_fFractionInterToStopMovingTarget;
+ inter = 0.5f - 0.5*Cos(inter*PI); // smooth it
+
+ m_vecSourceWhenInterPol = m_cvecStartingSourceForInterPol + inter*m_cvecSourceSpeedAtStartInter;
+ m_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol + inter*m_cvecTargetSpeedAtStartInter;
+ m_vecUpWhenInterPol = m_cvecStartingUpForInterPol + inter*m_cvecUpSpeedAtStartInter;
+ m_fFOVWhenInterPol = m_fStartingFOVForInterPol + inter*m_fFOVSpeedAtStartInter;
+
+ CamSource = m_vecSourceWhenInterPol;
+
+ if(m_bItsOkToLookJustAtThePlayer){
+ m_vecTargetWhenInterPol.x = FindPlayerPed()->GetPosition().x;
+ m_vecTargetWhenInterPol.y = FindPlayerPed()->GetPosition().y;
+ m_fBetaWhenInterPol = m_fStartingBetaForInterPol + inter*m_fBetaSpeedAtStartInter;
+
+ float dist = (CamSource - m_vecTargetWhenInterPol).Magnitude2D();
+ if(dist < PlayerMinDist){
+ if(dist > 0.0f){
+ CamSource.x = m_vecTargetWhenInterPol.x + PlayerMinDist*Cos(m_fBetaWhenInterPol);
+ CamSource.y = m_vecTargetWhenInterPol.y + PlayerMinDist*Sin(m_fBetaWhenInterPol);
+ }else{
+ // can only be 0.0 now...
+ float beta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+ CamSource.x = m_vecTargetWhenInterPol.x + PlayerMinDist*Cos(beta);
+ CamSource.y = m_vecTargetWhenInterPol.y + PlayerMinDist*Sin(beta);
+ }
+ }else{
+ CamSource.x = m_vecTargetWhenInterPol.x + dist*Cos(m_fBetaWhenInterPol);
+ CamSource.y = m_vecTargetWhenInterPol.y + dist*Sin(m_fBetaWhenInterPol);
+ }
+ }
+
+ CamFront = m_vecTargetWhenInterPol - CamSource;
+ StoreValuesDuringInterPol(CamSource, m_vecTargetWhenInterPol, m_vecUpWhenInterPol, m_fFOVWhenInterPol);
+ Target = m_vecTargetWhenInterPol;
+ CamFront.Normalise();
+ if(m_bLookingAtPlayer)
+ CamUp = CVector(0.0f, 0.0f, 1.0f);
+ else
+ CamUp = m_vecUpWhenInterPol;
+ CamUp.Normalise();
+
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
+ CamFront.Normalise();
+ CamUp = CrossProduct(CamFront, CVector(-1.0f, 0.0f, 0.0f));
+ }else{
+ CamFront.Normalise();
+ CamUp.Normalise();
+ CVector right = CrossProduct(CamFront, CamUp);
+ right.Normalise();
+ CamUp = CrossProduct(right, CamFront);
+ }
+ CamUp.Normalise();
+ FOV = m_fFOVWhenInterPol;
+ }else if(fractionInter > m_fFractionInterToStopMovingTarget && fractionInter <= 1.0f){
+ float inter;
+ if(m_fFractionInterToStopCatchUpTarget == 0.0f)
+ inter = 0.0f;
+ else
+ inter = (fractionInter - m_fFractionInterToStopMovingTarget)/m_fFractionInterToStopCatchUpTarget;
+ inter = 0.5f - 0.5*Cos(inter*PI); // smooth it
+
+ CamSource = m_vecSourceWhenInterPol + inter*(Cams[ActiveCam].Source - m_vecSourceWhenInterPol);
+ FOV = m_fFOVWhenInterPol + inter*(Cams[ActiveCam].FOV - m_fFOVWhenInterPol);
+ Target = m_vecTargetWhenInterPol + inter*(Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - m_vecTargetWhenInterPol);
+ CamUp = m_vecUpWhenInterPol + inter*(Cams[ActiveCam].Up - m_vecUpWhenInterPol);
+ deltaBeta = Cams[ActiveCam].m_fTrueBeta - m_fBetaWhenInterPol;
+ MakeAngleLessThan180(deltaBeta);
+ float interpBeta = m_fBetaWhenInterPol + inter*deltaBeta;
+
+ if(m_bItsOkToLookJustAtThePlayer){
+ Target.x = FindPlayerPed()->GetPosition().x;
+ Target.y = FindPlayerPed()->GetPosition().y;
+
+ float dist = (CamSource - Target).Magnitude2D();
+ if(dist < PlayerMinDist){
+ if(dist > 0.0f){
+ CamSource.x = Target.x + PlayerMinDist*Cos(interpBeta);
+ CamSource.y = Target.y + PlayerMinDist*Sin(interpBeta);
+ }else{
+ // can only be 0.0 now...
+ float beta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+ CamSource.x = Target.x + PlayerMinDist*Cos(beta);
+ CamSource.y = Target.y + PlayerMinDist*Sin(beta);
+ }
+ }else{
+ CamSource.x = Target.x + dist*Cos(interpBeta);
+ CamSource.y = Target.y + dist*Sin(interpBeta);
+ }
+ }
+
+ CamFront = Target - CamSource;
+ StoreValuesDuringInterPol(CamSource, Target, CamUp, FOV);
+ CamFront.Normalise();
+ if(m_bLookingAtPlayer)
+ CamUp = CVector(0.0f, 0.0f, 1.0f);
+
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
+ CamFront.Normalise();
+ CamUp = CrossProduct(CamFront, CVector(-1.0f, 0.0f, 0.0f));
+ }else{
+ CamFront.Normalise();
+ CamUp.Normalise();
+ CVector right = CrossProduct(CamFront, CamUp);
+ right.Normalise();
+ CamUp = CrossProduct(right, CamFront);
+ }
+ CamUp.Normalise();
+#ifndef FIX_BUGS
+ // BUG: FOV was already interpolated but m_fFOVWhenInterPol was not
+ FOV = m_fFOVWhenInterPol;
+#endif
+ }
+
+ CVector Dist = CamSource - Target;
+ float DistOnGround = Dist.Magnitude2D();
+ float Alpha = CGeneral::GetATanOfXY(DistOnGround, Dist.z);
+ float Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
+ Cams[ActiveCam].KeepTrackOfTheSpeed(CamSource, Target, CamUp, Alpha, Beta, FOV);
+ }else{
+ // No transition, take Cam values directly
+ if(WorldViewerBeingUsed){
+ CamSource = Cams[2].Source;
+ CamFront = Cams[2].Front;
+ CamUp = Cams[2].Up;
+ FOV = Cams[2].FOV;
+ }else{
+ CamSource = Cams[ActiveCam].Source;
+ CamFront = Cams[ActiveCam].Front;
+ CamUp = Cams[ActiveCam].Up;
+ FOV = Cams[ActiveCam].FOV;
+ }
+ WasPreviouslyInterSyhonFollowPed = false; // unused
+ }
+
+ if(m_uiTransitionState != 0)
+ if(!m_bLookingAtVector && m_bLookingAtPlayer && !CCullZones::CamStairsForPlayer() && !m_bPlayerIsInGarage){
+ CEntity *entity = nil;
+ CColPoint colPoint;
+ if(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), CamSource, colPoint, entity, true, false, false, true, false, true, true)){
+ CamSource = colPoint.point;
+ RwCameraSetNearClipPlane(Scene.camera, 0.05f);
+ }
+ }
+
+ GetRight() = CrossProduct(CamUp, CamFront); // actually Left
+ GetForward() = CamFront;
+ GetUp() = CamUp;
+ GetPosition() = CamSource;
+
+ // Process Shake
+ float shakeStrength = m_fCamShakeForce - 0.28f*(CTimer::GetTimeInMilliseconds()-m_uiCamShakeStart)/1000.0f;
+ shakeStrength = clamp(shakeStrength, 0.0f, 2.0f);
+ int shakeRand = CGeneral::GetRandomNumber();
+ float shakeOffset = shakeStrength*0.1f;
+ GetPosition().x += shakeOffset*((shakeRand&0xF)-7);
+ GetPosition().y += shakeOffset*(((shakeRand&0xF0)>>4)-7);
+ GetPosition().z += shakeOffset*(((shakeRand&0xF00)>>8)-7);
+
+ if(shakeOffset > 0.0f && m_BlurType != MBLUR_SNIPER)
+ SetMotionBlurAlpha(min((int)(shakeStrength*255.0f) + 25, 150));
+ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && FindPlayerVehicle() && FindPlayerVehicle()->GetUp().z < 0.2f)
+ SetMotionBlur(230, 230, 230, 215, MBLUR_NORMAL);
+
+ CalculateDerivedValues();
+ CDraw::SetFOV(FOV);
+
+ // Set RW camera
+ if(WorldViewerBeingUsed){
+ RwFrame *frame = RwCameraGetFrame(m_pRwCamera);
+ CVector Source = Cams[2].Source;
+ CVector Front = Cams[2].Front;
+ CVector Up = Cams[2].Up;
+
+ GetRight() = CrossProduct(Up, Front);
+ GetForward() = Front;
+ GetUp() = Up;
+ GetPosition() = Source;
+
+ CDraw::SetFOV(Cams[2].FOV);
+ m_vecGameCamPos = Cams[ActiveCam].Source;
+
+ *RwMatrixGetPos(RwFrameGetMatrix(frame)) = (RwV3d)GetPosition();
+ *RwMatrixGetAt(RwFrameGetMatrix(frame)) = (RwV3d)GetForward();
+ *RwMatrixGetUp(RwFrameGetMatrix(frame)) = (RwV3d)GetUp();
+ *RwMatrixGetRight(RwFrameGetMatrix(frame)) = (RwV3d)GetRight();
+ RwMatrixUpdate(RwFrameGetMatrix(frame));
+ RwFrameUpdateObjects(frame);
+ }else{
+ RwFrame *frame = RwCameraGetFrame(m_pRwCamera);
+ m_vecGameCamPos = GetPosition();
+ *RwMatrixGetPos(RwFrameGetMatrix(frame)) = (RwV3d)GetPosition();
+ *RwMatrixGetAt(RwFrameGetMatrix(frame)) = (RwV3d)GetForward();
+ *RwMatrixGetUp(RwFrameGetMatrix(frame)) = (RwV3d)GetUp();
+ *RwMatrixGetRight(RwFrameGetMatrix(frame)) = (RwV3d)GetRight();
+ RwMatrixUpdate(RwFrameGetMatrix(frame));
+ RwFrameUpdateObjects(frame);
+ }
+
+ CDraw::SetNearClipZ(RwCameraGetNearClipPlane(m_pRwCamera));
+ CDraw::SetFarClipZ(RwCameraGetFarClipPlane(m_pRwCamera));
+
+ UpdateSoundDistances();
+
+ if((CTimer::GetFrameCounter()&0xF) == 3)
+ DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y);
+
+ // LOD dist
+ if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier())
+ LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f);
+ else
+ LODDistMultiplier = 1.0f;
+ GenerationDistMultiplier = LODDistMultiplier;
+ LODDistMultiplier *= CRenderer::ms_lodDistScale;
+
+ // Keep track of speed
+ if(m_bJustInitalised || m_bJust_Switched){
+ m_PreviousCameraPosition = GetPosition();
+ m_bJustInitalised = false;
+ }
+ m_CameraSpeedSoFar += (GetPosition() - m_PreviousCameraPosition).Magnitude();
+ m_iNumFramesSoFar++;
+ if(m_iNumFramesSoFar == m_iWorkOutSpeedThisNumFrames){
+ m_CameraAverageSpeed = m_CameraSpeedSoFar / m_iWorkOutSpeedThisNumFrames;
+ m_CameraSpeedSoFar = 0.0f;
+ m_iNumFramesSoFar = 0;
+ }
+ m_PreviousCameraPosition = GetPosition();
+
+ // PS2: something doing on with forward vector here
+
+ if(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED){
+ Cams[ActiveCam].Source = Cams[ActiveCam].SourceBeforeLookBehind;
+ Orientation += PI;
+ }
+
+ if(m_uiTransitionState != 0){
+ int OtherCam = (ActiveCam+1)%2;
+ if(Cams[OtherCam].CamTargetEntity &&
+ pTargetEntity && pTargetEntity->IsPed() &&
+ !Cams[OtherCam].CamTargetEntity->IsVehicle() &&
+ Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD){
+ Cams[OtherCam].Source = Cams[ActiveCam%2].SourceBeforeLookBehind;
+ Orientation += PI;
+ }
+ }
+
+ m_bCameraJustRestored = false;
}
-bool
-CCamera::IsSphereVisible(const CVector &center, float radius)
+void
+CCamera::CamControl(void)
{
- CMatrix mat = m_cameraMatrix;
- return IsSphereVisible(center, radius, &mat);
+ static bool PlaceForFixedWhenSniperFound = false;
+ static int16 ReqMode;
+ bool disableGarageCam = false;
+ bool switchByJumpCut = false;
+ bool stairs = false;
+ bool boatTarget = false;
+ CVector targetPos;
+ CVector garageCenter, garageDoorPos1, garageDoorPos2;
+ CVector garageCenterToDoor, garageCamPos;
+ int whichDoor;
+
+ m_bObbeCinematicPedCamOn = false;
+ m_bObbeCinematicCarCamOn = false;
+ m_bUseTransitionBeta = false;
+ m_bUseSpecialFovTrain = false;
+ m_bJustCameOutOfGarage = false;
+ m_bTargetJustCameOffTrain = false;
+ m_bInATunnelAndABigVehicle = false;
+
+ if(Cams[ActiveCam].CamTargetEntity == nil && pTargetEntity == nil)
+ pTargetEntity = PLAYER;
+
+ m_iZoneCullFrameNumWereAt++;
+ if(m_iZoneCullFrameNumWereAt > m_iCheckCullZoneThisNumFrames)
+ m_iZoneCullFrameNumWereAt = 1;
+ m_bCullZoneChecksOn = m_iZoneCullFrameNumWereAt == m_iCheckCullZoneThisNumFrames;
+ if(m_bCullZoneChecksOn)
+ m_bFailedCullZoneTestPreviously = CCullZones::CamCloseInForPlayer();
+
+ if(m_bLookingAtPlayer){
+ CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_1;
+ FindPlayerPed()->bIsVisible = true;
+ }
+
+ if(!CTimer::GetIsPaused()){
+ float CloseInCarHeightTarget = 0.0f;
+ float CloseInPedHeightTarget = 0.0f;
+
+ if(m_bTargetJustBeenOnTrain){
+ // Getting off train
+ if(!pTargetEntity->IsVehicle() || !((CVehicle*)pTargetEntity)->IsTrain()){
+ Restore();
+ m_bTargetJustCameOffTrain = true;
+ m_bTargetJustBeenOnTrain = false;
+ SetWideScreenOff();
+ }
+ }
+
+ // Vehicle target
+ if(pTargetEntity->IsVehicle()){
+ if(((CVehicle*)pTargetEntity)->IsTrain()){
+ if(!m_bTargetJustBeenOnTrain){
+ m_bInitialNodeFound = false;
+ m_bInitialNoNodeStaticsSet = false;
+ }
+ Process_Train_Camera_Control();
+ }else{
+ if(((CVehicle*)pTargetEntity)->IsBoat())
+ boatTarget = true;
+
+ // Change user selected mode
+ if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() &&
+ (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
+ !m_WideScreenOn)
+ CarZoomIndicator -= 1.0f;
+ if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&
+ (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
+ !m_WideScreenOn)
+ CarZoomIndicator += 1.0f;
+ if(!m_bFailedCullZoneTestPreviously){
+ if(CarZoomIndicator < CAM_ZOOM_1STPRS) CarZoomIndicator = CAM_ZOOM_CINEMATIC;
+ else if(CarZoomIndicator > CAM_ZOOM_CINEMATIC) CarZoomIndicator = CAM_ZOOM_1STPRS;
+ }
+
+ if(m_bFailedCullZoneTestPreviously)
+ if(CarZoomIndicator != CAM_ZOOM_1STPRS && CarZoomIndicator != CAM_ZOOM_TOPDOWN)
+ ReqMode = CCam::MODE_CAM_ON_A_STRING;
+
+ switch(((CVehicle*)pTargetEntity)->m_vehType){
+ case VEHICLE_TYPE_CAR:
+ case VEHICLE_TYPE_BIKE:
+ if(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition())){
+ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer ||
+ WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){
+ if(pToGarageWeAreIn){
+ float ground;
+ bool foundGround;
+
+ // This is all very strange....
+ // targetPos = pTargetEntity->GetPosition(); // unused
+ if(pToGarageWeAreIn->m_pDoor1){
+ whichDoor = 1;
+ garageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X;
+ garageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y;
+ garageDoorPos1.z = 0.0f;
+ // targetPos.z = 0.0f; // unused
+ // (targetPos - doorPos1).Magnitude(); // unused
+ }else if(pToGarageWeAreIn->m_pDoor2){
+ whichDoor = 2;
+#ifdef FIX_BUGS
+ garageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X;
+ garageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y;
+ garageDoorPos2.z = 0.0f;
+#endif
+ }else{
+ whichDoor = 1;
+ garageDoorPos1.x = pTargetEntity->GetPosition().x;
+ garageDoorPos1.y = pTargetEntity->GetPosition().y;
+#ifdef FIX_BUGS
+ garageDoorPos1.z = 0.0f;
+#else
+ garageDoorPos2.z = 0.0f;
+#endif
+ }
+ garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f;
+ garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f;
+ garageCenter.z = 0.0f;
+ if(whichDoor == 1)
+ garageCenterToDoor = garageDoorPos1 - garageCenter;
+ else
+ garageCenterToDoor = garageDoorPos2 - garageCenter;
+ targetPos = pTargetEntity->GetPosition();
+ ground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround);
+ if(!foundGround)
+ ground = targetPos.z - 0.2f;
+ garageCenterToDoor.z = 0.0f;
+ garageCenterToDoor.Normalise();
+ if(whichDoor == 1)
+ garageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor;
+ else
+ garageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor;
+ garageCamPos.z = ground + 3.1f;
+ SetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f));
+ m_bGarageFixedCamPositionSet = true;
+ }
+ }
+
+ if(CGarages::CameraShouldBeOutside() && m_bGarageFixedCamPositionSet &&
+ (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)){
+ if(pToGarageWeAreIn){
+ ReqMode = CCam::MODE_FIXED;
+ m_bPlayerIsInGarage = true;
+ }
+ }else{
+ if(m_bPlayerIsInGarage){
+ m_bJustCameOutOfGarage = true;
+ m_bPlayerIsInGarage = false;
+ }
+ ReqMode = CCam::MODE_CAM_ON_A_STRING;
+ }
+ }else{
+ if(m_bPlayerIsInGarage){
+ m_bJustCameOutOfGarage = true;
+ m_bPlayerIsInGarage = false;
+ }
+ m_bGarageFixedCamPositionSet = false;
+ ReqMode = CCam::MODE_CAM_ON_A_STRING;
+ }
+ break;
+ case VEHICLE_TYPE_BOAT:
+ ReqMode = CCam::MODE_BEHINDBOAT;
+ break;
+ }
+
+ // Car zoom value
+ if(CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage){
+ CarZoomValue = 0.0f;
+ ReqMode = CCam::MODE_1STPERSON;
+ }else if(CarZoomIndicator == CAM_ZOOM_1)
+ CarZoomValue = 0.05f;
+ else if(CarZoomIndicator == CAM_ZOOM_2)
+ CarZoomValue = 1.9f;
+ else if(CarZoomIndicator == CAM_ZOOM_3)
+ CarZoomValue = 3.9f;
+ if(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){
+ CarZoomValue = 1.0f;
+ ReqMode = CCam::MODE_TOPDOWN;
+ }
+
+ // Check if we have to go into first person
+ if(((CVehicle*)pTargetEntity)->IsCar() && !m_bPlayerIsInGarage){
+ if(CCullZones::Cam1stPersonForPlayer() &&
+ pTargetEntity->GetColModel()->boundingBox.GetSize().z >= 3.026f &&
+ pToGarageWeAreInForHackAvoidFirstPerson == nil){
+ ReqMode = CCam::MODE_1STPERSON;
+ m_bInATunnelAndABigVehicle = true;
+ }
+ }
+ if(ReqMode == CCam::MODE_TOPDOWN &&
+ (CCullZones::Cam1stPersonForPlayer() || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()))
+ ReqMode = CCam::MODE_1STPERSON;
+
+ // Smooth zoom value - ugly code
+ if(m_bUseScriptZoomValueCar){
+ if(CarZoomValueSmooth < m_fCarZoomValueScript){
+ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = min(CarZoomValueSmooth, m_fCarZoomValueScript);
+ }else{
+ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = max(CarZoomValueSmooth, m_fCarZoomValueScript);
+ }
+ }else if(m_bFailedCullZoneTestPreviously){
+ CloseInCarHeightTarget = 0.65f;
+ if(CarZoomValueSmooth < -0.65f){
+ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = min(CarZoomValueSmooth, -0.65f);
+ }else{
+ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = max(CarZoomValueSmooth, -0.65f);
+ }
+ }else{
+ if(CarZoomValueSmooth < CarZoomValue){
+ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = min(CarZoomValueSmooth, CarZoomValue);
+ }else{
+ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ CarZoomValueSmooth = max(CarZoomValueSmooth, CarZoomValue);
+ }
+ }
+
+ WellBufferMe(CloseInCarHeightTarget, &Cams[ActiveCam].m_fCloseInCarHeightOffset, &Cams[ActiveCam].m_fCloseInCarHeightOffsetSpeed, 0.1f, 0.25f, false);
+
+ // Fallen into water
+ if(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) && !boatTarget &&
+ !Cams[ActiveCam].CamTargetEntity->IsPed())
+ ReqMode = CCam::MODE_PLAYER_FALLEN_WATER;
+ }
+ }
+
+ // Ped target
+ else if(pTargetEntity->IsPed()){
+ // Change user selected mode
+ if(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() &&
+ (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
+ !m_WideScreenOn && !m_bFailedCullZoneTestPreviously){
+ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){
+ if(PedZoomIndicator == CAM_ZOOM_TOPDOWN)
+ PedZoomIndicator = CAM_ZOOM_1;
+ else
+ PedZoomIndicator = CAM_ZOOM_TOPDOWN;
+ }else
+ PedZoomIndicator -= 1.0f;
+ }
+ if(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&
+ (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
+ !m_WideScreenOn && !m_bFailedCullZoneTestPreviously){
+ if(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){
+ if(PedZoomIndicator == CAM_ZOOM_TOPDOWN)
+ PedZoomIndicator = CAM_ZOOM_1;
+ else
+ PedZoomIndicator = CAM_ZOOM_TOPDOWN;
+ }else
+ PedZoomIndicator += 1.0f;
+ }
+ // disabled obbe's cam here
+ if(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_TOPDOWN;
+ else if(PedZoomIndicator > CAM_ZOOM_TOPDOWN) PedZoomIndicator = CAM_ZOOM_1;
+
+ ReqMode = CCam::MODE_FOLLOWPED;
+
+ // Check 1st person mode
+ if(m_bLookingAtPlayer && pTargetEntity->IsPed() && !m_WideScreenOn && !Cams[0].Using3rdPersonMouseCam()
+#ifdef FREE_CAM
+ && !CCamera::bFreeCam
+#endif
+ ){
+ // See if we want to enter first person mode
+ if(CPad::GetPad(0)->LookAroundLeftRight() || CPad::GetPad(0)->LookAroundUpDown()){
+ m_uiFirstPersonCamLastInputTime = CTimer::GetTimeInMilliseconds();
+ m_bFirstPersonBeingUsed = true;
+ }else if(m_bFirstPersonBeingUsed){
+ // Or if we want to go back to 3rd person
+ if(CPad::GetPad(0)->GetPedWalkLeftRight() || CPad::GetPad(0)->GetPedWalkUpDown() ||
+ CPad::GetPad(0)->GetSquare() || CPad::GetPad(0)->GetTriangle() ||
+ CPad::GetPad(0)->GetCross() || CPad::GetPad(0)->GetCircle() ||
+ CTimer::GetTimeInMilliseconds() - m_uiFirstPersonCamLastInputTime > 2850.0f)
+ m_bFirstPersonBeingUsed = false;
+ }
+ }else
+ m_bFirstPersonBeingUsed = false;
+
+ if(!FindPlayerPed()->IsPedInControl() || FindPlayerPed()->m_fMoveSpeed > 0.0f)
+ m_bFirstPersonBeingUsed = false;
+ if(m_bFirstPersonBeingUsed){
+ ReqMode = CCam::MODE_1STPERSON;
+ CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_1;
+ }
+
+ // Zoom value
+ if(PedZoomIndicator == CAM_ZOOM_1)
+ m_fPedZoomValue = 0.25f;
+ else if(PedZoomIndicator == CAM_ZOOM_2)
+ m_fPedZoomValue = 1.5f;
+ else if(PedZoomIndicator == CAM_ZOOM_3)
+ m_fPedZoomValue = 2.9f;
+
+ // Smooth zoom value - ugly code
+ if(m_bUseScriptZoomValuePed){
+ if(m_fPedZoomValueSmooth < m_fPedZoomValueScript){
+ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, m_fPedZoomValueScript);
+ }else{
+ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, m_fPedZoomValueScript);
+ }
+ }else if(m_bFailedCullZoneTestPreviously){
+ static float PedZoomedInVal = 0.5f;
+ CloseInPedHeightTarget = 0.7f;
+ if(m_fPedZoomValueSmooth < PedZoomedInVal){
+ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, PedZoomedInVal);
+ }else{
+ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, PedZoomedInVal);
+ }
+ }else{
+ if(m_fPedZoomValueSmooth < m_fPedZoomValue){
+ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, m_fPedZoomValue);
+ }else{
+ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();
+ m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, m_fPedZoomValue);
+ }
+ }
+
+ WellBufferMe(CloseInPedHeightTarget, &Cams[ActiveCam].m_fCloseInPedHeightOffset, &Cams[ActiveCam].m_fCloseInPedHeightOffsetSpeed, 0.1f, 0.025f, false);
+
+ // Check if entering fight cam
+ if(!m_bFirstPersonBeingUsed){
+ if(FindPlayerPed()->GetPedState() == PED_FIGHT && !m_bUseMouse3rdPerson)
+ ReqMode = CCam::MODE_FIGHT_CAM;
+ if(((CPed*)pTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&
+ FindPlayerPed()->GetPedState() == PED_ATTACK && !m_bUseMouse3rdPerson)
+ ReqMode = CCam::MODE_FIGHT_CAM;
+ }
+
+ // Garage cam
+ if(CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer())
+ stairs = true;
+ // Some hack for Mr Whoopee in a bomb shop
+ if(Cams[ActiveCam].Using3rdPersonMouseCam() && CCollision::ms_collisionInMemory == LEVEL_COMMERCIAL){
+ if(pTargetEntity->GetPosition().x < 83.0f && pTargetEntity->GetPosition().x > 18.0f &&
+ pTargetEntity->GetPosition().y < -305.0f && pTargetEntity->GetPosition().y > -390.0f)
+ disableGarageCam = true;
+ }
+ if(!disableGarageCam && (CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs)){
+ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){
+ if(pToGarageWeAreIn || stairs){
+ float ground;
+ bool foundGround;
+
+ if(pToGarageWeAreIn){
+ // targetPos = pTargetEntity->GetPosition(); // unused
+ if(pToGarageWeAreIn->m_pDoor1){
+ whichDoor = 1;
+ garageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X;
+ garageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y;
+ garageDoorPos1.z = 0.0f;
+ // targetPos.z = 0.0f; // unused
+ // (targetPos - doorPos1).Magnitude(); // unused
+ }else if(pToGarageWeAreIn->m_pDoor2){
+ whichDoor = 2;
+#ifdef FIX_BUGS
+ garageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X;
+ garageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y;
+ garageDoorPos2.z = 0.0f;
+#endif
+ }else{
+ whichDoor = 1;
+ garageDoorPos1.x = pTargetEntity->GetPosition().x;
+ garageDoorPos1.y = pTargetEntity->GetPosition().y;
+#ifdef FIX_BUGS
+ garageDoorPos1.z = 0.0f;
+#else
+ garageDoorPos2.z = 0.0f;
+#endif
+ }
+ }else{
+ whichDoor = 1;
+ garageDoorPos1 = Cams[ActiveCam].Source;
+ }
+
+ if(pToGarageWeAreIn){
+ garageCenter.x = (pToGarageWeAreIn->m_fX1 + pToGarageWeAreIn->m_fX2)/2.0f;
+ garageCenter.y = (pToGarageWeAreIn->m_fY1 + pToGarageWeAreIn->m_fY2)/2.0f;
+ garageCenter.z = 0.0f;
+ }else{
+ garageDoorPos1.z = 0.0f;
+ if(stairs){
+ CAttributeZone *az = CCullZones::FindZoneWithStairsAttributeForPlayer();
+ garageCenter.x = (az->minx + az->maxx)/2.0f;
+ garageCenter.y = (az->miny + az->maxy)/2.0f;
+ garageCenter.z = 0.0f;
+ }else
+ garageCenter = pTargetEntity->GetPosition();
+ }
+ if(whichDoor == 1)
+ garageCenterToDoor = garageDoorPos1 - garageCenter;
+ else
+ garageCenterToDoor = garageDoorPos2 - garageCenter;
+ targetPos = pTargetEntity->GetPosition();
+ ground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround);
+ if(!foundGround)
+ ground = targetPos.z - 0.2f;
+ garageCenterToDoor.z = 0.0f;
+ garageCenterToDoor.Normalise();
+ if(whichDoor == 1){
+ if(pToGarageWeAreIn == nil && stairs)
+ garageCamPos = garageDoorPos1 + 3.75f*garageCenterToDoor;
+ else
+ garageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor;
+ }else{
+ garageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor;
+ }
+ if(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !stairs){
+ garageCamPos = garageCenter;
+ garageCamPos.z += FindPlayerPed()->GetPosition().z + 2.1f;
+ if(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fX2) // What?
+ garageCamPos.z = pToGarageWeAreIn->m_fX2;
+ }else
+ garageCamPos.z = ground + 3.1f;
+ SetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f));
+ m_bGarageFixedCamPositionSet = true;
+ }
+ }
+
+ if((CGarages::CameraShouldBeOutside() || stairs) && m_bLookingAtPlayer && m_bGarageFixedCamPositionSet){
+ if(pToGarageWeAreIn || stairs){
+ ReqMode = CCam::MODE_FIXED;
+ m_bPlayerIsInGarage = true;
+ }
+ }else{
+ if(m_bPlayerIsInGarage){
+ m_bJustCameOutOfGarage = true;
+ m_bPlayerIsInGarage = false;
+ }
+ ReqMode = CCam::MODE_FOLLOWPED;
+ }
+ }else{
+ if(m_bPlayerIsInGarage){
+ m_bJustCameOutOfGarage = true;
+ m_bPlayerIsInGarage = false;
+ }
+ m_bGarageFixedCamPositionSet = false;
+ }
+
+ // Fallen into water
+ if(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) &&
+ Cams[ActiveCam].CamTargetEntity->IsPed())
+ ReqMode = CCam::MODE_PLAYER_FALLEN_WATER;
+
+ // Set top down
+ if(PedZoomIndicator == CAM_ZOOM_TOPDOWN &&
+ !CCullZones::Cam1stPersonForPlayer() &&
+ !CCullZones::CamNoRain() &&
+ !CCullZones::PlayerNoRain() &&
+ !m_bFirstPersonBeingUsed &&
+ !m_bPlayerIsInGarage)
+ ReqMode = CCam::MODE_TOP_DOWN_PED;
+
+ // Weapon mode
+ if(!CPad::GetPad(0)->GetTarget() && PlayerWeaponMode.Mode != CCam::MODE_HELICANNON_1STPERSON)
+ ClearPlayerWeaponMode();
+ if(m_PlayerMode.Mode != CCam::MODE_NONE)
+ ReqMode = m_PlayerMode.Mode;
+ if(PlayerWeaponMode.Mode != CCam::MODE_NONE && !stairs){
+ if(PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
+ PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER ||
+ PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ||
+ PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON ||
+ Cams[ActiveCam].GetWeaponFirstPersonOn()){
+ // First person weapon mode
+ if(PLAYER->GetPedState() == PED_SEEK_CAR){
+ if(ReqMode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].GetWeaponFirstPersonOn())
+ ReqMode = PlayerWeaponMode.Mode;
+ else
+ ReqMode = CCam::MODE_FOLLOWPED;
+ }else
+ ReqMode = PlayerWeaponMode.Mode;
+ }else if(ReqMode != CCam::MODE_TOP_DOWN_PED){
+ // Syphon mode
+ float playerTargetDist;
+ float deadPedDist = 4.0f;
+ static float alivePedDist = 2.0f; // original name lost
+ float pedDist; // actually only used on dead target
+ bool targetDead = false;
+ float camAngle, targetAngle;
+ CVector playerToTarget = m_cvecAimingTargetCoors - pTargetEntity->GetPosition();
+ CVector playerToCam = Cams[ActiveCam].Source - pTargetEntity->GetPosition();
+
+ if(PedZoomIndicator == CAM_ZOOM_1)
+ deadPedDist = 2.25f;
+ if(FindPlayerPed()->m_pPointGunAt){
+ // BUG: this need not be a ped!
+ if(((CPed*)FindPlayerPed()->m_pPointGunAt)->DyingOrDead()){
+ targetDead = true;
+ pedDist = deadPedDist;
+ }else
+ pedDist = alivePedDist;
+ playerTargetDist = playerToTarget.Magnitude2D();
+ camAngle = CGeneral::GetATanOfXY(playerToCam.x, playerToCam.y);
+ targetAngle = CGeneral::GetATanOfXY(playerToTarget.x, playerToTarget.y);
+ ReqMode = PlayerWeaponMode.Mode;
+
+ // Check whether to start aiming in crim-in-front mode
+ if(Cams[ActiveCam].Mode != CCam::MODE_SYPHON){
+ float angleDiff = camAngle - targetAngle;
+ while(angleDiff >= PI) angleDiff -= 2*PI;
+ while(angleDiff < -PI) angleDiff += 2*PI;
+ if(Abs(angleDiff) < HALFPI && playerTargetDist < 3.5f && playerToTarget.z > -1.0f)
+ ReqMode = CCam::MODE_SYPHON_CRIM_IN_FRONT;
+ }
+
+ // Check whether to go to special fixed mode
+ float fixedModeDist = 0.0f;
+ if((ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SYPHON) &&
+ (m_uiTransitionState == 0 || Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) &&
+ playerTargetDist < pedDist && targetDead){
+ if(ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT)
+ fixedModeDist = 5.0f;
+ else
+ fixedModeDist = 3.0f;
+ ReqMode = CCam::MODE_SPECIAL_FIXED_FOR_SYPHON;
+ }
+ if(ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){
+ if(!PlaceForFixedWhenSniperFound){
+ // Find position
+ CEntity *entity;
+ CColPoint colPoint;
+ CVector fixedPos = pTargetEntity->GetPosition();
+ fixedPos.x += fixedModeDist*Cos(camAngle);
+ fixedPos.y += fixedModeDist*Sin(camAngle);
+ fixedPos.z += 1.15f;
+ if(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), fixedPos, colPoint, entity, true, false, false, true, false, true, true))
+ SetCamPositionForFixedMode(colPoint.point, CVector(0.0f, 0.0f, 0.0f));
+ else
+ SetCamPositionForFixedMode(fixedPos, CVector(0.0f, 0.0f, 0.0f));
+ PlaceForFixedWhenSniperFound = true;
+ }
+ }else
+ PlaceForFixedWhenSniperFound = false;
+ }
+ }
+ }
+ }
+ }
+
+ m_bIdleOn = false;
+
+ if(DebugCamMode)
+ ReqMode = DebugCamMode;
+
+
+ // Process arrested player
+ static int ThePickedArrestMode;
+ static int LastPedState;
+ bool startArrestCam = false;
+
+ if(LastPedState != PED_ARRESTED && PLAYER->GetPedState() == PED_ARRESTED){
+ if(CarZoomIndicator != CAM_ZOOM_1STPRS && pTargetEntity->IsVehicle())
+ startArrestCam = true;
+ }else
+ startArrestCam = false;
+ LastPedState = PLAYER->GetPedState();
+ if(startArrestCam){
+ if(m_uiTransitionState)
+ ReqMode = Cams[ActiveCam].Mode;
+ else{
+ bool valid;
+ if(pTargetEntity->IsPed()){
+ // How can this happen if arrest cam is only done in cars?
+ Cams[(ActiveCam+1)%2].ResetStatics = true;
+ valid = Cams[(ActiveCam+1)%2].ProcessArrestCamOne();
+ ReqMode = CCam::MODE_ARRESTCAM_ONE;
+ }else{
+ Cams[(ActiveCam+1)%2].ResetStatics = true;
+ valid = Cams[(ActiveCam+1)%2].ProcessArrestCamTwo();
+ ReqMode = CCam::MODE_ARRESTCAM_TWO;
+ }
+ if(!valid)
+ ReqMode = Cams[ActiveCam].Mode;
+ }
+ }
+ ThePickedArrestMode = ReqMode;
+ if(PLAYER->GetPedState() == PED_ARRESTED)
+ ReqMode = ThePickedArrestMode; // this is rather useless...
+
+ // Process dead player
+ if(PLAYER->GetPedState() == PED_DEAD){
+ if(Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)
+ ReqMode = CCam::MODE_PED_DEAD_BABY;
+ else{
+ bool foundRoof;
+ CVector pos = FindPlayerPed()->GetPosition();
+ CWorld::FindRoofZFor3DCoord(pos.x, pos.y, pos.z, &foundRoof);
+ if(!foundRoof)
+ ReqMode = CCam::MODE_PED_DEAD_BABY;
+ }
+ }
+
+ // Restore with a jump cut
+ if(m_bRestoreByJumpCut){
+ if(ReqMode != CCam::MODE_FOLLOWPED &&
+ ReqMode != CCam::MODE_M16_1STPERSON &&
+ ReqMode != CCam::MODE_SNIPER &&
+ ReqMode != CCam::MODE_ROCKETLAUNCHER ||
+ !m_bUseMouse3rdPerson)
+ SetCameraDirectlyBehindForFollowPed_CamOnAString();
+
+ ReqMode = m_iModeToGoTo;
+ Cams[ActiveCam].Mode = ReqMode;
+ m_bJust_Switched = true;
+ Cams[ActiveCam].ResetStatics = true;
+ Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
+ Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;
+ Cams[ActiveCam].m_bCamLookingAtVector = false;
+ Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;
+ m_bRestoreByJumpCut = false;
+ Cams[ActiveCam].ResetStatics = true;
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ CarZoomValueSmooth = CarZoomValue;
+ m_fPedZoomValueSmooth = m_fPedZoomValue;
+ m_uiTransitionState = 0;
+ m_vecDoingSpecialInterPolation = false;
+ }
+
+ if(gbModelViewer)
+ ReqMode = CCam::MODE_MODELVIEW;
+
+ // Turn on Obbe's cam
+ bool canUseObbeCam = true;
+ if(pTargetEntity){
+ if(pTargetEntity->IsVehicle()){
+ if(CarZoomIndicator == CAM_ZOOM_CINEMATIC)
+ m_bObbeCinematicCarCamOn = true;
+ }else{
+ if(PedZoomIndicator == CAM_ZOOM_CINEMATIC)
+ m_bObbeCinematicPedCamOn = true;
+ }
+ }
+ if(m_bTargetJustBeenOnTrain ||
+ ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON ||
+ ReqMode == CCam::MODE_PED_DEAD_BABY || ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO ||
+ ReqMode == CCam::MODE_FIGHT_CAM || ReqMode == CCam::MODE_PLAYER_FALLEN_WATER ||
+ ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER || ReqMode == CCam::MODE_M16_1STPERSON ||
+ ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON ||
+ WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT ||
+ m_bJustCameOutOfGarage || m_bPlayerIsInGarage)
+ canUseObbeCam = false;
+
+ if(m_bObbeCinematicPedCamOn && canUseObbeCam)
+ ProcessObbeCinemaCameraPed();
+ else if(m_bObbeCinematicCarCamOn && canUseObbeCam)
+ ProcessObbeCinemaCameraCar();
+ else{
+ if(m_bPlayerIsInGarage && m_bObbeCinematicCarCamOn)
+ switchByJumpCut = true;
+ canUseObbeCam = false;
+ DontProcessObbeCinemaCamera();
+ }
+
+ // Start the transition or do a jump cut
+ if(m_bLookingAtPlayer){
+ // Going into top down modes normally needs a jump cut (but see below)
+ if(ReqMode == CCam::MODE_TOPDOWN || ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_TOP_DOWN_PED){
+ switchByJumpCut = true;
+ }
+ // Going from top down to vehicle
+ else if(ReqMode == CCam::MODE_CAM_ON_A_STRING || ReqMode == CCam::MODE_BEHINDBOAT){
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED)
+ switchByJumpCut = true;
+ }else if(ReqMode == CCam::MODE_FIXED){
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN)
+ switchByJumpCut = true;
+ }
+
+ // Top down modes can interpolate between each other
+ if(ReqMode == CCam::MODE_TOPDOWN){
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)
+ switchByJumpCut = false;
+ }else if(ReqMode == CCam::MODE_TOP_DOWN_PED){
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)
+ switchByJumpCut = false;
+ }
+
+ if(ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_M16_1STPERSON ||
+ ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER ||
+ ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ ReqMode == CCam::MODE_HELICANNON_1STPERSON ||
+ ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO){
+ // Going into any 1st person mode is a jump cut
+ if(pTargetEntity->IsPed())
+ switchByJumpCut = true;
+ }else if(ReqMode == CCam::MODE_FIXED && m_bPlayerIsInGarage){
+ // Going from 1st peron mode into garage
+ if(Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED ||
+ stairs ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT){
+ if(pTargetEntity && pTargetEntity->IsVehicle())
+ switchByJumpCut = true;
+ }
+ }else if(ReqMode == CCam::MODE_FOLLOWPED){
+ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||
+ Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_ONE ||
+ Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_TWO ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY ||
+ Cams[ActiveCam].Mode == CCam::MODE_PILLOWS_PAPS ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN ||
+ Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
+ if(!m_bJustCameOutOfGarage){
+ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON){
+ float angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI;
+ ((CPed*)pTargetEntity)->m_fRotationCur = angle;
+ ((CPed*)pTargetEntity)->m_fRotationDest = angle;
+ }
+ m_bUseTransitionBeta = true;
+ switchByJumpCut = true;
+ if(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
+ CVector front = Cams[ActiveCam].Source - FindPlayerPed()->GetPosition();
+ front.z = 0.0f;
+ front.Normalise();
+#ifdef FIX_BUGS
+ // this is almost as bad as the bugged code
+ if(front.x == 0.001f && front.y == 0.001f)
+ front.y = 1.0f;
+#else
+ // someone used = instead of == in the above check by accident
+ front.x = 0.001f;
+ front.y = 1.0f;
+#endif
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(front.x, front.y);
+ }else
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
+ }
+ }
+ }else if(ReqMode == CCam::MODE_FIGHT_CAM){
+ if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON)
+ switchByJumpCut = true;
+ }
+
+ if(ReqMode != Cams[ActiveCam].Mode && Cams[ActiveCam].CamTargetEntity == nil)
+ switchByJumpCut = true;
+ if(m_bPlayerIsInGarage && pToGarageWeAreIn){
+ if(pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP1 ||
+ pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP2 ||
+ pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP3){
+ if(pTargetEntity->IsVehicle() && pTargetEntity->GetModelIndex() == MI_MRWHOOP &&
+ ReqMode != Cams[ActiveCam].Mode)
+ switchByJumpCut = true;
+ }
+ }
+ if(CSceneEdit::m_bEditOn)
+ ReqMode = CCam::MODE_EDITOR;
+
+ if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){
+ if(switchByJumpCut){
+ if(!m_bPlayerIsInGarage || m_bJustCameOutOfGarage){
+ if(ReqMode != CCam::MODE_FOLLOWPED &&
+ ReqMode != CCam::MODE_M16_1STPERSON &&
+ ReqMode != CCam::MODE_SNIPER &&
+ ReqMode != CCam::MODE_ROCKETLAUNCHER ||
+ !m_bUseMouse3rdPerson)
+ SetCameraDirectlyBehindForFollowPed_CamOnAString();
+ }
+ Cams[ActiveCam].Mode = ReqMode;
+ m_bJust_Switched = true;
+ Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
+ Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;
+ Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;
+ Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;
+ CarZoomValueSmooth = CarZoomValue;
+ m_fPedZoomValueSmooth = m_fPedZoomValue;
+ m_uiTransitionState = 0;
+ m_vecDoingSpecialInterPolation = false;
+ m_bStartInterScript = false;
+ Cams[ActiveCam].ResetStatics = true;
+
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }else if(!m_bWaitForInterpolToFinish){
+ StartTransition(ReqMode);
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }
+ }else if(m_uiTransitionState != 0 && ReqMode != Cams[ActiveCam].Mode){
+ bool startTransition = true;
+
+ if(ReqMode == CCam::MODE_FIGHT_CAM || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM)
+ startTransition = false;
+ if(ReqMode == CCam::MODE_FOLLOWPED && Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM)
+ startTransition = false;
+
+ if(!m_bWaitForInterpolToFinish && m_bLookingAtPlayer && m_uiTransitionState != 0){
+ CVector playerDist;
+ playerDist.x = FindPlayerPed()->GetPosition().x - GetPosition().x;
+ playerDist.y = FindPlayerPed()->GetPosition().y - GetPosition().y;
+ playerDist.z = FindPlayerPed()->GetPosition().z - GetPosition().z;
+ // if player is too far away, keep interpolating and don't transition
+ if(pTargetEntity && pTargetEntity->IsPed()){
+ if(playerDist.Magnitude() > 17.5f &&
+ (ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT))
+ m_bWaitForInterpolToFinish = true;
+ }
+ }
+ if(m_bWaitForInterpolToFinish)
+ startTransition = false;
+
+ if(startTransition){
+ StartTransitionWhenNotFinishedInter(ReqMode);
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }
+ }else if(ReqMode == CCam::MODE_FIXED && pTargetEntity != Cams[ActiveCam].CamTargetEntity && m_bPlayerIsInGarage){
+ if(m_uiTransitionState != 0)
+ StartTransitionWhenNotFinishedInter(ReqMode);
+ else
+ StartTransition(ReqMode);
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }
+ }else{
+ // not following player
+ if(m_uiTransitionState == 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){
+ ReqMode = m_iModeToGoTo;
+ StartTransition(ReqMode);
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }else if(m_uiTransitionState != 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){
+ ReqMode = m_iModeToGoTo;
+ StartTransitionWhenNotFinishedInter(ReqMode);
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ }else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT){
+ m_uiTransitionState = 0;
+ m_vecDoingSpecialInterPolation = false;
+ Cams[ActiveCam].Mode = m_iModeToGoTo;
+ m_bJust_Switched = true;
+ Cams[ActiveCam].ResetStatics = true;
+ Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
+ Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;
+ Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;
+ Cams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;
+ m_bJust_Switched = true;
+ pTargetEntity->RegisterReference(&pTargetEntity);
+ Cams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);
+ CarZoomValueSmooth = CarZoomValue;
+ m_fPedZoomValueSmooth = m_fPedZoomValue;
+ }
+ }
+
+ m_bStartInterScript = false;
+
+ if(Cams[ActiveCam].CamTargetEntity == nil)
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+
+ // Ped visibility
+ if((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) && pTargetEntity->IsPed() ||
+ Cams[ActiveCam].Mode == CCam::MODE_FLYBY)
+ FindPlayerPed()->bIsVisible = false;
+ else
+ FindPlayerPed()->bIsVisible = true;
+
+ if(!canUseObbeCam && WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)
+ Restore();
}
-bool
-CCamera::IsPointVisible(const CVector &center, const CMatrix *mat)
+// What a mess!
+void
+CCamera::UpdateTargetEntity(void)
{
- RwV3d c;
- c = *(RwV3d*)&center;
- RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
- if(c.y < CDraw::GetNearClipZ()) return false;
- if(c.y > CDraw::GetFarClipZ()) return false;
- if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false;
- if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > 0.0f) return false;
- if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > 0.0f) return false;
- if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > 0.0f) return false;
- return true;
+ bool enteringCar = false; // not on PS2 but only used as && !enteringCar so we can keep it
+ bool obbeCam = false;
+
+ if(WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){
+ obbeCam = true;
+ if(m_iModeObbeCamIsInForCar == OBBE_COPCAR_WHEEL || m_iModeObbeCamIsInForCar == OBBE_COPCAR){
+ if(FindPlayerPed()->GetPedState() != PED_ARRESTED)
+ obbeCam = false;
+ if(FindPlayerVehicle() == nil)
+ pTargetEntity = FindPlayerPed();
+ }
+ }
+
+ if((m_bLookingAtPlayer || obbeCam) && m_uiTransitionState == 0 ||
+ pTargetEntity == nil ||
+ m_bTargetJustBeenOnTrain){
+ if(FindPlayerVehicle())
+ pTargetEntity = FindPlayerVehicle();
+ else{
+ pTargetEntity = FindPlayerPed();
+#ifndef GTA_PS2_STUFF
+ // this keeps the camera on the player while entering cars
+ if(PLAYER->GetPedState() == PED_ENTER_CAR ||
+ PLAYER->GetPedState() == PED_CARJACK ||
+ PLAYER->GetPedState() == PED_OPEN_DOOR)
+ enteringCar = true;
+
+ if(!enteringCar)
+ if(Cams[ActiveCam].CamTargetEntity != pTargetEntity)
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+#endif
+ }
+
+ bool cantOpen = true;
+ if(PLAYER &&
+ PLAYER->m_pMyVehicle &&
+ PLAYER->m_pMyVehicle->CanPedOpenLocks(PLAYER))
+ cantOpen = false;
+
+ if(PLAYER->GetPedState() == PED_ENTER_CAR && !cantOpen){
+ if(!enteringCar && CarZoomIndicator != 0.0f){
+ pTargetEntity = PLAYER->m_pMyVehicle;
+ if(PLAYER->m_pMyVehicle == nil)
+ pTargetEntity = PLAYER;
+ }
+ }
+
+ if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
+ if(!enteringCar && CarZoomIndicator != 0.0f)
+#ifdef GTA_PS2_STUFF
+// dunno if this has any amazing effects
+ {
+#endif
+ pTargetEntity = PLAYER->m_pMyVehicle;
+ if(PLAYER->m_pMyVehicle == nil)
+ pTargetEntity = PLAYER;
+#ifdef GTA_PS2_STUFF
+ }
+#endif
+ }
+
+ if(PLAYER->GetPedState() == PED_EXIT_CAR)
+ pTargetEntity = FindPlayerPed();
+ if(PLAYER->GetPedState() == PED_DRAG_FROM_CAR)
+ pTargetEntity = FindPlayerPed();
+ if(pTargetEntity->IsVehicle() && CarZoomIndicator != 0.0f && FindPlayerPed()->GetPedState() == PED_ARRESTED)
+ pTargetEntity = FindPlayerPed();
+ }
}
-bool
-CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat)
+const float SOUND_DIST = 20.0f;
+
+void
+CCamera::UpdateSoundDistances(void)
{
- int i;
- int frustumTests[6] = { 0 };
- RwV3dTransformPoints(box, box, 8, &mat->m_matrix);
+ CVector center, end;
+ CEntity *entity;
+ CColPoint colPoint;
+ float f;
+ int n;
- for(i = 0; i < 8; i++){
- if(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++;
- if(box[i].y > CDraw::GetFarClipZ()) frustumTests[1]++;
- if(box[i].x*m_vecFrustumNormals[0].x + box[i].y*m_vecFrustumNormals[0].y > 0.0f) frustumTests[2]++;
- if(box[i].x*m_vecFrustumNormals[1].x + box[i].y*m_vecFrustumNormals[1].y > 0.0f) frustumTests[3]++;
-// Why not test z?
-// if(box[i].y*m_vecFrustumNormals[2].y + box[i].z*m_vecFrustumNormals[2].z > 0.0f) frustumTests[4]++;
-// if(box[i].y*m_vecFrustumNormals[3].y + box[i].z*m_vecFrustumNormals[3].z > 0.0f) frustumTests[5]++;
+ if((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) &&
+ pTargetEntity->IsPed())
+ center = GetPosition() + 0.5f*GetForward();
+ else
+ center = GetPosition() + 5.0f*GetForward();
+
+ // check up
+ n = CTimer::GetFrameCounter() % 12;
+ if(n == 0){
+ SoundDistUpAsReadOld = SoundDistUpAsRead;
+ if(CWorld::ProcessVerticalLine(center, center.z+SOUND_DIST, colPoint, entity, true, false, false, false, true, false, nil))
+ SoundDistUpAsRead = colPoint.point.z - center.z;
+ else
+ SoundDistUpAsRead = SOUND_DIST;
}
- for(i = 0; i < 6; i++)
- if(frustumTests[i] == 8)
- return false; // Box is completely outside of one plane
- return true;
+ f = (n + 1) / 6.0f;
+ SoundDistUp = (1.0f-f)*SoundDistUpAsReadOld + f*SoundDistUpAsRead;
+
+ // check left
+ n = (CTimer::GetFrameCounter()+2) % 12;
+ if(n == 0){
+ SoundDistLeftAsReadOld = SoundDistLeftAsRead;
+ end = center + SOUND_DIST*GetRight();
+ if(CWorld::ProcessLineOfSight(center, end, colPoint, entity, true, false, false, false, true, true, true))
+ SoundDistLeftAsRead = (colPoint.point - center).Magnitude();
+ else
+ SoundDistLeftAsRead = SOUND_DIST;
+ }
+ f = (n + 1) / 6.0f;
+ SoundDistLeft = (1.0f-f)*SoundDistLeftAsReadOld + f*SoundDistLeftAsRead;
+
+ // check right
+ // end = center - SOUND_DIST*GetRight(); // useless
+ n = (CTimer::GetFrameCounter()+4) % 12;
+ if(n == 0){
+ SoundDistRightAsReadOld = SoundDistRightAsRead;
+ end = center - SOUND_DIST*GetRight();
+ if(CWorld::ProcessLineOfSight(center, end, colPoint, entity, true, false, false, false, true, true, true))
+ SoundDistRightAsRead = (colPoint.point - center).Magnitude();
+ else
+ SoundDistRightAsRead = SOUND_DIST;
+ }
+ f = (n + 1) / 6.0f;
+ SoundDistRight = (1.0f-f)*SoundDistRightAsReadOld + f*SoundDistRightAsRead;
}
-int
-CCamera::GetLookDirection(void)
+void
+CCamera::InitialiseCameraForDebugMode(void)
{
- if(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING ||
- Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
- Cams[ActiveCam].Mode == CCam::MODE_BEHINDBOAT ||
- Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED)
- return Cams[ActiveCam].DirectionWasLooking;
- return LOOKING_FORWARD;;
+ if(FindPlayerVehicle())
+ Cams[2].Source = FindPlayerVehicle()->GetPosition();
+ else if(FindPlayerPed())
+ Cams[2].Source = FindPlayerPed()->GetPosition();
+ Cams[2].Alpha = 0.0f;
+ Cams[2].Beta = 0.0f;
+ Cams[2].Mode = CCam::MODE_DEBUG;
}
-bool
-CCamera::GetLookingForwardFirstPerson()
+void
+CCamera::CamShake(float strength, float x, float y, float z)
{
- return Cams[ActiveCam].Mode == CCam::MODE_1STPERSON &&
- Cams[ActiveCam].DirectionWasLooking == LOOKING_FORWARD;
+ CVector Dist = Cams[ActiveCam].Source - CVector(x, y, z);
+ // a bit complicated...
+ float dist2d = Sqrt(SQR(Dist.x) + SQR(Dist.y));
+ float dist3d = Sqrt(SQR(dist2d) + SQR(Dist.z));
+ if(dist3d > 100.0f) dist3d = 100.0f;
+ if(dist3d < 0.0f) dist3d = 0.0f;
+ float mult = 1.0f - dist3d/100.0f;
+
+ float curForce = mult*(m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - m_uiCamShakeStart)/1000.0f);
+ strength = mult*strength;
+ if(clamp(curForce, 0.0f, 2.0f) < strength){
+ m_fCamShakeForce = strength;
+ m_uiCamShakeStart = CTimer::GetTimeInMilliseconds();
+ }
}
+// This seems to be CCamera::CamShake(float) on PS2
+void
+CamShakeNoPos(CCamera *cam, float strength)
+{
+ float curForce = cam->m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - cam->m_uiCamShakeStart)/1000.0f;
+ if(clamp(curForce, 0.0f, 2.0f) < strength){
+ cam->m_fCamShakeForce = strength;
+ cam->m_uiCamShakeStart = CTimer::GetTimeInMilliseconds();
+ }
+}
-WRAPPER void CCamera::Fade(float timeout, int16 direction) { EAXJMP(0x46B3A0); }
-WRAPPER void CCamera::ProcessFade(void) { EAXJMP(0x46F080); }
-WRAPPER void CCamera::ProcessMusicFade(void) { EAXJMP(0x46F1E0); }
-int
-CCamera::GetScreenFadeStatus(void)
+
+void
+CCamera::TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller)
{
- if(m_fFLOATingFade == 0.0f)
- return FADE_0;
- if(m_fFLOATingFade == 255.0f)
- return FADE_2;
- return FADE_1;
+ bool doSwitch = true;
+ if(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT)
+ doSwitch = false;
+ if(doSwitch){
+ WhoIsInControlOfTheCamera = controller;
+ if(target){
+ if(mode == CCam::MODE_NONE){
+ // Why are we checking the old entity?
+ if(pTargetEntity->IsPed())
+ mode = CCam::MODE_FOLLOWPED;
+ else if(pTargetEntity->IsVehicle())
+ mode = CCam::MODE_CAM_ON_A_STRING;
+ }
+ }else if(FindPlayerVehicle())
+ target = FindPlayerVehicle();
+ else
+ target = PLAYER;
+
+ m_bLookingAtVector = false;
+ pTargetEntity = target;
+ m_iModeToGoTo = mode;
+ m_iTypeOfSwitch = typeOfSwitch;
+ m_bLookingAtPlayer = false;
+ m_bStartInterScript = true;
+ // FindPlayerPed(); // unused
+ }
}
void
-CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b)
+CCamera::TakeControlNoEntity(const CVector &position, int16 typeOfSwitch, int32 controller)
{
- m_FadeTargetIsSplashScreen = r == 0 && g == 0 && b == 0;
- CDraw::FadeRed = r;
- CDraw::FadeGreen = g;
- CDraw::FadeBlue = b;
+ bool doSwitch = true;
+ if(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT)
+ doSwitch = false;
+ if(doSwitch){
+ WhoIsInControlOfTheCamera = controller;
+ m_bLookingAtVector = true;
+ m_bLookingAtPlayer = false;
+ m_iModeToGoTo = CCam::MODE_FIXED;
+ m_vecFixedModeVector = position;
+ m_iTypeOfSwitch = typeOfSwitch;
+ m_bStartInterScript = true;
+ }
}
void
-CCamera::SetMotionBlur(int r, int g, int b, int a, int type)
+CCamera::TakeControlWithSpline(int16 typeOfSwitch)
{
- m_BlurRed = r;
- m_BlurGreen = g;
- m_BlurBlue = b;
- m_motionBlur = a;
- m_BlurType = type;
+ m_iModeToGoTo = CCam::MODE_FLYBY;
+ m_bLookingAtPlayer = false;
+ m_bLookingAtVector = false;
+ m_bcutsceneFinished = false;
+ m_iTypeOfSwitch = typeOfSwitch;
+ m_bStartInterScript = true;
+
+ //FindPlayerPed(); // unused
+};
+
+void
+CCamera::Restore(void)
+{
+ m_bLookingAtPlayer = true;
+ m_bLookingAtVector = false;
+ m_iTypeOfSwitch = INTERPOLATION;
+ m_bUseNearClipScript = false;
+ m_iModeObbeCamIsInForCar = OBBE_INVALID;
+ m_fPositionAlongSpline = 0.0;
+ m_bStartingSpline = false;
+ m_bScriptParametersSetForInterPol = false;
+ WhoIsInControlOfTheCamera = CAMCONTROL_GAME;
+
+ if(FindPlayerVehicle()){
+ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;
+ pTargetEntity = FindPlayerVehicle();
+ }else{
+ m_iModeToGoTo = CCam::MODE_FOLLOWPED;
+ pTargetEntity = PLAYER;
+ }
+
+ if(PLAYER->GetPedState() == PED_ENTER_CAR ||
+ PLAYER->GetPedState() == PED_CARJACK ||
+ PLAYER->GetPedState() == PED_OPEN_DOOR){
+ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;
+ pTargetEntity = PLAYER->m_pSeekTarget;
+ }
+ if(PLAYER->GetPedState() == PED_EXIT_CAR){
+ m_iModeToGoTo = CCam::MODE_FOLLOWPED;
+ pTargetEntity = PLAYER;
+ }
+
+ m_bUseScriptZoomValuePed = false;
+ m_bUseScriptZoomValueCar = false;
+ m_bStartInterScript = true;
+ m_bCameraJustRestored = true;
}
void
-CCamera::SetMotionBlurAlpha(int a)
+CCamera::RestoreWithJumpCut(void)
{
- m_imotionBlurAddAlpha = a;
+ m_bRestoreByJumpCut = true;
+ m_bLookingAtPlayer = true;
+ m_bLookingAtVector = false;
+ m_iTypeOfSwitch = JUMP_CUT;
+ m_bUseNearClipScript = false;
+ m_iModeObbeCamIsInForCar = OBBE_INVALID;
+ m_fPositionAlongSpline = 0.0;
+ m_bStartingSpline = false;
+ m_bScriptParametersSetForInterPol = false;
+ WhoIsInControlOfTheCamera = CAMCONTROL_GAME;
+ m_bCameraJustRestored = true;
+
+ if(FindPlayerVehicle()){
+ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;
+ pTargetEntity = FindPlayerVehicle();
+ }else{
+ m_iModeToGoTo = CCam::MODE_FOLLOWPED;
+ pTargetEntity = PLAYER;
+ }
+
+ if(PLAYER->GetPedState() == PED_ENTER_CAR ||
+ PLAYER->GetPedState() == PED_CARJACK ||
+ PLAYER->GetPedState() == PED_OPEN_DOOR){
+ m_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;
+ pTargetEntity = PLAYER->m_pSeekTarget;
+ }
+ if(PLAYER->GetPedState() == PED_EXIT_CAR){
+ m_iModeToGoTo = CCam::MODE_FOLLOWPED;
+ pTargetEntity = PLAYER;
+ }
+
+ m_bUseScriptZoomValuePed = false;
+ m_bUseScriptZoomValueCar = false;
}
void
-CCamera::SetNearClipScript(float clip)
+CCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffSet)
{
- m_fNearClipScript = clip;
- m_bUseNearClipScript = true;
+ m_vecFixedModeSource = Source;
+ m_vecFixedModeUpOffSet = UpOffSet;
}
+
+
+/*
+ * On PS2 the transition happens between Cams[1] and Cams[2].
+ * On PC the whole system has been changed.
+ */
void
-CCamera::RenderMotionBlur(void)
+CCamera::StartTransition(int16 newMode)
{
- if(m_BlurType == 0)
- return;
+ bool foo = false;
+ bool switchSyphonMode = false;
+ bool switchPedToCar = false;
+ bool switchPedMode = false;
+ bool switchFromFixed = false;
+ bool switch1stPersonToVehicle = false;
+ float betaOffset, targetBeta, camBeta, deltaBeta;
+ int door;
+ bool vehicleVertical;
- CMBlur::MotionBlurRender(m_pRwCamera,
- m_BlurRed, m_BlurGreen, m_BlurBlue,
- m_motionBlur, m_BlurType, m_imotionBlurAddAlpha);
+// missing on PS2
+ m_bItsOkToLookJustAtThePlayer = false;
+ m_fFractionInterToStopMovingTarget = 0.25f;
+ m_fFractionInterToStopCatchUpTarget = 0.75f;
+
+ if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED ||
+ Cams[ActiveCam].Mode == CCam::MODE_SYPHON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){
+ if(newMode == CCam::MODE_SYPHON_CRIM_IN_FRONT ||
+ newMode == CCam::MODE_FOLLOWPED ||
+ newMode == CCam::MODE_SYPHON ||
+ newMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON)
+ m_bItsOkToLookJustAtThePlayer = true;
+ if(newMode == CCam::MODE_CAM_ON_A_STRING)
+ switchPedToCar = true;
+ }
+//
+
+ if(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT && newMode == CCam::MODE_SYPHON)
+ switchSyphonMode = true;
+ if(Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM && newMode == CCam::MODE_FOLLOWPED)
+ switchPedMode = true;
+ if(Cams[ActiveCam].Mode == CCam::MODE_FIXED)
+ switchFromFixed = true;
+
+ m_bUseTransitionBeta = false;
+
+ if((Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT) &&
+ pTargetEntity->IsPed()){
+ float angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI;
+ ((CPed*)pTargetEntity)->m_fRotationCur = angle;
+ ((CPed*)pTargetEntity)->m_fRotationDest = angle;
+ }
+
+/* // PS2
+ ActiveCam = (ActiveCam+1)%2;
+ Cams[ActiveCam].Init();
+ Cams[ActiveCam].Mode = newMode;
+ */
+
+ Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
+ Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;
+ Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;
+
+ if(newMode == CCam::MODE_SNIPER ||
+ newMode == CCam::MODE_ROCKETLAUNCHER ||
+ newMode == CCam::MODE_M16_1STPERSON ||
+ newMode == CCam::MODE_SNIPER_RUNABOUT ||
+ newMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||
+ newMode == CCam::MODE_1STPERSON_RUNABOUT ||
+ newMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
+ newMode == CCam::MODE_FIGHT_CAM_RUNABOUT ||
+ newMode == CCam::MODE_HELICANNON_1STPERSON)
+ Cams[ActiveCam].Alpha = 0.0f;
+
+ // PS2 also copies values to ActiveCam here
+ switch(Cams[ActiveCam].Mode)
+ case CCam::MODE_SNIPER_RUNABOUT:
+ case CCam::MODE_ROCKETLAUNCHER_RUNABOUT:
+ case CCam::MODE_1STPERSON_RUNABOUT:
+ case CCam::MODE_M16_1STPERSON_RUNABOUT:
+ case CCam::MODE_FIGHT_CAM_RUNABOUT:
+ if(newMode == CCam::MODE_CAM_ON_A_STRING || newMode == CCam::MODE_BEHINDBOAT)
+ switch1stPersonToVehicle = true;
+
+ switch(newMode){
+ case CCam::MODE_BEHINDCAR:
+ Cams[ActiveCam].BetaSpeed = 0.0f;
+ break;
+
+ case CCam::MODE_FOLLOWPED:
+ // Getting out of vehicle normally
+ betaOffset = DEGTORAD(55.0f);
+ if(m_bJustCameOutOfGarage){
+ m_bUseTransitionBeta = true;
+/*
+ // weird logic...
+ if(CMenuManager::m_ControlMethod == CONTROL_CLASSIC)
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
+ else if(Cams[ActiveCam].Front.x != 0.0f && Cams[ActiveCam].Front.y != 0.0f) // && is wrong here
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
+ else
+ Cams[ActiveCam].m_fTransitionBeta = 0.0f;
+*/
+ // this is better:
+ if(Cams[ActiveCam].Front.x != 0.0f || Cams[ActiveCam].Front.y != 0.0f)
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;
+ else
+ Cams[ActiveCam].m_fTransitionBeta = 0.0f;
+ }
+ if(m_bTargetJustCameOffTrain)
+ m_bCamDirectlyInFront = true;
+ if(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING)
+ break;
+ m_bUseTransitionBeta = true;
+ vehicleVertical = false;
+ if(((CPed*)pTargetEntity)->m_carInObjective &&
+ ((CPed*)pTargetEntity)->m_carInObjective->GetForward().x == 0.0f &&
+ ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y == 0.0f)
+ vehicleVertical = true;
+ if(vehicleVertical){
+ Cams[ActiveCam].m_fTransitionBeta = 0.0f;
+ break;
+ }
+ camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+ if(((CPed*)pTargetEntity)->m_carInObjective)
+ targetBeta = CGeneral::GetATanOfXY(((CPed*)pTargetEntity)->m_carInObjective->GetForward().x, ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y);
+ else
+ targetBeta = camBeta;
+ deltaBeta = targetBeta - camBeta;
+ while(deltaBeta >= PI) deltaBeta -= 2*PI;
+ while(deltaBeta < -PI) deltaBeta += 2*PI;
+ deltaBeta = Abs(deltaBeta);
+
+ door = FindPlayerPed()->m_vehEnterType;
+ if(deltaBeta > HALFPI){
+ if(((CPed*)pTargetEntity)->m_carInObjective){
+ if(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){
+ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
+ betaOffset = -DEGTORAD(95.0f);
+ }else{
+ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = -DEGTORAD(95.0f);
+ }
+ }
+ Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset;
+ }else{
+ if(((CPed*)pTargetEntity)->m_carInObjective){
+ if(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){
+ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = -DEGTORAD(55.0f);
+ else if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
+ betaOffset = DEGTORAD(95.0f);
+ }else{
+ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
+ betaOffset = -DEGTORAD(55.0f);
+ else if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = DEGTORAD(95.0f);
+ }
+ }
+ Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI;
+ }
+ break;
+
+ case CCam::MODE_SNIPER:
+ case CCam::MODE_ROCKETLAUNCHER:
+ case CCam::MODE_M16_1STPERSON:
+ case CCam::MODE_SNIPER_RUNABOUT:
+ case CCam::MODE_ROCKETLAUNCHER_RUNABOUT:
+ case CCam::MODE_1STPERSON_RUNABOUT:
+ case CCam::MODE_M16_1STPERSON_RUNABOUT:
+ case CCam::MODE_FIGHT_CAM_RUNABOUT:
+ case CCam::MODE_HELICANNON_1STPERSON:
+ if(FindPlayerVehicle())
+ Cams[ActiveCam].Beta = Atan2(FindPlayerVehicle()->GetForward().x, FindPlayerVehicle()->GetForward().y);
+ else
+ Cams[ActiveCam].Beta = Atan2(PLAYER->GetForward().x, PLAYER->GetForward().y);
+ break;
+
+ case CCam::MODE_SYPHON:
+ Cams[ActiveCam].Alpha = 0.0f;
+ Cams[ActiveCam].AlphaSpeed = 0.0f;
+ break;
+
+ case CCam::MODE_CAM_ON_A_STRING:
+ // Get into vehicle
+ betaOffset = DEGTORAD(57.0f);
+ if(!m_bLookingAtPlayer || m_bJustCameOutOfGarage)
+ break;
+ m_bUseTransitionBeta = true;
+ targetBeta = CGeneral::GetATanOfXY(pTargetEntity->GetForward().x, pTargetEntity->GetForward().y);
+ camBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+ deltaBeta = targetBeta - camBeta;
+ while(deltaBeta >= PI) deltaBeta -= 2*PI;
+ while(deltaBeta < -PI) deltaBeta += 2*PI;
+ deltaBeta = Abs(deltaBeta);
+ // switchFromFixed logic again here, skipped
+ if(switchFromFixed){
+ Cams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);
+ break;
+ }
+
+ door = FindPlayerPed()->m_vehEnterType;
+ if(deltaBeta > HALFPI){
+ if(((CVehicle*)pTargetEntity)->IsUpsideDown()){
+ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR) // BUG: game checks LF twice
+ betaOffset = -DEGTORAD(57.0f);
+ }else{
+ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = -DEGTORAD(57.0f);
+ }
+ Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI;
+ }else{
+ if(((CVehicle*)pTargetEntity)->IsUpsideDown()){
+ if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = -DEGTORAD(57.0f);
+ else if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
+ betaOffset = DEGTORAD(57.0f);
+ }else{
+ if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)
+ betaOffset = -DEGTORAD(57.0f);
+ else if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)
+ betaOffset = DEGTORAD(57.0f);
+ }
+ Cams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset;
+ }
+ break;
+
+ case CCam::MODE_BEHINDBOAT:
+ Cams[ActiveCam].BetaSpeed = 0.0f;
+ break;
+
+ case CCam::MODE_PED_DEAD_BABY:
+ Cams[ActiveCam].Alpha = DEGTORAD(15.0f);
+ break;
+
+ case CCam::MODE_FIGHT_CAM:
+ Cams[ActiveCam].Beta = 0.0f;
+ Cams[ActiveCam].BetaSpeed = 0.0f;
+ Cams[ActiveCam].Alpha = 0.0f;
+ Cams[ActiveCam].AlphaSpeed = 0.0f;
+ break;
+ }
+
+ Cams[ActiveCam].Init();
+ Cams[ActiveCam].Mode = newMode;
+
+ m_uiTransitionDuration = 1350;
+ if(switchSyphonMode)
+ m_uiTransitionDuration = 1800;
+ else if(switchPedMode)
+ m_uiTransitionDuration = 750;
+// not on PS2
+ else if(switchPedToCar){
+ m_fFractionInterToStopMovingTarget = 0.2f;
+ m_fFractionInterToStopCatchUpTarget = 0.8f;
+ m_uiTransitionDuration = 950;
+ }else if(switchFromFixed){
+ m_fFractionInterToStopMovingTarget = 0.05f;
+ m_fFractionInterToStopCatchUpTarget = 0.95f;
+ }else if(switch1stPersonToVehicle){
+ m_fFractionInterToStopMovingTarget = 0.0f;
+ m_fFractionInterToStopCatchUpTarget = 1.0f;
+ m_uiTransitionDuration = 1;
+ }else
+ m_uiTransitionDuration = 1350; // already set above
+//
+ m_uiTransitionState = 1;
+ m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds();
+ m_uiTransitionJUSTStarted = 1;
+// PS2 returns here
+ if(m_vecDoingSpecialInterPolation){
+ m_cvecStartingSourceForInterPol = SourceDuringInter;
+ m_cvecStartingTargetForInterPol = TargetDuringInter;
+ m_cvecStartingUpForInterPol = UpDuringInter;
+ m_fStartingAlphaForInterPol = m_fAlphaDuringInterPol;
+ m_fStartingBetaForInterPol = m_fBetaDuringInterPol;
+ }else{
+ m_cvecStartingSourceForInterPol = Cams[ActiveCam].Source;
+ m_cvecStartingTargetForInterPol = Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter;
+ m_cvecStartingUpForInterPol = Cams[ActiveCam].Up;
+ m_fStartingAlphaForInterPol = Cams[ActiveCam].m_fTrueAlpha;
+ m_fStartingBetaForInterPol = Cams[ActiveCam].m_fTrueBeta;
+ }
+ Cams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;
+ Cams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;
+ Cams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;
+ Cams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;
+ Cams[ActiveCam].Mode = newMode; // already done above
+ Cams[ActiveCam].CamTargetEntity = pTargetEntity;
+ m_uiTransitionState = 1; // these three already done above
+ m_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds();
+ m_uiTransitionJUSTStarted = 1;
+ m_fStartingFOVForInterPol = Cams[ActiveCam].FOV;
+ m_cvecSourceSpeedAtStartInter = Cams[ActiveCam].m_cvecSourceSpeedOverOneFrame;
+ m_cvecTargetSpeedAtStartInter = Cams[ActiveCam].m_cvecTargetSpeedOverOneFrame;
+ m_cvecUpSpeedAtStartInter = Cams[ActiveCam].m_cvecUpOverOneFrame;
+ m_fAlphaSpeedAtStartInter = Cams[ActiveCam].m_fAlphaSpeedOverOneFrame;
+ m_fBetaSpeedAtStartInter = Cams[ActiveCam].m_fBetaSpeedOverOneFrame;
+ m_fFOVSpeedAtStartInter = Cams[ActiveCam].m_fFovSpeedOverOneFrame;
+ Cams[ActiveCam].ResetStatics = true;
+ if(!m_bLookingAtPlayer && m_bScriptParametersSetForInterPol){
+ m_fFractionInterToStopMovingTarget = m_fScriptPercentageInterToStopMoving;
+ m_fFractionInterToStopCatchUpTarget = m_fScriptPercentageInterToCatchUp;
+ m_uiTransitionDuration = m_fScriptTimeForInterPolation;
+ }
}
void
-CCamera::ClearPlayerWeaponMode()
+CCamera::StartTransitionWhenNotFinishedInter(int16 mode)
{
- PlayerWeaponMode.Mode = 0;
- PlayerWeaponMode.MaxZoom = 1;
- PlayerWeaponMode.MinZoom = -1;
- PlayerWeaponMode.Duration = 0.0f;
+ m_vecDoingSpecialInterPolation = true;
+ StartTransition(mode);
}
-float
-CCamera::Find3rdPersonQuickAimPitch(void)
+void
+CCamera::StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV)
{
- float clampedFrontZ = clamp(Cams[ActiveCam].Front.z, -1.0f, 1.0f);
+ SourceDuringInter = source;
+ TargetDuringInter = target;
+ UpDuringInter = up;
+ FOVDuringInter = FOV;
+ CVector Dist = source - TargetDuringInter;
+ float DistOnGround = Dist.Magnitude2D();
+ m_fBetaDuringInterPol = CGeneral::GetATanOfXY(Dist.x, Dist.y);
+ m_fAlphaDuringInterPol = CGeneral::GetATanOfXY(DistOnGround, Dist.z);
+}
- // float rot = atan2(clampedFrontZ, sqrt(1.0f - sq(clampedFrontZ)));
- float rot = Asin(clampedFrontZ);
- return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot);
+
+void
+CCamera::SetWideScreenOn(void)
+{
+ m_WideScreenOn = true;
}
void
-CCamera::SetCamCutSceneOffSet(const CVector &pos)
+CCamera::SetWideScreenOff(void)
{
- m_vecCutSceneOffset = pos;
-};
+ m_bWantsToSwitchWidescreenOff = m_WideScreenOn;
+}
void
-CCamera::TakeControlWithSpline(short nSwitch)
+CCamera::ProcessWideScreenOn(void)
{
- m_iModeToGoTo = CCam::MODE_FLYBY;
- m_bLookingAtPlayer = false;
- m_bLookingAtVector = false;
- m_bcutsceneFinished = false;
- m_iTypeOfSwitch = nSwitch;
- m_bStartInterScript = true;
+ if(m_bWantsToSwitchWidescreenOff){
+ m_bWantsToSwitchWidescreenOff = false;
+ m_WideScreenOn = false;
+ m_ScreenReductionPercentage = 0.0f;
+ m_fFOV_Wide_Screen = 0.0f;
+ m_fWideScreenReductionAmount = 0.0f;
+ }else{
+ m_fFOV_Wide_Screen = 0.3f*Cams[ActiveCam].FOV;
+ m_fWideScreenReductionAmount = 1.0f;
+ m_ScreenReductionPercentage = 30.0f;
+ }
+}
- //FindPlayerPed(); // unused
-};
+void
+CCamera::DrawBordersForWideScreen(void)
+{
+ if(m_BlurType == MBLUR_NONE || m_BlurType == MBLUR_NORMAL)
+ SetMotionBlurAlpha(80);
+
+ CSprite2d::DrawRect(
+ CRect(0.0f, (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f,
+ SCREEN_WIDTH, 0.0f),
+ CRGBA(0, 0, 0, 255));
-void CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString()
+ CSprite2d::DrawRect(
+ CRect(0.0f, SCREEN_HEIGHT,
+ SCREEN_WIDTH, SCREEN_HEIGHT - (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f),
+ CRGBA(0, 0, 0, 255));
+}
+
+
+
+bool
+CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time)
{
- m_bCamDirectlyInFront = true;
- CPlayerPed *player = FindPlayerPed();
- if (player)
- m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
+ CVehicle *veh;
+ uint32 t = time; // no annoying compiler warnings
+ CVector fwd;
+
+ if(obbeMode < 0)
+ return true;
+ switch(obbeMode){
+ case OBBE_WHEEL:
+ veh = FindPlayerVehicle();
+ if(veh == nil){
+ if(CTimer::GetTimeInMilliseconds() > t+5000)
+ return true;
+ SetNearClipScript(0.6f);
+ return false;
+ }
+ if(veh->IsBoat() || veh->GetModelIndex() == MI_RHINO)
+ return true;
+ if(CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false)){
+ if(CTimer::GetTimeInMilliseconds() > t+5000)
+ return true;
+ SetNearClipScript(0.6f);
+ return false;
+ }
+ return true;
+ case OBBE_1:
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return true;
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ // too close
+ if(fwd.Magnitude() < 1.6f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_2:
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return true;
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ if(fwd.Magnitude() < 2.0f)
+ // very close, fix near clip
+ SetNearClipScript(max(fwd.Magnitude()*0.5f, 0.05f));
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 19.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ // too close
+ if(fwd.Magnitude() < 1.6f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_3:
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 28.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_1STPERSON:
+ return CTimer::GetTimeInMilliseconds() > t+3000;
+ case OBBE_5:
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return true;
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 28.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_ONSTRING:
+ return CTimer::GetTimeInMilliseconds() > t+3000;
+ case OBBE_COPCAR:
+ return CTimer::GetTimeInMilliseconds() > t+2000 && !FindPlayerVehicle()->GetIsOnScreen();
+ case OBBE_COPCAR_WHEEL:
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return true;
+ if(CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false)){
+ if(CTimer::GetTimeInMilliseconds() > t+1000)
+ return true;
+ SetNearClipScript(0.6f);
+ return false;
+ }
+ return true;
+
+ // Ped modes
+ case OBBE_9:
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_10:
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_11:
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 25.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_12:
+ if(CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false)){
+ fwd = FindPlayerCoors() - m_vecFixedModeSource;
+ fwd.z = 0.0f;
+
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return true;
+ return false;
+ }
+ return true;
+ case OBBE_13:
+ return CTimer::GetTimeInMilliseconds() > t+5000;
+ default:
+ return false;
+ }
}
-void CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString()
+bool
+CCamera::TryToStartNewCamMode(int obbeMode)
{
- m_bCamDirectlyBehind = true;
- CPlayerPed *player = FindPlayerPed();
- if (player)
- m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
+ CVehicle *veh;
+ CVector target, camPos, playerSpeed, fwd;
+ float ground;
+ bool foundGround;
+ int i;
+
+ if(obbeMode < 0)
+ return true;
+ switch(obbeMode){
+ case OBBE_WHEEL:
+ veh = FindPlayerVehicle();
+ if(veh == nil || veh->IsBoat() || veh->GetModelIndex() == MI_RHINO)
+ return false;
+ target = Multiply3x3(FindPlayerVehicle()->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));
+ target += FindPlayerVehicle()->GetPosition();
+ if(!CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false))
+ return false;
+ TakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_1:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 20.0f*playerSpeed;
+ camPos += 3.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return false;
+
+ ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 1.5f;
+ else{
+ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 1.5f;
+ }
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ fwd = FindPlayerCoors() - camPos;
+ fwd.z = 0.0f;
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return false;
+ // too close
+ if(fwd.Magnitude() < 1.6f)
+ return true;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_2:
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return false;
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 16.0f*playerSpeed;
+ camPos += 2.5f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);
+
+ ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 0.5f;
+ else{
+ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 0.5f;
+ }
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ fwd = FindPlayerCoors() - camPos;
+ fwd.z = 0.0f;
+ // too far and driving away from cam
+ if(fwd.Magnitude() > 19.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)
+ return false;
+ // too close
+ if(fwd.Magnitude() < 1.6f)
+ return true;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_3:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 30.0f*playerSpeed;
+ camPos += 8.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);
+
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_1STPERSON:
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_5:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 30.0f*playerSpeed;
+ camPos += 6.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);
+
+ ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 3.5f;
+ else{
+ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 3.5f;
+ }
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_ONSTRING:
+ TakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_COPCAR:
+ if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1)
+ return false;
+ if(FindPlayerVehicle() == nil)
+ return false;
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return false;
+ i = CPools::GetVehiclePool()->GetSize();
+ while(--i >= 0){
+ veh = CPools::GetVehiclePool()->GetSlot(i);
+ if(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){
+ float dx = veh->GetPosition().x - FindPlayerCoors().x;
+ float dy = veh->GetPosition().y - FindPlayerCoors().y;
+ float dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude();
+ if(dist < 30.0f){
+ if(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f &&
+ veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){
+ TakeControl(veh, CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ case OBBE_COPCAR_WHEEL:
+ if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1)
+ return false;
+ if(FindPlayerVehicle() == nil)
+ return false;
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())
+ return false;
+ i = CPools::GetVehiclePool()->GetSize();
+ while(--i >= 0){
+ veh = CPools::GetVehiclePool()->GetSlot(i);
+ if(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){
+ float dx = veh->GetPosition().x - FindPlayerCoors().x;
+ float dy = veh->GetPosition().y - FindPlayerCoors().y;
+ float dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude();
+ if(dist < 30.0f){
+ if(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f &&
+ veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){
+ target = Multiply3x3(veh->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));
+ target += veh->GetPosition();
+ if(!CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false))
+ return false;
+ TakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+
+ case OBBE_9:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 15.0f*playerSpeed;
+ camPos += CVector(2.0f, 1.0f, 0.0f);
+
+ ground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 0.5f;
+ else{
+ ground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);
+ if(foundGround)
+ camPos.z = ground + 0.5f;
+ }
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_10:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 5.0f*playerSpeed;
+ camPos += CVector(2.0f, 1.0f, 0.5f);
+
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_11:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 20.0f*playerSpeed;
+ camPos += CVector(2.0f, 1.0f, 20.0f);
+
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_12:
+ camPos = FindPlayerCoors();
+ playerSpeed = FindPlayerSpeed();
+ playerSpeed.z = 0.0f;
+ playerSpeed.Normalise();
+ camPos += 5.0f*playerSpeed;
+ camPos += CVector(2.0f, 1.0f, 10.5f);
+
+ if(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))
+ return false;
+
+ SetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));
+ TakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);
+ return true;
+ case OBBE_13:
+#ifdef FIX_BUGS
+ TakeControl(FindPlayerEntity(), CCam::MODE_TOP_DOWN_PED, JUMP_CUT, CAMCONTROL_OBBE);
+#else
+ TakeControl(FindPlayerEntity(), CCam::MODE_TOPDOWN, JUMP_CUT, CAMCONTROL_OBBE);
+#endif
+ return true;
+ default:
+ return false;
+ }
}
+static int32 SequenceOfCams[16] = {
+ OBBE_WHEEL, OBBE_COPCAR, OBBE_3, OBBE_1, OBBE_3, OBBE_COPCAR_WHEEL,
+ OBBE_2, OBBE_3, OBBE_COPCAR_WHEEL, OBBE_COPCAR, OBBE_2, OBBE_3,
+ OBBE_5, OBBE_3,
+ OBBE_ONSTRING // actually unused...
+};
+
void
-CCamera::SetWideScreenOn(void)
+CCamera::ProcessObbeCinemaCameraCar(void)
{
- m_WideScreenOn = true;
+ static int OldMode = -1;
+ static int32 TimeForNext = 0;
+ int i = 0;
+
+ if(!bDidWeProcessAnyCinemaCam){
+ OldMode = -1;
+ CHud::SetHelpMessage(TheText.Get("CINCAM"), true);
+ }
+
+ if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfCams[OldMode], TimeForNext)){
+ // This is very strange code...
+ for(OldMode = (OldMode+1) % 14;
+ !TryToStartNewCamMode(SequenceOfCams[OldMode]) && i <= 14;
+ OldMode = (OldMode+1) % 14)
+ i++;
+ TimeForNext = CTimer::GetTimeInMilliseconds();
+ if(i >= 14){
+ OldMode = 14;
+ TryToStartNewCamMode(SequenceOfCams[14]);
+ }
+ }
+
+ m_iModeObbeCamIsInForCar = OldMode;
+ bDidWeProcessAnyCinemaCam = true;
}
+static int32 SequenceOfPedCams[5] = { OBBE_9, OBBE_10, OBBE_11, OBBE_12, OBBE_13 };
+
void
-CCamera::SetWideScreenOff(void)
+CCamera::ProcessObbeCinemaCameraPed(void)
{
- m_bWantsToSwitchWidescreenOff = m_WideScreenOn;
+ // static bool bObbePedProcessed = false; // unused
+ static int PedOldMode = -1;
+ static int32 PedTimeForNext = 0;
+
+ if(!bDidWeProcessAnyCinemaCam)
+ PedOldMode = -1;
+
+ if(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfPedCams[PedOldMode], PedTimeForNext)){
+ for(PedOldMode = (PedOldMode+1) % 5;
+ !TryToStartNewCamMode(SequenceOfPedCams[PedOldMode]);
+ PedOldMode = (PedOldMode+1) % 5);
+ PedTimeForNext = CTimer::GetTimeInMilliseconds();
+ }
+ bDidWeProcessAnyCinemaCam = true;
}
void
-CCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom)
+CCamera::DontProcessObbeCinemaCamera(void)
{
- PlayerWeaponMode.Mode = mode;
- PlayerWeaponMode.MaxZoom = maxZoom;
- PlayerWeaponMode.MinZoom = minZoom;
- PlayerWeaponMode.Duration = 0.0f;
+ bDidWeProcessAnyCinemaCam = false;
}
+
void
-CCamera::UpdateAimingCoors(CVector const &coors)
+CCamera::LoadTrainCamNodes(char const *name)
{
- m_cvecAimingTargetCoors = coors;
+ CFileMgr::SetDir("data");
+
+ char token[16] = { 0 };
+ char filename[16] = { 0 };
+ uint8 *buf;
+ int bufpos = 0;
+ int field = 0;
+ int tokpos = 0;
+ char c;
+ int i;
+ int len;
+
+ strcpy(filename, name);
+ len = strlen(filename);
+ filename[len] = '.';
+ filename[len+1] = 'd';
+ filename[len+2] = 'a';
+ filename[len+3] = 't';
+
+ m_uiNumberOfTrainCamNodes = 0;
+
+ buf = new uint8[20000];
+ len = CFileMgr::LoadFile(filename, buf, 20000, "r");
+
+ for(i = 0; i < MAX_NUM_OF_NODES; i++){
+ m_arrTrainCamNode[i].m_cvecPointToLookAt = CVector(0.0f, 0.0f, 0.0f);
+ m_arrTrainCamNode[i].m_cvecMinPointInRange = CVector(0.0f, 0.0f, 0.0f);
+ m_arrTrainCamNode[i].m_cvecMaxPointInRange = CVector(0.0f, 0.0f, 0.0f);
+ m_arrTrainCamNode[i].m_fDesiredFOV = 0.0f;
+ m_arrTrainCamNode[i].m_fNearClip = 0.0f;
+ }
+
+ while(bufpos <= len){
+ c = buf[bufpos];
+ switch(c){
+ case '-':
+ case '.':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+// case '10': case '11': case '12': case '13': // ahem...
+ token[tokpos++] = c;
+ bufpos++;
+ break;
+
+ case ',':
+ case ';': // game has the code for this duplicated but we handle both under the same case
+ switch((field+14)%14){
+ case 0:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.x = atof(token);
+ break;
+ case 1:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.y = atof(token);
+ break;
+ case 2:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.z = atof(token);
+ break;
+ case 3:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.x = atof(token);
+ break;
+ case 4:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.y = atof(token);
+ break;
+ case 5:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.z = atof(token);
+ break;
+ case 6:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.x = atof(token);
+ break;
+ case 7:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.y = atof(token);
+ break;
+ case 8:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.z = atof(token);
+ break;
+ case 9:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.x = atof(token);
+ break;
+ case 10:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.y = atof(token);
+ break;
+ case 11:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.z = atof(token);
+ break;
+ case 12:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fDesiredFOV = atof(token);
+ break;
+ case 13:
+ m_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fNearClip = atof(token);
+ m_uiNumberOfTrainCamNodes++;
+ break;
+ }
+ field++;
+ bufpos++;
+ memset(token, 0, sizeof(token));
+ tokpos = 0;
+ break;
+
+ default:
+ bufpos++;
+ break;
+ }
+ }
+
+ delete[] buf;
+ CFileMgr::SetDir("");
}
void
-CCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffSet)
+CCamera::Process_Train_Camera_Control(void)
{
- m_vecFixedModeSource = Source;
- m_vecFixedModeUpOffSet = UpOffSet;
+ bool found = false;
+ CTrain *target = (CTrain*)pTargetEntity;
+ m_bUseSpecialFovTrain = true;
+ static bool OKtoGoBackToNodeCam = true; // only ever set to true
+ uint32 i;
+
+ if(target->m_nTrackId == TRACK_ELTRAIN && !m_bAboveGroundTrainNodesLoaded){
+ m_bAboveGroundTrainNodesLoaded = true;
+ m_bBelowGroundTrainNodesLoaded = false;
+ LoadTrainCamNodes("Train");
+ m_uiTimeLastChange = CTimer::GetTimeInMilliseconds();
+ OKtoGoBackToNodeCam = true;
+ m_iCurrentTrainCamNode = 0;
+ }
+ if(target->m_nTrackId == TRACK_SUBWAY && !m_bBelowGroundTrainNodesLoaded){
+ m_bBelowGroundTrainNodesLoaded = true;
+ m_bAboveGroundTrainNodesLoaded = false;
+ LoadTrainCamNodes("Train2");
+ m_uiTimeLastChange = CTimer::GetTimeInMilliseconds();
+ OKtoGoBackToNodeCam = true;
+ m_iCurrentTrainCamNode = 0;
+ }
+
+ m_bTargetJustBeenOnTrain = true;
+ uint32 node = m_iCurrentTrainCamNode;
+ for(i = 0; i < m_uiNumberOfTrainCamNodes && !found; i++){
+ if(target->IsWithinArea(m_arrTrainCamNode[node].m_cvecMinPointInRange.x,
+ m_arrTrainCamNode[node].m_cvecMinPointInRange.y,
+ m_arrTrainCamNode[node].m_cvecMinPointInRange.z,
+ m_arrTrainCamNode[node].m_cvecMaxPointInRange.x,
+ m_arrTrainCamNode[node].m_cvecMaxPointInRange.y,
+ m_arrTrainCamNode[node].m_cvecMaxPointInRange.z)){
+ m_iCurrentTrainCamNode = node;
+ found = true;
+ }
+ node++;
+ if(node >= m_uiNumberOfTrainCamNodes)
+ node = 0;
+ }
+
+ if(found){
+ SetWideScreenOn();
+ if(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){
+ TakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);
+ if(target->Doors[0].IsFullyOpen())
+ SetWideScreenOff();
+ }else{
+ SetCamPositionForFixedMode(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecCamPosition, CVector(0.0f, 0.0f, 0.0f));
+ if(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.x == 999.0f &&
+ m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.y == 999.0f &&
+ m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.z == 999.0f)
+ TakeControl(target, CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT);
+ else
+ TakeControlNoEntity(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt, JUMP_CUT, CAMCONTROL_SCRIPT);
+ RwCameraSetNearClipPlane(Scene.camera, m_arrTrainCamNode[m_iCurrentTrainCamNode].m_fNearClip);
+ }
+ }else{
+ if(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){
+ TakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);
+ if(target->Doors[0].IsFullyOpen())
+ SetWideScreenOff();
+ }
+ }
}
+
+
void
-CCamera::SetRwCamera(RwCamera *cam)
+CCamera::LoadPathSplines(int file)
{
- m_pRwCamera = cam;
- m_viewMatrix.Attach(&m_pRwCamera->viewMatrix, false);
- CMBlur::MotionBlurOpen(m_pRwCamera);
+ bool reading = true;
+ char c, token[32] = { 0 };
+ int i, j, n;
+
+ n = 0;
+
+ for(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++)
+ for(j = 0; j < CCamPathSplines::MAXPATHLENGTH; j++)
+ m_arrPathArray[i].m_arr_PathData[j] = 0.0f;
+
+ m_bStartingSpline = false;
+
+ i = 0;
+ j = 0;
+ while(reading){
+ CFileMgr::Read(file, &c, 1);
+ switch(c){
+ case '\0':
+ reading = false;
+ break;
+
+ case '+': case '-': case '.':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'e': case 'E':
+ token[n++] = c;
+ break;
+
+ case ',':
+#ifdef FIX_BUGS
+ if(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH)
+#endif
+ m_arrPathArray[i].m_arr_PathData[j] = atof(token);
+ j++;
+ memset(token, 0, 32);
+ n = 0;
+ break;
+
+ case ';':
+#ifdef FIX_BUGS
+ if(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH)
+#endif
+ m_arrPathArray[i].m_arr_PathData[j] = atof(token);
+ i++;
+ j = 0;
+ memset(token, 0, 32);
+ n = 0;
+ }
+ }
+}
+
+void
+CCamera::FinishCutscene(void)
+{
+ SetPercentAlongCutScene(100.0f);
+ m_fPositionAlongSpline = 1.0f;
+ m_bcutsceneFinished = true;
}
uint32
@@ -291,17 +2917,33 @@ CCamera::GetCutSceneFinishTime(void)
}
void
-CCamera::FinishCutscene(void)
+CCamera::SetCamCutSceneOffSet(const CVector &pos)
{
- SetPercentAlongCutScene(100.0f);
- m_fPositionAlongSpline = 1.0f;
- m_bcutsceneFinished = true;
+ m_vecCutSceneOffset = pos;
+};
+
+void
+CCamera::SetPercentAlongCutScene(float percent)
+{
+ if(Cams[ActiveCam].Mode == CCam::MODE_FLYBY)
+ Cams[ActiveCam].m_fTimeElapsedFloat = percent/100.0f * Cams[ActiveCam].m_uiFinishTime;
+ else if(Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FLYBY)
+ Cams[(ActiveCam+1)%2].m_fTimeElapsedFloat = percent/100.0f * Cams[(ActiveCam+1)%2].m_uiFinishTime;
}
void
-CCamera::SetZoomValueFollowPedScript(int16 mode)
+CCamera::SetParametersForScriptInterpolation(float stopMoving, float catchUp, int32 time)
{
- switch (mode) {
+ m_fScriptPercentageInterToStopMoving = stopMoving * 0.01f;
+ m_fScriptPercentageInterToCatchUp = catchUp * 0.01f;
+ m_fScriptTimeForInterPolation = time;
+ m_bScriptParametersSetForInterPol = true;
+}
+
+void
+CCamera::SetZoomValueFollowPedScript(int16 dist)
+{
+ switch (dist) {
case 0: m_fPedZoomValueScript = 0.25f; break;
case 1: m_fPedZoomValueScript = 1.5f; break;
case 2: m_fPedZoomValueScript = 2.9f; break;
@@ -312,9 +2954,9 @@ CCamera::SetZoomValueFollowPedScript(int16 mode)
}
void
-CCamera::SetZoomValueCamStringScript(int16 mode)
+CCamera::SetZoomValueCamStringScript(int16 dist)
{
- switch (mode) {
+ switch (dist) {
case 0: m_fCarZoomValueScript = 0.05f; break;
case 1: m_fCarZoomValueScript = 1.9f; break;
case 2: m_fCarZoomValueScript = 3.9f; break;
@@ -324,6 +2966,395 @@ CCamera::SetZoomValueCamStringScript(int16 mode)
m_bUseScriptZoomValueCar = true;
}
+void
+CCamera::SetNearClipScript(float clip)
+{
+ m_fNearClipScript = clip;
+ m_bUseNearClipScript = true;
+}
+
+
+
+void
+CCamera::ProcessFade(void)
+{
+ float fade = (CTimer::GetTimeInMilliseconds() - m_uiFadeTimeStarted)/1000.0f;
+ // Why even set CDraw::FadeValue if m_fFLOATingFade sets it anyway?
+ if(m_bFading){
+ if(m_iFadingDirection == FADE_IN){
+ if(m_fTimeToFadeOut != 0.0f){
+ m_fFLOATingFade = 255.0f - 255.0f*fade/m_fTimeToFadeOut;
+ if(m_fFLOATingFade <= 0.0f){
+ m_bFading = false;
+ CDraw::FadeValue = 0;
+ m_fFLOATingFade = 0.0f;
+ }
+ }else{
+ m_bFading = false;
+ CDraw::FadeValue = 0;
+ m_fFLOATingFade = 0.0f;
+ }
+ }else if(m_iFadingDirection == FADE_OUT){
+ if(m_fTimeToFadeOut != 0.0f){
+ m_fFLOATingFade = 255.0f*fade/m_fTimeToFadeOut;
+ if(m_fFLOATingFade >= 255.0f){
+ m_bFading = false;
+ CDraw::FadeValue = 255;
+ m_fFLOATingFade = 255.0f;
+ }
+ }else{
+ m_bFading = false;
+ CDraw::FadeValue = 255;
+ m_fFLOATingFade = 255.0f;
+ }
+ }
+ CDraw::FadeValue = m_fFLOATingFade;
+ }
+}
+
+void
+CCamera::ProcessMusicFade(void)
+{
+ float fade = (CTimer::GetTimeInMilliseconds() - m_uiFadeTimeStartedMusic)/1000.0f;
+ if(m_bMusicFading){
+ if(m_iMusicFadingDirection == FADE_IN){
+ if(m_fTimeToFadeMusic == 0.0f)
+ m_fTimeToFadeMusic = 1.0f;
+
+ m_fFLOATingFadeMusic = 255.0f*fade/m_fTimeToFadeMusic;
+ if(m_fFLOATingFadeMusic > 255.0f){
+ m_bMusicFading = false;
+ m_fFLOATingFadeMusic = 0.0f;
+ DMAudio.SetEffectsFadeVol(127);
+ DMAudio.SetMusicFadeVol(127);
+ }else{
+ DMAudio.SetEffectsFadeVol(m_fFLOATingFadeMusic/255.0f * 127);
+ DMAudio.SetMusicFadeVol(m_fFLOATingFadeMusic/255.0f * 127);
+ }
+ }else if(m_iMusicFadingDirection == FADE_OUT){
+ if(m_fTimeToFadeMusic == 0.0f)
+ m_fTimeToFadeMusic = 1.0f;
+
+ if(m_bMoveCamToAvoidGeom || StillToFadeOut){
+ m_fFLOATingFadeMusic = 256.0f;
+ m_bMoveCamToAvoidGeom = false;
+ }else
+ m_fFLOATingFadeMusic = 255.0f*fade/m_fTimeToFadeMusic;
+
+ if(m_fFLOATingFadeMusic > 255.0f){
+ m_bMusicFading = false;
+ m_fFLOATingFadeMusic = 255.0f;
+ DMAudio.SetEffectsFadeVol(0);
+ DMAudio.SetMusicFadeVol(0);
+ }else{
+ DMAudio.SetEffectsFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127);
+ DMAudio.SetMusicFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127);
+ }
+ }
+ }
+}
+
+void
+CCamera::Fade(float timeout, int16 direction)
+{
+ m_bFading = true;
+ m_iFadingDirection = direction;
+ m_fTimeToFadeOut = timeout;
+ m_uiFadeTimeStarted = CTimer::GetTimeInMilliseconds();
+ if(!m_bIgnoreFadingStuffForMusic){
+ m_bMusicFading = true;
+ m_iMusicFadingDirection = direction;
+ m_fTimeToFadeMusic = timeout;
+ m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds();
+// Not on PS2
+ if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){
+ unknown++;
+ if(unknown >= 2){
+ m_bJustJumpedOutOf1stPersonBecauseOfTarget = true;
+ unknown = 0;
+ }else
+ m_bMoveCamToAvoidGeom = true;
+ }
+ }
+}
+
+void
+CCamera::SetFadeColour(uint8 r, uint8 g, uint8 b)
+{
+ m_FadeTargetIsSplashScreen = r == 0 && g == 0 && b == 0;
+ CDraw::FadeRed = r;
+ CDraw::FadeGreen = g;
+ CDraw::FadeBlue = b;
+}
+
+bool
+CCamera::GetFading(void)
+{
+ return m_bFading;
+}
+
+int
+CCamera::GetFadingDirection(void)
+{
+ if(m_bFading)
+ return m_iFadingDirection == FADE_IN ? FADE_IN : FADE_OUT;
+ else
+ return FADE_NONE;
+}
+
+int
+CCamera::GetScreenFadeStatus(void)
+{
+ if(m_fFLOATingFade == 0.0f)
+ return FADE_0;
+ if(m_fFLOATingFade == 255.0f)
+ return FADE_2;
+ return FADE_1;
+}
+
+
+
+void
+CCamera::RenderMotionBlur(void)
+{
+ if(m_BlurType == 0)
+ return;
+
+ CMBlur::MotionBlurRender(m_pRwCamera,
+ m_BlurRed, m_BlurGreen, m_BlurBlue,
+ m_motionBlur, m_BlurType, m_imotionBlurAddAlpha);
+}
+
+void
+CCamera::SetMotionBlur(int r, int g, int b, int a, int type)
+{
+ m_BlurRed = r;
+ m_BlurGreen = g;
+ m_BlurBlue = b;
+ m_motionBlur = a;
+ m_BlurType = type;
+}
+
+void
+CCamera::SetMotionBlurAlpha(int a)
+{
+ m_imotionBlurAddAlpha = a;
+}
+
+
+
+int
+CCamera::GetLookDirection(void)
+{
+ if(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING ||
+ Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||
+ Cams[ActiveCam].Mode == CCam::MODE_BEHINDBOAT ||
+ Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED)
+ return Cams[ActiveCam].DirectionWasLooking;
+ return LOOKING_FORWARD;;
+}
+
+bool
+CCamera::GetLookingForwardFirstPerson(void)
+{
+ return Cams[ActiveCam].Mode == CCam::MODE_1STPERSON &&
+ Cams[ActiveCam].DirectionWasLooking == LOOKING_FORWARD;
+}
+
+bool
+CCamera::GetLookingLRBFirstPerson(void)
+{
+ return Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD;
+}
+
+void
+CCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString(void)
+{
+ m_bCamDirectlyBehind = true;
+ CPlayerPed *player = FindPlayerPed();
+ if (player)
+ m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
+}
+
+void
+CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString(void)
+{
+ m_bCamDirectlyInFront = true;
+ CPlayerPed *player = FindPlayerPed();
+ if (player)
+ m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
+}
+
+void
+CCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom)
+{
+ PlayerWeaponMode.Mode = mode;
+ PlayerWeaponMode.MaxZoom = maxZoom;
+ PlayerWeaponMode.MinZoom = minZoom;
+ PlayerWeaponMode.Duration = 0.0f;
+}
+
+void
+CCamera::ClearPlayerWeaponMode(void)
+{
+ PlayerWeaponMode.Mode = 0;
+ PlayerWeaponMode.MaxZoom = 1;
+ PlayerWeaponMode.MinZoom = -1;
+ PlayerWeaponMode.Duration = 0.0f;
+}
+
+void
+CCamera::UpdateAimingCoors(CVector const &coors)
+{
+ m_cvecAimingTargetCoors = coors;
+}
+
+void
+CCamera::Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target)
+{
+ if(CPad::GetPad(0)->GetLookBehindForPed()){
+ source = pos;
+ target = dist*Cams[ActiveCam].CamTargetEntity->GetForward() + source;
+ }else{
+ float angleX = DEGTORAD((m_f3rdPersonCHairMultX-0.5f) * 1.8f * 0.5f * Cams[ActiveCam].FOV * CDraw::GetAspectRatio());
+ float angleY = DEGTORAD((0.5f-m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV);
+ source = Cams[ActiveCam].Source;
+ target = Cams[ActiveCam].Front;
+ target += Cams[ActiveCam].Up * Tan(angleY);
+ target += CrossProduct(Cams[ActiveCam].Front, Cams[ActiveCam].Up) * Tan(angleX);
+ target.Normalise();
+ float dot = DotProduct(pos - source, target);
+ source += dot*target;
+ target = dist*target + source;
+ }
+}
+
+float
+CCamera::Find3rdPersonQuickAimPitch(void)
+{
+ float clampedFrontZ = clamp(Cams[ActiveCam].Front.z, -1.0f, 1.0f);
+
+ float rot = Asin(clampedFrontZ);
+
+ return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot);
+}
+
+
+
+void
+CCamera::SetRwCamera(RwCamera *cam)
+{
+ m_pRwCamera = cam;
+ m_viewMatrix.Attach(&m_pRwCamera->viewMatrix, false);
+ CMBlur::MotionBlurOpen(m_pRwCamera);
+}
+
+void
+CCamera::CalculateDerivedValues(void)
+{
+ m_cameraMatrix = Invert(m_matrix);
+
+ float hfov = DEGTORAD(CDraw::GetFOV()/2.0f);
+ float c = cos(hfov);
+ float s = sin(hfov);
+
+ // right plane
+ m_vecFrustumNormals[0] = CVector(c, -s, 0.0f);
+ // left plane
+ m_vecFrustumNormals[1] = CVector(-c, -s, 0.0f);
+
+ c /= CDraw::FindAspectRatio();
+ s /= CDraw::FindAspectRatio();
+ // bottom plane
+ m_vecFrustumNormals[2] = CVector(0.0f, -s, -c);
+ // top plane
+ m_vecFrustumNormals[3] = CVector(0.0f, -s, c);
+
+ if(GetForward().x == 0.0f && GetForward().y == 0.0f)
+ GetForward().x = 0.0001f;
+ else
+ Orientation = Atan2(GetForward().x, GetForward().y);
+
+ CamFrontXNorm = GetForward().x;
+ CamFrontYNorm = GetForward().y;
+ float l = Sqrt(SQR(CamFrontXNorm) + SQR(CamFrontYNorm));
+ if(l == 0.0f)
+ CamFrontXNorm = 1.0f;
+ else{
+ CamFrontXNorm /= l;
+ CamFrontYNorm /= l;
+ }
+}
+
+bool
+CCamera::IsPointVisible(const CVector &center, const CMatrix *mat)
+{
+ RwV3d c;
+ c = *(RwV3d*)&center;
+ RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
+ if(c.y < CDraw::GetNearClipZ()) return false;
+ if(c.y > CDraw::GetFarClipZ()) return false;
+ if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false;
+ if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > 0.0f) return false;
+ if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > 0.0f) return false;
+ if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > 0.0f) return false;
+ return true;
+}
+
+bool
+CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
+{
+ RwV3d c;
+ c = *(RwV3d*)&center;
+ RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
+ if(c.y + radius < CDraw::GetNearClipZ()) return false;
+ if(c.y - radius > CDraw::GetFarClipZ()) return false;
+ if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false;
+ if(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > radius) return false;
+ if(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > radius) return false;
+ if(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > radius) return false;
+ return true;
+}
+
+bool
+CCamera::IsSphereVisible(const CVector &center, float radius)
+{
+ CMatrix mat = m_cameraMatrix;
+ return IsSphereVisible(center, radius, &mat);
+}
+
+bool
+CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat)
+{
+ int i;
+ int frustumTests[6] = { 0 };
+ RwV3dTransformPoints(box, box, 8, &mat->m_matrix);
+
+ for(i = 0; i < 8; i++){
+ if(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++;
+ if(box[i].y > CDraw::GetFarClipZ()) frustumTests[1]++;
+ if(box[i].x*m_vecFrustumNormals[0].x + box[i].y*m_vecFrustumNormals[0].y > 0.0f) frustumTests[2]++;
+ if(box[i].x*m_vecFrustumNormals[1].x + box[i].y*m_vecFrustumNormals[1].y > 0.0f) frustumTests[3]++;
+// Why not test z?
+// if(box[i].y*m_vecFrustumNormals[2].y + box[i].z*m_vecFrustumNormals[2].z > 0.0f) frustumTests[4]++;
+// if(box[i].y*m_vecFrustumNormals[3].y + box[i].z*m_vecFrustumNormals[3].z > 0.0f) frustumTests[5]++;
+ }
+ for(i = 0; i < 6; i++)
+ if(frustumTests[i] == 8)
+ return false; // Box is completely outside of one plane
+ return true;
+}
+
+
+
+CCamPathSplines::CCamPathSplines(void)
+{
+ int i;
+ for(i = 0; i < MAXPATHLENGTH; i++)
+ m_arr_PathData[i] = 0.0f;
+}
+
+
STARTPATCHES
InjectHook(0x42C760, (bool (CCamera::*)(const CVector &center, float radius, const CMatrix *mat))&CCamera::IsSphereVisible, PATCH_JUMP);
InjectHook(0x46FD00, &CCamera::SetFadeColour, PATCH_JUMP);
@@ -343,4 +3374,37 @@ STARTPATCHES
InjectHook(0x46B560, &CCamera::FinishCutscene, PATCH_JUMP);
InjectHook(0x46FF30, &CCamera::SetZoomValueFollowPedScript, PATCH_JUMP);
InjectHook(0x46FF90, &CCamera::SetZoomValueCamStringScript, PATCH_JUMP);
+
+
+ InjectHook(0x46F8E0, &CCamera::ProcessWideScreenOn, PATCH_JUMP);
+ InjectHook(0x46FDE0, &CCamera::SetParametersForScriptInterpolation, PATCH_JUMP);
+ InjectHook(0x46BA20, &CCamera::GetLookingLRBFirstPerson, PATCH_JUMP);
+ InjectHook(0x470D80, &CCamera::StartTransitionWhenNotFinishedInter, PATCH_JUMP);
+ InjectHook(0x46FFF0, &CCamera::StartTransition, PATCH_JUMP);
+ InjectHook(0x46BEB0, &CCamera::InitialiseCameraForDebugMode, PATCH_JUMP);
+ InjectHook(0x471500, &CCamera::TakeControl, PATCH_JUMP);
+ InjectHook(0x4715B0, &CCamera::TakeControlNoEntity, PATCH_JUMP);
+ InjectHook(0x46B3A0, &CCamera::Fade, PATCH_JUMP);
+ InjectHook(0x46FE20, &CCamera::SetPercentAlongCutScene, PATCH_JUMP);
+ InjectHook(0x46B100, &CamShakeNoPos, PATCH_JUMP);
+ InjectHook(0x46B200, &CCamera::CamShake, PATCH_JUMP);
+ InjectHook(0x46F520, &CCamera::ProcessObbeCinemaCameraPed, PATCH_JUMP);
+ InjectHook(0x46F3E0, &CCamera::ProcessObbeCinemaCameraCar, PATCH_JUMP);
+ InjectHook(0x470DA0, &CCamera::StoreValuesDuringInterPol, PATCH_JUMP);
+ InjectHook(0x46B430, &CCamera::DrawBordersForWideScreen, PATCH_JUMP);
+ InjectHook(0x46F990, &CCamera::Restore, PATCH_JUMP);
+ InjectHook(0x46FAE0, &CCamera::RestoreWithJumpCut, PATCH_JUMP);
+ InjectHook(0x46F080, &CCamera::ProcessFade, PATCH_JUMP);
+ InjectHook(0x46EEA0, &CCamera::CalculateDerivedValues, PATCH_JUMP);
+ InjectHook(0x46F1E0, &CCamera::ProcessMusicFade, PATCH_JUMP);
+ InjectHook(0x46D1D0, &CCamera::LoadPathSplines, PATCH_JUMP);
+ InjectHook(0x4712A0, &CCamera::UpdateTargetEntity, PATCH_JUMP);
+ InjectHook(0x46B580, &CCamera::Find3rdPersonCamTargetVector, PATCH_JUMP);
+ InjectHook(0x46BAD0, &CCamera::Init, PATCH_JUMP);
+ InjectHook(0x46C9E0, &CCamera::LoadTrainCamNodes, PATCH_JUMP);
+ InjectHook(0x46F600, &CCamera::Process_Train_Camera_Control, PATCH_JUMP);
+ InjectHook(0x470EA0, &CCamera::UpdateSoundDistances, PATCH_JUMP);
+ InjectHook(0x46BF10, &CCamera::IsItTimeForNewcam, PATCH_JUMP);
+ InjectHook(0x471650, &CCamera::TryToStartNewCamMode, PATCH_JUMP);
+// InjectHook(0x46D3F0, &CCamera::Process, PATCH_JUMP);
ENDPATCHES
diff --git a/src/core/Camera.h b/src/core/Camera.h
index f3e3e661..f21fe913 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -4,13 +4,28 @@
class CEntity;
class CPed;
class CAutomobile;
+class CGarage;
extern int16 &DebugCamMode;
-#define NUMBER_OF_VECTORS_FOR_AVERAGE 2
+enum
+{
+ NUMBER_OF_VECTORS_FOR_AVERAGE = 2,
+ MAX_NUM_OF_SPLINETYPES = 4,
+ MAX_NUM_OF_NODES = 800 // for trains
+};
+
+#define DEFAULT_NEAR (0.9f)
+#define CAM_ZOOM_1STPRS (0.0f)
+#define CAM_ZOOM_1 (1.0f)
+#define CAM_ZOOM_2 (2.0f)
+#define CAM_ZOOM_3 (3.0f)
+#define CAM_ZOOM_TOPDOWN (4.0f)
+#define CAM_ZOOM_CINEMATIC (5.0f)
-struct CCam
+class CCam
{
+public:
enum
{
MODE_NONE = 0,
@@ -230,9 +245,12 @@ static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
static_assert(offsetof(CCam, Front) == 0x140, "CCam: error");
-struct CCamPathSplines
+class CCamPathSplines
{
- float m_arr_PathData[800];
+public:
+ enum {MAXPATHLENGTH=800};
+ float m_arr_PathData[MAXPATHLENGTH];
+ CCamPathSplines(void);
};
struct CTrainCamNode
@@ -296,13 +314,14 @@ enum
enum
{
- CAM_CONTROLLER_0,
- CAM_CONTROLLER_1,
- CAM_CONTROLLER_2
+ CAMCONTROL_GAME,
+ CAMCONTROL_SCRIPT,
+ CAMCONTROL_OBBE
};
-struct CCamera : public CPlaceable
+class CCamera : public CPlaceable
{
+public:
bool m_bAboveGroundTrainNodesLoaded;
bool m_bBelowGroundTrainNodesLoaded;
bool m_bCamDirectlyBehind;
@@ -344,16 +363,12 @@ struct CCamera : public CPlaceable
bool m_bHeadBob;
bool m_bFailedCullZoneTestPreviously;
-bool m_FadeTargetIsSplashScreen;
+ bool m_FadeTargetIsSplashScreen;
bool WorldViewerBeingUsed;
uint8 ActiveCam;
uint32 m_uiCamShakeStart;
uint32 m_uiFirstPersonCamLastInputTime;
-// where are those?
-//bool m_bVehicleSuspenHigh;
-//bool m_bEnable1rstPersonCamCntrlsScript;
-//bool m_bAllow1rstPersonWeaponsCamera;
uint32 m_uiLongestTimeInMill;
uint32 m_uiNumberOfTrainCamNodes;
@@ -369,7 +384,7 @@ bool m_FadeTargetIsSplashScreen;
int m_BlurRed;
int m_BlurType;
-uint32 unknown;
+uint32 unknown; // some counter having to do with music
int m_iWorkOutSpeedThisNumFrames;
int m_iNumFramesSoFar;
@@ -412,20 +427,20 @@ uint32 unknown;
float m_fOldBetaDiff;
float m_fPedZoomValue;
- float m_fPedZoomValueScript;
- float m_fPedZoomValueSmooth;
- float m_fPositionAlongSpline;
- float m_ScreenReductionPercentage;
- float m_ScreenReductionSpeed;
- float m_AlphaForPlayerAnim1rstPerson;
- float Orientation;
- float PedZoomIndicator;
- float PlayerExhaustion;
- float SoundDistUp, SoundDistLeft, SoundDistRight;
- float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;
- float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld;
- float m_fWideScreenReductionAmount;
- float m_fStartingFOVForInterPol;
+ float m_fPedZoomValueScript;
+ float m_fPedZoomValueSmooth;
+ float m_fPositionAlongSpline;
+ float m_ScreenReductionPercentage;
+ float m_ScreenReductionSpeed;
+ float m_AlphaForPlayerAnim1rstPerson;
+ float Orientation;
+ float PedZoomIndicator;
+ float PlayerExhaustion;
+ float SoundDistUp, SoundDistLeft, SoundDistRight;
+ float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;
+ float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld;
+ float m_fWideScreenReductionAmount;
+ float m_fStartingFOVForInterPol;
// not static yet
float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
@@ -435,8 +450,8 @@ uint32 unknown;
CCam Cams[3];
- void *pToGarageWeAreIn;
- void *pToGarageWeAreInForHackAvoidFirstPerson;
+ CGarage *pToGarageWeAreIn;
+ CGarage *pToGarageWeAreInForHackAvoidFirstPerson;
CQueuedMode m_PlayerMode;
CQueuedMode PlayerWeaponMode;
CVector m_PreviousCameraPosition;
@@ -447,17 +462,15 @@ uint32 unknown;
CVector m_vecFixedModeUpOffSet;
CVector m_vecCutSceneOffset;
- // one of those has to go
- CVector m_cvecStartingSourceForInterPol;
- CVector m_cvecStartingTargetForInterPol;
- CVector m_cvecStartingUpForInterPol;
- CVector m_cvecSourceSpeedAtStartInter;
- CVector m_cvecTargetSpeedAtStartInter;
- CVector m_cvecUpSpeedAtStartInter;
- CVector m_vecSourceWhenInterPol;
- CVector m_vecTargetWhenInterPol;
- CVector m_vecUpWhenInterPol;
- //CVector m_vecClearGeometryVec;
+ CVector m_cvecStartingSourceForInterPol;
+ CVector m_cvecStartingTargetForInterPol;
+ CVector m_cvecStartingUpForInterPol;
+ CVector m_cvecSourceSpeedAtStartInter;
+ CVector m_cvecTargetSpeedAtStartInter;
+ CVector m_cvecUpSpeedAtStartInter;
+ CVector m_vecSourceWhenInterPol;
+ CVector m_vecTargetWhenInterPol;
+ CVector m_vecUpWhenInterPol;
CVector m_vecGameCamPos;
CVector SourceDuringInter;
@@ -465,8 +478,8 @@ uint32 unknown;
CVector UpDuringInter;
RwCamera *m_pRwCamera;
CEntity *pTargetEntity;
- CCamPathSplines m_arrPathArray[4];
- CTrainCamNode m_arrTrainCamNode[800];
+ CCamPathSplines m_arrPathArray[MAX_NUM_OF_SPLINETYPES];
+ CTrainCamNode m_arrTrainCamNode[MAX_NUM_OF_NODES];
CMatrix m_cameraMatrix;
bool m_bGarageFixedCamPositionSet;
bool m_vecDoingSpecialInterPolation;
@@ -490,7 +503,7 @@ uint32 unknown;
float m_fScriptPercentageInterToStopMoving;
float m_fScriptPercentageInterToCatchUp;
-uint32 m_fScriptTimeForInterPolation;
+ uint32 m_fScriptTimeForInterPolation;
int16 m_iFadingDirection;
@@ -503,68 +516,97 @@ uint32 m_fScriptTimeForInterPolation;
uint32 m_uiFadeTimeStartedMusic;
static bool &m_bUseMouse3rdPerson;
+#ifdef FREE_CAM
+ static bool bFreeCam;
+#endif
+ // High level and misc
+ void Init(void);
+ void Process(void);
+ void CamControl(void);
+ void UpdateTargetEntity(void);
+ void UpdateSoundDistances(void);
+ void InitialiseCameraForDebugMode(void);
+ void CamShake(float strength, float x, float y, float z);
bool Get_Just_Switched_Status() { return m_bJust_Switched; }
- inline const CMatrix& GetCameraMatrix(void) { return m_cameraMatrix; }
- CVector &GetGameCamPosition(void) { return m_vecGameCamPos; }
- float GetPositionAlongSpline(void) { return m_fPositionAlongSpline; }
- bool IsPointVisible(const CVector &center, const CMatrix *mat);
- bool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);
- bool IsSphereVisible(const CVector &center, float radius);
- bool IsBoxVisible(RwV3d *box, const CMatrix *mat);
- int GetLookDirection(void);
- bool GetLookingForwardFirstPerson(void);
- void Fade(float timeout, int16 direction);
- int GetScreenFadeStatus(void);
- void ProcessFade(void);
- void ProcessMusicFade(void);
- void SetFadeColour(uint8 r, uint8 g, uint8 b);
-
- void CamShake(float strength, float x, float y, float z);
+ // Who's in control
+ void TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller);
+ void TakeControlNoEntity(const CVector &position, int16 typeOfSwitch, int32 controller);
+ void TakeControlWithSpline(int16 typeOfSwitch);
+ void Restore(void);
+ void RestoreWithJumpCut(void);
+ void SetCamPositionForFixedMode(const CVector &Source, const CVector &UppOffSet);
- void SetMotionBlur(int r, int g, int b, int a, int type);
- void SetMotionBlurAlpha(int a);
- void RenderMotionBlur(void);
- void ClearPlayerWeaponMode();
- void CalculateDerivedValues(void);
+ // Transition
+ void StartTransition(int16 mode);
+ void StartTransitionWhenNotFinishedInter(int16 mode);
+ void StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV);
- void DrawBordersForWideScreen(void);
- void Restore(void);
+ // Widescreen borders
void SetWideScreenOn(void);
void SetWideScreenOff(void);
- void SetNearClipScript(float);
-
- float Find3rdPersonQuickAimPitch(void);
+ void ProcessWideScreenOn(void);
+ void DrawBordersForWideScreen(void);
- void TakeControl(CEntity*, int16, int16, int32);
- void TakeControlNoEntity(const CVector&, int16, int32);
- void SetCamPositionForFixedMode(const CVector&, const CVector&);
- bool GetFading();
- int GetFadingDirection();
+ // Obbe's cam
+ bool IsItTimeForNewcam(int32 obbeMode, int32 time);
+ bool TryToStartNewCamMode(int32 obbeMode);
+ void DontProcessObbeCinemaCamera(void);
+ void ProcessObbeCinemaCameraCar(void);
+ void ProcessObbeCinemaCameraPed(void);
- void Init();
- void SetRwCamera(RwCamera*);
- void Process();
+ // Train
+ void LoadTrainCamNodes(char const *name);
+ void Process_Train_Camera_Control(void);
+ // Script
void LoadPathSplines(int file);
- uint32 GetCutSceneFinishTime(void);
void FinishCutscene(void);
+ float GetPositionAlongSpline(void) { return m_fPositionAlongSpline; }
+ uint32 GetCutSceneFinishTime(void);
+ void SetCamCutSceneOffSet(const CVector &pos);
+ void SetPercentAlongCutScene(float percent);
+ void SetParametersForScriptInterpolation(float stopMoving, float catchUp, int32 time);
+ void SetZoomValueFollowPedScript(int16 dist);
+ void SetZoomValueCamStringScript(int16 dist);
+ void SetNearClipScript(float);
- void SetCamCutSceneOffSet(const CVector&);
- void TakeControlWithSpline(short);
- void RestoreWithJumpCut(void);
+ // Fading
+ void ProcessFade(void);
+ void ProcessMusicFade(void);
+ void Fade(float timeout, int16 direction);
+ void SetFadeColour(uint8 r, uint8 g, uint8 b);
+ bool GetFading(void);
+ int GetFadingDirection(void);
+ int GetScreenFadeStatus(void);
+
+ // Motion blur
+ void RenderMotionBlur(void);
+ void SetMotionBlur(int r, int g, int b, int a, int type);
+ void SetMotionBlurAlpha(int a);
+
+ // Player looking and aiming
+ int GetLookDirection(void);
+ bool GetLookingForwardFirstPerson(void);
+ bool GetLookingLRBFirstPerson(void);
void SetCameraDirectlyInFrontForFollowPed_CamOnAString(void);
void SetCameraDirectlyBehindForFollowPed_CamOnAString(void);
- void SetZoomValueFollowPedScript(int16);
- void SetZoomValueCamStringScript(int16);
- void SetNewPlayerWeaponMode(int16, int16, int16);
- void UpdateAimingCoors(CVector const &);
-
- void SetPercentAlongCutScene(float);
- void SetParametersForScriptInterpolation(float, float, int32);
+ void SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom);
+ void ClearPlayerWeaponMode(void);
+ void UpdateAimingCoors(CVector const &coors);
+ void Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target);
+ float Find3rdPersonQuickAimPitch(void);
- void dtor(void) { this->CCamera::~CCamera(); }
+ // Physical camera
+ void SetRwCamera(RwCamera *cam);
+ const CMatrix& GetCameraMatrix(void) { return m_cameraMatrix; }
+ CVector &GetGameCamPosition(void) { return m_vecGameCamPos; }
+ void CalculateDerivedValues(void);
+ bool IsPointVisible(const CVector &center, const CMatrix *mat);
+ bool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);
+ bool IsSphereVisible(const CVector &center, float radius);
+ bool IsBoxVisible(RwV3d *box, const CMatrix *mat);
};
static_assert(offsetof(CCamera, DistanceToWater) == 0xe4, "CCamera: error");
static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error");
@@ -583,3 +625,5 @@ static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
extern CCamera &TheCamera;
void CamShakeNoPos(CCamera*, float);
+void MakeAngleLessThan180(float &Angle);
+void WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle);
diff --git a/src/core/CutsceneMgr.h b/src/core/CutsceneMgr.h
index 381c71c9..7b809964 100644
--- a/src/core/CutsceneMgr.h
+++ b/src/core/CutsceneMgr.h
@@ -29,6 +29,7 @@ public:
static void SetRunning(bool running) { ms_running = running; }
static bool IsRunning(void) { return ms_running; }
static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }
+ static bool UseLodMultiplier(void) { return ms_useLodMultiplier; }
static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; }
static int GetCutsceneTimeInMilleseconds(void) { return 1000.0f * ms_cutsceneTimer; }
static char *GetCutsceneName(void) { return ms_cutsceneName; }
diff --git a/src/core/FrontEndControls.cpp b/src/core/FrontEndControls.cpp
new file mode 100644
index 00000000..866be42f
--- /dev/null
+++ b/src/core/FrontEndControls.cpp
@@ -0,0 +1,1881 @@
+#include "common.h"
+#include "main.h"
+#include "Timer.h"
+#include "Pad.h"
+#include "ControllerConfig.h"
+#include "VisibilityPlugins.h"
+#include "Sprite2d.h"
+#include "Text.h"
+#include "Font.h"
+#include "Frontend.h"
+#include "FrontEndControls.h"
+
+
+void
+CPlaceableShText::Draw(float x, float y)
+{
+ if(m_text == nil)
+ return;
+
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOn();
+ if(m_bDropShadow){
+ CFont::SetDropShadowPosition(m_shadowOffset.x);
+ CFont::SetDropColor(m_shadowColor);
+ }
+ CFont::SetColor(m_color);
+ CFont::PrintString(x+m_position.x, y+m_position.y, m_text);
+ if(m_bDropShadow)
+ CFont::SetDropShadowPosition(0);
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOff();
+}
+
+void
+CPlaceableShText::Draw(const CRGBA &color, float x, float y)
+{
+ if(m_text == nil)
+ return;
+
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOn();
+ if(m_bDropShadow){
+ CFont::SetDropShadowPosition(m_shadowOffset.x);
+ CFont::SetDropColor(m_shadowColor);
+ }
+ CFont::SetColor(color);
+ CFont::PrintString(x+m_position.x, y+m_position.y, m_text);
+ if(m_bDropShadow)
+ CFont::SetDropShadowPosition(0);
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOff();
+}
+
+void
+CPlaceableShTextTwoLines::Draw(float x, float y)
+{
+ if(m_line1.m_text == nil && m_line2.m_text == nil)
+ return;
+
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOn();
+ if(m_bDropShadow){
+ CFont::SetDropShadowPosition(m_shadowOffset.x);
+ CFont::SetDropColor(m_shadowColor);
+ }
+
+ if(m_line1.m_text){
+ CFont::SetColor(m_line1.m_color);
+ CFont::PrintString(x+m_line1.m_position.x, y+m_line1.m_position.y, m_line1.m_text);
+ }
+ if(m_line2.m_text){
+ CFont::SetColor(m_line2.m_color);
+ CFont::PrintString(x+m_line2.m_position.x, y+m_line2.m_position.y, m_line2.m_text);
+ }
+
+ if(m_bDropShadow)
+ CFont::SetDropShadowPosition(0);
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOff();
+}
+
+void
+CPlaceableShTextTwoLines::Draw(const CRGBA &color, float x, float y)
+{
+ if(m_line1.m_text == nil && m_line2.m_text == nil)
+ return;
+
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOn();
+ if(m_bDropShadow){
+ CFont::SetDropShadowPosition(m_shadowOffset.x);
+ CFont::SetDropColor(m_shadowColor);
+ }
+
+ if(m_line1.m_text){
+ CFont::SetColor(color);
+ CFont::PrintString(x+m_line1.m_position.x, y+m_line1.m_position.y, m_line1.m_text);
+ }
+ if(m_line2.m_text){
+ CFont::SetColor(color);
+ CFont::PrintString(x+m_line2.m_position.x, y+m_line2.m_position.y, m_line2.m_text);
+ }
+
+ if(m_bDropShadow)
+ CFont::SetDropShadowPosition(0);
+ if(m_bRightJustify)
+ CFont::SetRightJustifyOff();
+}
+
+void
+CPlaceableShOption::Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight)
+{
+ if(bHighlight)
+ CPlaceableShText::Draw(highlightColor, x, y);
+ else if(m_bSelected)
+ CPlaceableShText::Draw(m_selectedColor, x, y);
+ else
+ CPlaceableShText::Draw(x, y);
+}
+
+void
+CPlaceableShOptionTwoLines::Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight)
+{
+ if(bHighlight)
+ CPlaceableShTextTwoLines::Draw(highlightColor, x, y);
+ else if(m_bSelected)
+ CPlaceableShTextTwoLines::Draw(m_selectedColor, x, y);
+ else
+ CPlaceableShTextTwoLines::Draw(x, y);
+}
+
+void
+CPlaceableSprite::Draw(float x, float y)
+{
+ Draw(m_color, x, y);
+}
+
+void
+CPlaceableSprite::Draw(const CRGBA &color, float x, float y)
+{
+ if(m_pSprite)
+ m_pSprite->Draw(CRect(m_position.x+x, m_position.y+y,
+ m_position.x+x + m_size.x, m_position.y+y + m_size.y),
+ color);
+}
+
+void
+CPlaceableShSprite::Draw(float x, float y)
+{
+ if(m_bDropShadow)
+ m_shadow.Draw(m_shadow.m_color, m_sprite.m_position.x+x, m_sprite.m_position.y+y);
+ m_sprite.Draw(x, y);
+}
+
+
+/*
+ * CMenuPictureAndText
+ */
+
+void
+CMenuPictureAndText::SetNewOldShadowWrapX(bool bWrapX, float newWrapX, float oldWrapX)
+{
+ m_bWrap = bWrapX;
+ m_wrapX = newWrapX;
+ m_oldWrapx = oldWrapX;
+}
+
+void
+CMenuPictureAndText::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale)
+{
+ m_bSetTextScale = bTextScale;
+ m_textScale = newScale;
+ m_oldTextScale = oldScale;
+}
+
+void
+CMenuPictureAndText::SetTextsColor(CRGBA const &color)
+{
+ int i;
+ for(i = 0; i < m_numTexts; i++)
+ m_texts[i].m_color = color;
+}
+
+void
+CMenuPictureAndText::AddText(wchar *text, float positionX, float positionY, CRGBA const &color, bool bRightJustify)
+{
+ int i;
+ if(m_numTexts >= 20)
+ return;
+ i = m_numTexts++;
+ m_texts[i].m_text = text;
+ m_texts[i].m_position.x = positionX;
+ m_texts[i].m_position.y = positionY;
+ m_texts[i].m_color = color;
+ m_texts[i].m_bRightJustify = bRightJustify;
+}
+
+void
+CMenuPictureAndText::AddPicture(CSprite2d *sprite, CSprite2d *shadow, float positionX, float positionY, float width, float height, CRGBA const &color)
+{
+ int i;
+ if(m_numSprites >= 5)
+ return;
+ i = m_numSprites++;
+ m_sprites[i].m_sprite.m_pSprite = sprite;
+ m_sprites[i].m_shadow.m_pSprite = shadow;
+ m_sprites[i].m_sprite.m_position.x = positionX;
+ m_sprites[i].m_sprite.m_position.y = positionY;
+ m_sprites[i].m_sprite.m_size.x = width;
+ m_sprites[i].m_sprite.m_size.y = height;
+ m_sprites[i].m_shadow.m_size.x = width;
+ m_sprites[i].m_shadow.m_size.y = height;
+ m_sprites[i].m_sprite.m_color = color;
+}
+
+void
+CMenuPictureAndText::AddPicture(CSprite2d *sprite, float positionX, float positionY, float width, float height, CRGBA const &color)
+{
+ int i;
+ if(m_numSprites >= 5)
+ return;
+ i = m_numSprites++;
+ m_sprites[i].m_sprite.m_pSprite = sprite;
+ m_sprites[i].m_shadow.m_pSprite = nil;
+ m_sprites[i].m_sprite.m_position.x = positionX;
+ m_sprites[i].m_sprite.m_position.y = positionY;
+ m_sprites[i].m_sprite.m_size.x = width;
+ m_sprites[i].m_sprite.m_size.y = height;
+ m_sprites[i].m_shadow.m_size.x = width;
+ m_sprites[i].m_shadow.m_size.y = height;
+ m_sprites[i].m_sprite.m_color = color;
+}
+
+void
+CMenuPictureAndText::Draw(CRGBA const &,CRGBA const &, float x, float y)
+{
+ int i;
+
+ for(i = 0; i < m_numSprites; i++)
+ m_sprites[i].Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ for(i = 0; i < m_numTexts; i++)
+ if(m_bWrap)
+ m_texts[i].DrawShWrap(m_position.x+x, m_position.y+y, m_wrapX, m_oldWrapx);
+ else
+ m_texts[i].Draw(m_position.x+x, m_position.y+y);
+ if(m_bSetTextScale)
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+}
+
+void
+CMenuPictureAndText::SetAlpha(uint8 alpha)
+{
+ int i;
+
+ for(i = 0; i < m_numSprites; i++)
+ m_sprites[i].SetAlpha(alpha);
+ for(i = 0; i < m_numTexts; i++)
+ m_texts[i].SetAlpha(alpha);
+}
+
+void
+CMenuPictureAndText::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)
+{
+ int i;
+
+ for(i = 0; i < 5; i++)
+ m_sprites[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+ for(i = 0; i < 20; i++)
+ m_texts[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+/*
+ * CMenuMultiChoice
+ */
+
+void
+CMenuMultiChoice::AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify)
+{
+ m_title.m_text = text;
+ m_title.SetPosition(positionX, positionY, bRightJustify);
+}
+
+CPlaceableShOption*
+CMenuMultiChoice::AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify)
+{
+ if(m_numOptions == NUM_MULTICHOICE_OPTIONS)
+ return nil;
+ m_options[m_numOptions].m_text = text;
+ m_options[m_numOptions].SetPosition(positionX, positionY);
+ m_options[m_numOptions].m_bSelected = bSelected;
+ m_options[m_numOptions].m_bRightJustify = bRightJustify;
+ return &m_options[m_numOptions++];
+}
+
+void
+CMenuMultiChoice::SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected)
+{
+ int i;
+ m_title.SetColor(title);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetColors(normal, selected);
+}
+
+void
+CMenuMultiChoice::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)
+{
+ m_bSetTextScale = bTextScale;
+ m_textScale = newScale;
+ m_oldTextScale = oldScale;
+ m_bSetTitleTextScale = bTitleTextScale;
+}
+
+void
+CMenuMultiChoice::Draw(CRGBA const &optionHighlight ,CRGBA const &titleHighlight, float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_cursor == -1)
+ m_title.Draw(m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ if(m_cursor == -1)
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+ else
+ for(i = 0; i < m_numOptions; i++){
+ if(i == m_cursor)
+ m_options[i].Draw(optionHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+ }
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoice::DrawNormal(float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ m_title.Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoice::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_cursor == -1)
+ m_title.Draw(m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoice::SetAlpha(uint8 alpha)
+{
+ int i;
+ m_title.SetAlpha(alpha);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetAlpha(alpha);
+}
+
+void
+CMenuMultiChoice::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)
+{
+ int i;
+ m_title.SetShadows(bDropShadows, shadowColor, shadowOffset);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+
+bool
+CMenuMultiChoice::GoNext(void)
+{
+ if(m_cursor == m_numOptions-1){
+ m_cursor = -1;
+ return false;
+ }else{
+ m_cursor++;
+ return true;
+ }
+}
+
+bool
+CMenuMultiChoice::GoPrev(void)
+{
+ if(m_cursor == 0){
+ m_cursor = -1;
+ return false;
+ }else{
+ m_cursor--;
+ return true;
+ }
+}
+
+void
+CMenuMultiChoice::SelectCurrentOptionUnderCursor(void)
+{
+ int i;
+ if(m_cursor == -1)
+ return;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].m_bSelected = false;
+ m_options[m_cursor].m_bSelected = true;
+}
+
+int
+CMenuMultiChoice::GetMenuSelection(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ if(m_options[i].m_bSelected)
+ return i;
+ return -1;
+}
+
+void
+CMenuMultiChoice::SetMenuSelection(int selection)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].m_bSelected = false;
+ m_options[selection%NUM_MULTICHOICE_OPTIONS].m_bSelected = true;
+}
+
+/*
+ * CMenuMultiChoiceTriggered
+ */
+
+void
+CMenuMultiChoiceTriggered::Initialise(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_triggers[i] = nil;
+ m_defaultCancel = nil;
+}
+
+CPlaceableShOption*
+CMenuMultiChoiceTriggered::AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify)
+{
+ CPlaceableShOption *option;
+ option = CMenuMultiChoice::AddOption(text, positionX, positionY, bSelected, bRightJustify);
+ if(option)
+ m_triggers[m_numOptions-1] = trigger;
+ return option;
+}
+
+void
+CMenuMultiChoiceTriggered::SelectCurrentOptionUnderCursor(void)
+{
+ CMenuMultiChoice::SelectCurrentOptionUnderCursor();
+ if(m_cursor != -1)
+ m_triggers[m_cursor](this);
+}
+
+void
+CMenuMultiChoiceTriggered::SelectDefaultCancelAction(void)
+{
+ if(m_defaultCancel)
+ m_defaultCancel(this);
+}
+
+/*
+ * CMenuMultiChoiceTriggeredAlways
+ */
+
+void
+CMenuMultiChoiceTriggeredAlways::Draw(CRGBA const &optionHighlight, CRGBA const &titleHighlight, float x, float y)
+{
+ if(m_alwaysTrigger)
+ m_alwaysTrigger(this);
+ CMenuMultiChoiceTriggered::Draw(optionHighlight, titleHighlight, x, y);
+}
+
+void
+CMenuMultiChoiceTriggeredAlways::DrawNormal(float x, float y)
+{
+ if(m_alwaysNormalTrigger)
+ m_alwaysNormalTrigger(this);
+ CMenuMultiChoiceTriggered::DrawNormal(x, y);
+}
+
+void
+CMenuMultiChoiceTriggeredAlways::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)
+{
+ if(m_alwaysHighlightTrigger)
+ m_alwaysHighlightTrigger(this);
+ CMenuMultiChoiceTriggered::DrawHighlighted(titleHighlight, x, y);
+}
+
+/*
+ * CMenuMultiChoicePictured
+ */
+
+void
+CMenuMultiChoicePictured::Initialise(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_bHasSprite[i] = false;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_sprites[i].m_pSprite = nil;
+}
+
+CPlaceableShOption*
+CMenuMultiChoicePictured::AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, bool bSelected)
+{
+ CPlaceableShOption *option;
+ option = CMenuMultiChoice::AddOption(nil, 0.0f, 0.0f, bSelected, false);
+ if(option){
+ m_sprites[m_numOptions-1].m_pSprite = sprite;
+ m_sprites[m_numOptions-1].SetPosition(positionX, positionY);
+ m_sprites[m_numOptions-1].m_size = size;
+ m_bHasSprite[m_numOptions-1] = true;
+ }
+ return option;
+}
+
+void
+CMenuMultiChoicePictured::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)
+{
+ int i;
+
+ // The title and all the text
+ CMenuMultiChoice::Draw(optionHighlight, titleHighlight, x, y);
+
+ CRGBA selectedColor = m_options[0].GetSelectedColor();
+ CRGBA color = m_options[0].GetColor();
+
+ // The sprites
+ if(m_cursor == -1){
+ for(i = 0; i < m_numOptions; i++)
+ if(m_bHasSprite[i]){
+ if(m_options[i].m_bSelected)
+ m_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);
+ else
+ m_sprites[i].Draw(color, m_position.x+x, m_position.y+y);
+ }
+ }else{
+ for(i = 0; i < m_numOptions; i++)
+ if(i == m_cursor){
+ if(m_bHasSprite[i])
+ m_sprites[i].Draw(CRGBA(255, 255, 255, 255), m_position.x+x, m_position.y+y);
+ }else{
+ if(m_bHasSprite[i]){
+ if(m_options[i].m_bSelected)
+ m_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);
+ else
+ m_sprites[i].Draw(color, m_position.x+x, m_position.y+y);
+ }
+ }
+ }
+}
+
+void
+CMenuMultiChoicePictured::DrawNormal(float x, float y)
+{
+ int i;
+
+ // The title and all the text
+ CMenuMultiChoice::DrawNormal(x, y);
+
+ CRGBA selectedColor = m_options[0].GetSelectedColor();
+ CRGBA color = m_options[0].GetColor();
+
+ // The sprites
+ for(i = 0; i < m_numOptions; i++)
+ if(m_bHasSprite[i]){
+ if(m_options[i].m_bSelected)
+ m_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);
+ else
+ m_sprites[i].Draw(color, m_position.x+x, m_position.y+y);
+ }
+}
+
+void
+CMenuMultiChoicePictured::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)
+{
+ int i;
+
+ // The title and all the text
+ CMenuMultiChoice::DrawHighlighted(titleHighlight, x, y);
+
+ CRGBA selectedColor = m_options[0].GetSelectedColor();
+ CRGBA color = m_options[0].GetColor();
+
+ // The sprites
+ for(i = 0; i < m_numOptions; i++)
+ if(m_bHasSprite[i]){
+ if(m_options[i].m_bSelected)
+ m_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);
+ else
+ m_sprites[i].Draw(color, m_position.x+x, m_position.y+y);
+ }
+}
+
+void
+CMenuMultiChoicePictured::SetAlpha(uint8 alpha)
+{
+ int i;
+ CMenuMultiChoice::SetAlpha(alpha);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_sprites[i].SetAlpha(alpha);
+
+}
+
+
+/*
+ * CMenuMultiChoicePicturedTriggered
+ */
+
+void
+CMenuMultiChoicePicturedTriggered::Initialise(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_triggers[i] = nil;
+ m_defaultCancel = nil; // missing on PS2
+}
+
+CPlaceableShOption*
+CMenuMultiChoicePicturedTriggered::AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected)
+{
+ CPlaceableShOption *option;
+ option = CMenuMultiChoicePictured::AddOption(sprite, positionX, positionY, size, bSelected);
+ if(option)
+ m_triggers[m_numOptions-1] = trigger;
+ return option;
+}
+
+void
+CMenuMultiChoicePicturedTriggered::SelectCurrentOptionUnderCursor(void)
+{
+ CMenuMultiChoice::SelectCurrentOptionUnderCursor();
+ if(m_cursor != -1)
+ m_triggers[m_cursor](this);
+}
+
+void
+CMenuMultiChoicePicturedTriggered::SelectDefaultCancelAction(void)
+{
+ if(m_defaultCancel)
+ m_defaultCancel(this);
+}
+
+/*
+ * CMenuMultiChoicePicturedTriggeredAnyMove
+ */
+
+void
+CMenuMultiChoicePicturedTriggeredAnyMove::Initialise(void)
+{
+ int i;
+ CMenuMultiChoicePicturedTriggered::Initialise();
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++){
+ m_moveTab[i].right = -1;
+ m_moveTab[i].left = -1;
+ m_moveTab[i].down = -1;
+ m_moveTab[i].up = -1;
+ }
+}
+
+CPlaceableShOption*
+CMenuMultiChoicePicturedTriggeredAnyMove::AddOption(CSprite2d *sprite, FEC_MOVETAB *moveTab, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected)
+{
+ CPlaceableShOption *option;
+ option = CMenuMultiChoicePicturedTriggered::AddOption(sprite, positionX, positionY, size, trigger, bSelected);
+ if(option && moveTab)
+ m_moveTab[m_numOptions-1] = *moveTab;
+ return option;
+}
+
+bool
+CMenuMultiChoicePicturedTriggeredAnyMove::GoDown(void)
+{
+ int move = m_moveTab[m_cursor].down;
+ if(move == -1)
+ return GoNext();
+ m_cursor = move;
+ return true;
+}
+
+bool
+CMenuMultiChoicePicturedTriggeredAnyMove::GoUp(void)
+{
+ int move = m_moveTab[m_cursor].up;
+ if(move == -1)
+ return GoPrev();
+ m_cursor = move;
+ return true;
+}
+
+bool
+CMenuMultiChoicePicturedTriggeredAnyMove::GoLeft(void)
+{
+ int move = m_moveTab[m_cursor].left;
+ if(move == -1)
+ return GoPrev();
+ m_cursor = move;
+ return true;
+}
+
+bool
+CMenuMultiChoicePicturedTriggeredAnyMove::GoRight(void)
+{
+ int move = m_moveTab[m_cursor].right;
+ if(move == -1)
+ return GoNext();
+ m_cursor = move;
+ return true;
+}
+
+
+/*
+ * CMenuMultiChoiceTwoLines
+ */
+
+void
+CMenuMultiChoiceTwoLines::AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify)
+{
+ m_title.m_text = text;
+ m_title.SetPosition(positionX, positionY, bRightJustify);
+}
+
+CPlaceableShOptionTwoLines*
+CMenuMultiChoiceTwoLines::AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify)
+{
+ return AddOption(text, positionX, positionY, nil, 0.0f, 0.0f, bSelected, bRightJustify);
+}
+
+CPlaceableShOptionTwoLines*
+CMenuMultiChoiceTwoLines::AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, bool bSelected, bool bRightJustify)
+{
+ if(m_numOptions == NUM_MULTICHOICE_OPTIONS)
+ return nil;
+ m_options[m_numOptions].m_line1.m_text = text1;
+ m_options[m_numOptions].m_line2.m_text = text2;
+ m_options[m_numOptions].m_line1.SetPosition(positionX1, positionY1);
+ m_options[m_numOptions].m_line2.SetPosition(positionX2, positionY2);
+ m_options[m_numOptions].m_bSelected = bSelected;
+ m_options[m_numOptions].m_bRightJustify = bRightJustify;
+ return &m_options[m_numOptions++];
+}
+
+
+void
+CMenuMultiChoiceTwoLines::SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected)
+{
+ int i;
+ m_title.SetColor(title);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetColors(normal, selected);
+}
+
+void
+CMenuMultiChoiceTwoLines::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)
+{
+ m_bSetTextScale = bTextScale;
+ m_textScale = newScale;
+ m_oldTextScale = oldScale;
+ m_bSetTitleTextScale = bTitleTextScale;
+}
+
+void
+CMenuMultiChoiceTwoLines::Draw(CRGBA const &optionHighlight ,CRGBA const &titleHighlight, float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_cursor == -1)
+ m_title.Draw(m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ if(m_cursor == -1)
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+ else
+ for(i = 0; i < m_numOptions; i++){
+ if(i == m_cursor)
+ m_options[i].Draw(optionHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+ }
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoiceTwoLines::DrawNormal(float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ m_title.Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoiceTwoLines::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)
+{
+ int i;
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_cursor == -1)
+ m_title.Draw(m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ for(i = 0; i < m_numOptions; i++)
+ m_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale){
+ CFont::DrawFonts();
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+ }
+}
+
+void
+CMenuMultiChoiceTwoLines::SetAlpha(uint8 alpha)
+{
+ int i;
+ m_title.SetAlpha(alpha);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetAlpha(alpha);
+}
+
+void
+CMenuMultiChoiceTwoLines::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)
+{
+ int i;
+ m_title.SetShadows(bDropShadows, shadowColor, shadowOffset);
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+
+bool
+CMenuMultiChoiceTwoLines::GoNext(void)
+{
+ if(m_cursor == m_numOptions-1){
+ m_cursor = -1;
+ return false;
+ }else{
+ m_cursor++;
+ return true;
+ }
+}
+
+bool
+CMenuMultiChoiceTwoLines::GoPrev(void)
+{
+ if(m_cursor == 0){
+ m_cursor = -1;
+ return false;
+ }else{
+ m_cursor--;
+ return true;
+ }
+}
+
+void
+CMenuMultiChoiceTwoLines::SelectCurrentOptionUnderCursor(void)
+{
+ int i;
+ if(m_cursor == -1)
+ return;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].m_bSelected = false;
+ m_options[m_cursor].m_bSelected = true;
+}
+
+int
+CMenuMultiChoiceTwoLines::GetMenuSelection(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ if(m_options[i].m_bSelected)
+ return i;
+ return -1;
+}
+
+void
+CMenuMultiChoiceTwoLines::SetMenuSelection(int selection)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_options[i].m_bSelected = false;
+ m_options[selection%NUM_MULTICHOICE_OPTIONS].m_bSelected = true;
+}
+
+/*
+ * CMenuMultiChoiceTwoLinesTriggered
+ */
+
+void
+CMenuMultiChoiceTwoLinesTriggered::Initialise(void)
+{
+ int i;
+ for(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)
+ m_triggers[i] = nil;
+ m_defaultCancel = nil;
+}
+
+CPlaceableShOptionTwoLines*
+CMenuMultiChoiceTwoLinesTriggered::AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify)
+{
+ CPlaceableShOptionTwoLines *option;
+ option = CMenuMultiChoiceTwoLines::AddOption(text, positionX, positionY, bSelected, bRightJustify);
+ if(option)
+ m_triggers[m_numOptions-1] = trigger;
+ return option;
+}
+
+CPlaceableShOptionTwoLines*
+CMenuMultiChoiceTwoLinesTriggered::AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, Trigger trigger, bool bSelected, bool bRightJustify)
+{
+ CPlaceableShOptionTwoLines *option;
+ option = CMenuMultiChoiceTwoLines::AddOption(text1, positionX1, positionY1, text2, positionX2, positionY2, bSelected, bRightJustify);
+ if(option)
+ m_triggers[m_numOptions-1] = trigger;
+ return option;
+}
+
+void
+CMenuMultiChoiceTwoLinesTriggered::SelectCurrentOptionUnderCursor(void)
+{
+ CMenuMultiChoiceTwoLines::SelectCurrentOptionUnderCursor();
+ if(m_cursor != -1)
+ m_triggers[m_cursor](this);
+}
+
+void
+CMenuMultiChoiceTwoLinesTriggered::SelectDefaultCancelAction(void)
+{
+ if(m_defaultCancel)
+ m_defaultCancel(this);
+}
+
+
+/*
+ * CMenuOnOff
+ */
+
+void
+CMenuOnOff::SetColors(const CRGBA &title, const CRGBA &options)
+{
+ m_title.SetColors(title, title);
+ m_options[0].SetColor(options);
+ m_options[1].SetColor(options);
+}
+
+void
+CMenuOnOff::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)
+{
+ m_bSetTextScale = bTextScale;
+ m_textScale = newScale;
+ m_oldTextScale = oldScale;
+ m_bSetTitleTextScale = bTitleTextScale;
+}
+
+void
+CMenuOnOff::SetOptionPosition(float x, float y, bool bRightJustify)
+{
+ m_options[0].SetPosition(x, y, bRightJustify);
+ m_options[1].SetPosition(x, y, bRightJustify);
+}
+
+void
+CMenuOnOff::AddTitle(wchar *text, bool bSelected, float positionX, float positionY, bool bRightJustify)
+{
+ m_title.m_text = text;
+ m_title.m_bSelected = bSelected;
+ m_title.SetPosition(positionX, positionY, bRightJustify);
+}
+
+void
+CMenuOnOff::Draw(CRGBA const &optionHighlight, CRGBA const &titleHighlight, float x, float y)
+{
+ if(m_type == 1){
+ m_options[0].m_text = TheText.Get("FEM_NO");
+ m_options[1].m_text = TheText.Get("FEM_YES");
+ }else if(m_type == 0){
+ m_options[0].m_text = TheText.Get("FEM_OFF");
+ m_options[1].m_text = TheText.Get("FEM_ON");
+ }
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_bActive)
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ if(m_bActive){
+ if(m_title.m_bSelected)
+ m_options[1].Draw(optionHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_options[0].Draw(optionHighlight, m_position.x+x, m_position.y+y);
+ }else{
+ if(m_title.m_bSelected)
+ m_options[1].Draw(m_position.x+x, m_position.y+y);
+ else
+ m_options[0].Draw(m_position.x+x, m_position.y+y);
+ }
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+}
+
+void
+CMenuOnOff::DrawNormal(float x, float y)
+{
+ if(m_type == 1){
+ m_options[0].m_text = TheText.Get("FEM_NO");
+ m_options[1].m_text = TheText.Get("FEM_YES");
+ }else if(m_type == 0){
+ m_options[0].m_text = TheText.Get("FEM_OFF");
+ m_options[1].m_text = TheText.Get("FEM_ON");
+ }
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ m_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ if(m_title.m_bSelected)
+ m_options[1].Draw(m_position.x+x, m_position.y+y);
+ else
+ m_options[0].Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+}
+
+void
+CMenuOnOff::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)
+{
+ if(m_type == 1){
+ m_options[0].m_text = TheText.Get("FEM_NO");
+ m_options[1].m_text = TheText.Get("FEM_YES");
+ }else if(m_type == 0){
+ m_options[0].m_text = TheText.Get("FEM_OFF");
+ m_options[1].m_text = TheText.Get("FEM_ON");
+ }
+
+ if(m_bSetTextScale && m_bSetTitleTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+ if(m_bActive)
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_textScale.x, m_textScale.y);
+
+ if(m_title.m_bSelected)
+ m_options[1].Draw(m_position.x+x, m_position.y+y);
+ else
+ m_options[0].Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bSetTextScale)
+ CFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);
+}
+
+void
+CMenuOnOff::SetAlpha(uint8 alpha)
+{
+ m_title.SetAlpha(alpha);
+ m_options[0].SetAlpha(alpha);
+ m_options[1].SetAlpha(alpha);
+}
+
+void
+CMenuOnOff::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)
+{
+ m_title.SetShadows(bDropShadows, shadowColor, shadowOffset);
+ m_options[0].SetShadows(bDropShadows, shadowColor, shadowOffset);
+ m_options[1].SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+/*
+ * CMenuOnOffTriggered
+ */
+
+void
+CMenuOnOffTriggered::SetOptionPosition(float x, float y, Trigger trigger, bool bRightJustify)
+{
+ CMenuOnOff::SetOptionPosition(x, y, bRightJustify);
+ if(trigger)
+ m_trigger = trigger;
+}
+
+void
+CMenuOnOffTriggered::SelectCurrentOptionUnderCursor(void)
+{
+ CMenuOnOff::SelectCurrentOptionUnderCursor();
+ if(m_trigger)
+ m_trigger(this);
+}
+
+
+
+/*
+ * CMenuSlider
+ */
+
+char CMenuSlider::Buf8[8];
+wchar CMenuSlider::Buf16[8];
+
+void
+CMenuSlider::SetColors(const CRGBA &title, const CRGBA &percentage, const CRGBA &left, const CRGBA &right)
+{
+ m_title.SetColor(title);
+ m_percentageText.SetColor(percentage);
+ m_colors[0] = left;
+ m_colors[1] = right;
+}
+
+
+void
+CMenuSlider::AddTickBox(float positionX, float positionY, float width, float heightLeft, float heightRight)
+{
+ m_box.SetPosition(positionX, positionY);
+ m_size[0].x = width;
+ m_size[0].y = heightLeft;
+ m_size[1].x = width;
+ m_size[1].y = heightRight;
+}
+
+void
+CMenuSlider::AddTitle(wchar *text, float positionX, float positionY)
+{
+ m_title.m_text = text;
+ m_title.SetPosition(positionX, positionY);
+}
+
+static CRGBA SELECTED_TEXT_COLOR_0(255, 182, 48, 255);
+
+void
+CMenuSlider::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)
+{
+ if(m_bActive){
+ CRGBA selectionCol = m_colors[0];
+ if(selectionCol.red == SELECTED_TEXT_COLOR_0.red &&
+ selectionCol.green == SELECTED_TEXT_COLOR_0.green &&
+ selectionCol.blue == SELECTED_TEXT_COLOR_0.blue &&
+ selectionCol.alpha == SELECTED_TEXT_COLOR_0.alpha)
+ selectionCol = m_colors[1];
+
+ if(m_style == 1){
+ // solid bar
+ CRGBA shadowCol = m_box.GetShadowColor();
+ float f = m_value/1000.0f;
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ if(m_box.m_bDropShadow)
+ CSprite2d::DrawRect(
+ CRect(boxPos.x + m_box.m_shadowOffset.x,
+ boxPos.y + m_box.m_shadowOffset.y,
+ boxPos.x + m_box.m_shadowOffset.x + m_size[0].x,
+ boxPos.y + m_box.m_shadowOffset.y + m_size[0].y),
+ shadowCol);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),
+ m_colors[1]);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),
+ selectionCol);
+ }else if(m_style == 0){
+ // ticks...
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ DrawTicks(boxPos, m_size[0], m_size[1].y,
+ m_value/1000.0f, m_colors[0], selectionCol, m_colors[1],
+ m_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());
+ }
+
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+
+ if(m_bDrawPercentage){
+ sprintf(Buf8, "%d%%", m_value/10);
+ AsciiToUnicode(Buf8, Buf16);
+ m_percentageText.m_text = Buf16;
+ m_percentageText.Draw(optionHighlight, m_position.x+x, m_position.y+y);
+ }
+ }else
+ CMenuSlider::DrawNormal(x, y);
+}
+
+void
+CMenuSlider::DrawNormal(float x, float y)
+{
+ if(m_style == 1){
+ // solid bar
+ CRGBA shadowCol = m_box.GetShadowColor();
+ float f = m_value/1000.0f;
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ if(m_box.m_bDropShadow)
+ CSprite2d::DrawRect(
+ CRect(boxPos.x + m_box.m_shadowOffset.x,
+ boxPos.y + m_box.m_shadowOffset.y,
+ boxPos.x + m_box.m_shadowOffset.x + m_size[0].x,
+ boxPos.y + m_box.m_shadowOffset.y + m_size[0].y),
+ shadowCol);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),
+ m_colors[1]);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),
+ m_colors[0]);
+ }else if(m_style == 0){
+ // ticks...
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ DrawTicks(boxPos, m_size[0], m_size[1].y,
+ m_value/1000.0f, m_colors[0], m_colors[1],
+ m_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());
+ }
+
+ m_title.Draw(m_position.x+x, m_position.y+y);
+
+ if(m_bDrawPercentage){
+ sprintf(Buf8, "%d%%", m_value/10);
+ AsciiToUnicode(Buf8, Buf16);
+ m_percentageText.m_text = Buf16;
+ m_percentageText.Draw(m_percentageText.GetColor(), m_position.x+x, m_position.y+y);
+ }
+}
+
+void
+CMenuSlider::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)
+{
+ if(m_bActive)
+ m_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);
+ else
+ m_title.Draw(m_position.x+x, m_position.y+y);
+
+ if(m_style == 1){
+ // solid bar
+ CRGBA shadowCol = m_box.GetShadowColor();
+ float f = m_value/1000.0f;
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ if(m_box.m_bDropShadow)
+ CSprite2d::DrawRect(
+ CRect(boxPos.x + m_box.m_shadowOffset.x,
+ boxPos.y + m_box.m_shadowOffset.y,
+ boxPos.x + m_box.m_shadowOffset.x + m_size[0].x,
+ boxPos.y + m_box.m_shadowOffset.y + m_size[0].y),
+ shadowCol);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),
+ m_colors[1]);
+ CSprite2d::DrawRect(
+ CRect(boxPos.x, boxPos.y,
+ boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),
+ m_colors[0]);
+ }else if(m_style == 0){
+ // ticks...
+ CVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);
+ DrawTicks(boxPos, m_size[0], m_size[1].y,
+ m_value/1000.0f, m_colors[0], m_colors[1],
+ m_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());
+ }
+
+ if(m_bDrawPercentage){
+ sprintf(Buf8, "%d%%", m_value/10);
+ AsciiToUnicode(Buf8, Buf16);
+ m_percentageText.m_text = Buf16;
+ m_percentageText.Draw(m_percentageText.GetColor(), m_position.x+x, m_position.y+y);
+ }
+}
+
+void
+CMenuSlider::DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &selCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor)
+{
+ int i;
+ int numTicks = size.x / 8.0f;
+ float dy = heightRight - size.y;
+ float stepy = dy / numTicks;
+ int left = level*numTicks;
+ int drewSelection = 0;
+ for(i = 0; i < numTicks; i++){
+ CRect rect(position.x + 8.0f*i, position.y + dy - stepy*i,
+ position.x + 8.0f*i + 4.0f, position.y + dy + size.y);
+ if(bShadow){
+ CRect shadowRect = rect;
+ shadowRect.left += shadowOffset.x;
+ shadowRect.right += shadowOffset.x;
+ shadowRect.top += shadowOffset.y;
+ shadowRect.bottom += shadowOffset.y;
+ CSprite2d::DrawRect(shadowRect, shadowColor);
+ }
+ if(i < left)
+ CSprite2d::DrawRect(rect, leftCol);
+ else if(!drewSelection){
+ CSprite2d::DrawRect(rect, selCol);
+ drewSelection = 1;
+ }else
+ CSprite2d::DrawRect(rect, rightCol);
+ }
+}
+
+void
+CMenuSlider::DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor)
+{
+ int i;
+ int numTicks = size.x / 8.0f;
+ float dy = heightRight - size.y;
+ float stepy = dy / numTicks;
+ int left = level*numTicks;
+ for(i = 0; i < numTicks; i++){
+ CRect rect(position.x + 8.0f*i, position.y + dy - stepy*i,
+ position.x + 8.0f*i + 4.0f, position.y + dy + size.y);
+ if(bShadow){
+ CRect shadowRect = rect;
+ shadowRect.left += shadowOffset.x;
+ shadowRect.right += shadowOffset.x;
+ shadowRect.top += shadowOffset.y;
+ shadowRect.bottom += shadowOffset.y;
+ CSprite2d::DrawRect(shadowRect, shadowColor);
+ }
+ if(i < left)
+ CSprite2d::DrawRect(rect, leftCol);
+ else
+ CSprite2d::DrawRect(rect, rightCol);
+ }
+}
+
+void
+CMenuSlider::SetAlpha(uint8 alpha)
+{
+ m_title.SetAlpha(alpha);
+ m_box.SetAlpha(alpha);
+ m_someAlpha = alpha;
+ m_percentageText.SetAlpha(alpha);
+ m_colors[0].alpha = alpha;
+ m_colors[1].alpha = alpha;
+}
+
+void
+CMenuSlider::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)
+{
+ m_title.SetShadows(bDropShadows, shadowColor, shadowOffset);
+ m_box.SetShadows(bDropShadows, shadowColor, shadowOffset);
+ m_percentageText.SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+/*
+ * CMenuSliderTriggered
+ */
+
+void
+CMenuSliderTriggered::AddTickBox(float positionX, float positionY, float width, float heightLeft, float heightRight, Trigger trigger, Trigger alwaysTrigger)
+{
+ CMenuSlider::AddTickBox(positionX, positionY, width, heightLeft, heightRight);
+ m_trigger = trigger;
+ m_alwaysTrigger = alwaysTrigger;
+}
+
+void
+CMenuSliderTriggered::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)
+{
+ CMenuSlider::Draw(optionHighlight, titleHighlight, x, y);
+ if(m_alwaysTrigger)
+ m_alwaysTrigger(this);
+}
+
+bool
+CMenuSliderTriggered::GoLeft(void)
+{
+ CMenuSlider::GoLeft();
+ if(m_trigger)
+ m_trigger(this);
+ return true;
+}
+
+bool
+CMenuSliderTriggered::GoRight(void)
+{
+ CMenuSlider::GoRight();
+ if(m_trigger)
+ m_trigger(this);
+ return true;
+}
+
+bool
+CMenuSliderTriggered::GoLeftStill(void)
+{
+ CMenuSlider::GoLeftStill();
+ if(m_trigger)
+ m_trigger(this);
+ return true;
+}
+
+bool
+CMenuSliderTriggered::GoRightStill(void)
+{
+ CMenuSlider::GoRightStill();
+ if(m_trigger)
+ m_trigger(this);
+ return true;
+}
+
+/*
+ * CMenuLineLister
+ */
+
+CMenuLineLister::CMenuLineLister(void)
+ : m_numLines(0), m_width(0.0f), m_height(0.0f),
+ m_scrollPosition(0.0f), m_scrollSpeed(1.0f), m_lineSpacing(15.0f), field_10E8(0)
+{
+ int i;
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ m_lineAlphas[i] = 0;
+ m_lineFade[i] = 0;
+ }
+}
+
+
+void
+CMenuLineLister::SetLinesColor(const CRGBA &color)
+{
+ int i;
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ m_linesLeft[i].SetColor(color);
+ m_linesRight[i].SetColor(color);
+ }
+}
+
+void
+CMenuLineLister::ResetNumberOfTextLines(void)
+{
+ int i;
+ m_numLines = 0;
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ m_lineAlphas[i] = 0;
+ m_lineFade[i] = 0;
+ }
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ // note this doesn't clear lines 0-14, probably an oversight
+ GetLeftLine(i)->m_text = nil;
+ GetRightLine(i)->m_text = nil;
+ }
+}
+
+bool
+CMenuLineLister::AddTextLine(wchar *left, wchar *right)
+{
+ CPlaceableShText *leftLine, *rightLine;
+ if(m_numLines == NUM_LINELISTER_LINES)
+ return false;
+ leftLine = GetLeftLine(m_numLines);
+ leftLine->m_text = left;
+ leftLine->SetPosition(0.0f, m_lineSpacing*(m_numLines+15));
+ rightLine = GetRightLine(m_numLines);
+ rightLine->m_text = right;
+ rightLine->SetPosition(leftLine->m_position.x, leftLine->m_position.y);
+ m_numLines++;
+ return true;
+}
+
+void
+CMenuLineLister::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)
+{
+ int i, n;
+
+ m_scrollPosition += m_scrollSpeed;
+ n = m_numLines + 15;
+ if(m_scrollSpeed > 0.0f){
+ if(m_scrollPosition > n*m_lineSpacing)
+ m_scrollPosition = 0.0f;
+ }else{
+ if(m_scrollPosition < 0.0f)
+ m_scrollPosition = n*m_lineSpacing;
+ }
+ // this is a weird condition....
+ for(i = 0;
+ m_scrollPosition < i*m_lineSpacing || m_scrollPosition >= (i+1)*m_lineSpacing;
+ i++);
+
+ float screenPos = 0.0f;
+ for(; i < n; i++){
+ CVector2D linePos = m_linesLeft[i].m_position;
+
+ if(linePos.y+m_position.y - (m_scrollPosition+m_position.y) < 64.0f)
+ m_lineFade[i] = -4.0f*Abs(m_scrollSpeed);
+ else
+ m_lineFade[i] = 4.0f*Abs(m_scrollSpeed);
+ int newAlpha = m_lineAlphas[i] + m_lineFade[i];
+ if(newAlpha < 0) newAlpha = 0;
+ if(newAlpha > 255) newAlpha = 255;
+ m_lineAlphas[i] = newAlpha;
+
+ uint8 alpha = m_linesLeft[i].m_shadowColor.alpha;
+
+ // apply alpha
+ m_linesLeft[i].SetAlpha((alpha*m_lineAlphas[i])>>8);
+ m_linesRight[i].SetAlpha((alpha*m_lineAlphas[i])>>8);
+
+ m_linesLeft[i].Draw(m_position.x+x, m_position.y+y - m_scrollPosition);
+ CFont::SetRightJustifyOn();
+ m_linesRight[i].Draw(m_position.x+x + m_width, m_position.y+y - m_scrollPosition);
+ CFont::SetRightJustifyOff();
+
+ // restore alpha
+ m_linesLeft[i].SetAlpha(alpha);
+ m_linesRight[i].SetAlpha(alpha);
+
+ screenPos += m_lineSpacing;
+ if(screenPos >= m_height)
+ break;
+ }
+
+ m_scrollSpeed = 1.0f;
+}
+
+void
+CMenuLineLister::SetAlpha(uint8 alpha)
+{
+ int i;
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ m_linesLeft[i].SetAlpha(alpha);
+ m_linesRight[i].SetAlpha(alpha);
+ }
+}
+
+void
+CMenuLineLister::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)
+{
+ int i;
+ for(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){
+ m_linesLeft[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+ m_linesRight[i].SetShadows(bDropShadows, shadowColor, shadowOffset);
+ }
+}
+
+
+/*
+ * CMenuPage
+ */
+
+void
+CMenuPage::Initialise(void)
+{
+ int i;
+ m_numControls = 0;
+ m_pCurrentControl = nil;
+ m_cursor = 0;
+ for(i = 0; i < NUM_PAGE_WIDGETS; i++)
+ m_controls[i] = nil;
+}
+
+bool
+CMenuPage::AddMenu(CMenuBase *widget)
+{
+ if(m_numControls >= NUM_PAGE_WIDGETS)
+ return false;
+ m_controls[m_numControls] = widget;
+ if(m_numControls == 0){
+ m_pCurrentControl = widget;
+ m_cursor = 0;
+ }
+ m_numControls++;
+ return true;
+}
+
+bool
+CMenuPage::IsActiveMenuTwoState(void)
+{
+ return m_pCurrentControl && m_pCurrentControl->m_bTwoState;
+}
+
+void
+CMenuPage::ActiveMenuTwoState_SelectNextPosition(void)
+{
+ int sel;
+ if(m_pCurrentControl == nil || !m_pCurrentControl->m_bTwoState)
+ return;
+ m_pCurrentControl->GoFirst();
+ sel = m_pCurrentControl->GetMenuSelection();
+ if(sel == 1)
+ m_pCurrentControl->SelectCurrentOptionUnderCursor();
+ else if(sel == 0){
+ m_pCurrentControl->GoNext();
+ m_pCurrentControl->SelectCurrentOptionUnderCursor();
+ }
+}
+
+void
+CMenuPage::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)
+{
+ int i;
+ for(i = 0; i < m_numControls; i++)
+ if(m_controls[i]){
+ if(i == m_cursor)
+ m_controls[i]->Draw(optionHighlight, titleHighlight, x, y);
+ else
+ m_controls[i]->DrawNormal(x, y);
+ }
+}
+
+void
+CMenuPage::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)
+{
+ int i;
+ for(i = 0; i< m_numControls; i++)
+ if(m_controls[i]){
+ if(i == m_cursor)
+ m_controls[i]->DrawHighlighted(titleHighlight, x, y);
+ else
+ m_controls[i]->DrawNormal(x, y);
+ }
+}
+
+void
+CMenuPage::DrawNormal(float x, float y)
+{
+ int i;
+ for(i = 0; i< m_numControls; i++)
+ if(m_controls[i])
+ m_controls[i]->DrawNormal(x, y);
+}
+
+void
+CMenuPage::ActivatePage(void)
+{
+ m_cursor = 0;
+ if(m_numControls == 0)
+ return;
+ for(;;){
+ m_pCurrentControl = m_controls[m_cursor];
+ if(m_pCurrentControl->GoFirst())
+ return;
+ if(m_cursor == m_numControls-1)
+ m_cursor = 0;
+ else
+ m_cursor++;
+ }
+}
+
+void
+CMenuPage::SetAlpha(uint8 alpha)
+{
+ int i;
+ for(i = 0; i< m_numControls; i++)
+ if(m_controls[i])
+ m_controls[i]->SetAlpha(alpha);
+}
+
+void
+CMenuPage::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)
+{
+ int i;
+ for(i = 0; i< m_numControls; i++)
+ if(m_controls[i])
+ m_controls[i]->SetShadows(bDropShadows, shadowColor, shadowOffset);
+}
+
+void
+CMenuPage::GoUpMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ do{
+ if(m_cursor == 0)
+ m_cursor = m_numControls-1;
+ else
+ m_cursor--;
+ m_pCurrentControl = m_controls[m_cursor];
+ }while(!m_pCurrentControl->GoLast());
+}
+
+void
+CMenuPage::GoDownMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ do{
+ if(m_cursor == m_numControls-1)
+ m_cursor = 0;
+ else
+ m_cursor++;
+ m_pCurrentControl = m_controls[m_cursor];
+ }while(!m_pCurrentControl->GoFirst());
+}
+
+void
+CMenuPage::GoLeftMenuOnPage(void)
+{
+ // same as up
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ do{
+ if(m_cursor == 0)
+ m_cursor = m_numControls-1;
+ else
+ m_cursor--;
+ m_pCurrentControl = m_controls[m_cursor];
+ }while(!m_pCurrentControl->GoLast());
+}
+
+void
+CMenuPage::GoRightMenuOnPage(void)
+{
+ // same as right
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ do{
+ if(m_cursor == m_numControls-1)
+ m_cursor = 0;
+ else
+ m_cursor++;
+ m_pCurrentControl = m_controls[m_cursor];
+ }while(!m_pCurrentControl->GoFirst());
+}
+
+/*
+ * CMenuPageAnyMove
+ */
+
+void
+CMenuPageAnyMove::Initialise(void)
+{
+ int i;
+ CMenuPage::Initialise();
+ for(i = 0; i < NUM_PAGE_WIDGETS; i++){
+ m_moveTab[i].left = -1;
+ m_moveTab[i].right = -1;
+ m_moveTab[i].up = -1;
+ m_moveTab[i].down = -1;
+ }
+}
+
+bool
+CMenuPageAnyMove::AddMenu(CMenuBase *widget, FEC_MOVETAB *moveTab)
+{
+ if(AddMenu(widget)){
+ m_moveTab[m_numControls-1] = *moveTab;
+ return true;
+ }
+ return false;
+}
+
+void
+CMenuPageAnyMove::GoUpMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ int move = m_moveTab[m_cursor].up;
+ if(move == -1)
+ CMenuPage::GoUpMenuOnPage();
+ else{ // BUG: no else in original code
+ m_cursor = move;
+ m_pCurrentControl = m_controls[m_cursor];
+ m_pCurrentControl->GoLast();
+ }
+}
+
+void
+CMenuPageAnyMove::GoDownMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ int move = m_moveTab[m_cursor].down;
+ if(move == -1)
+ CMenuPage::GoDownMenuOnPage();
+ else{ // BUG: no else in original code
+ m_cursor = move;
+ m_pCurrentControl = m_controls[m_cursor];
+ m_pCurrentControl->GoLast();
+ }
+}
+
+void
+CMenuPageAnyMove::GoLeftMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ int move = m_moveTab[m_cursor].left;
+ if(move == -1)
+ CMenuPage::GoLeftMenuOnPage();
+ else{ // BUG: no else in original code
+ m_cursor = move;
+ m_pCurrentControl = m_controls[m_cursor];
+ m_pCurrentControl->GoLast();
+ }
+}
+
+void
+CMenuPageAnyMove::GoRightMenuOnPage(void)
+{
+ if(m_pCurrentControl == nil)
+ return;
+ m_pCurrentControl->DeactivateMenu();
+ int move = m_moveTab[m_cursor].right;
+ if(move == -1)
+ CMenuPage::GoRightMenuOnPage();
+ else{ // BUG: no else in original code
+ m_cursor = move;
+ m_pCurrentControl = m_controls[m_cursor];
+ m_pCurrentControl->GoLast();
+ }
+}
diff --git a/src/core/FrontEndControls.h b/src/core/FrontEndControls.h
new file mode 100644
index 00000000..5b6f95bb
--- /dev/null
+++ b/src/core/FrontEndControls.h
@@ -0,0 +1,712 @@
+#pragma once
+
+enum {
+ NUM_MULTICHOICE_OPTIONS = 16,
+ // 50 actual lines and 15 for spacing
+ NUM_LINELISTER_LINES = 50,
+ NUM_LINELISTER_LINES_TOTAL = NUM_LINELISTER_LINES + 15,
+ NUM_PAGE_WIDGETS = 10,
+};
+
+
+class CPlaceableText
+{
+public:
+ CVector2D m_position;
+ CRGBA m_color;
+ wchar *m_text;
+
+ CPlaceableText(void)
+ : m_position(0.0f, 0.0f), m_color(255, 255, 255, 255) {}
+ void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
+ void SetColor(const CRGBA &color) { m_color = color; }
+ CRGBA GetColor(void) { return m_color; }
+ void SetAlpha(uint8 alpha) { m_color.alpha = alpha; }
+};
+
+// No trace of this in the game but it makes the other classes simpler
+class CPlaceableTextTwoLines
+{
+public:
+ CPlaceableText m_line1;
+ CPlaceableText m_line2;
+
+ void SetColor(const CRGBA &color) { m_line1.SetColor(color); m_line2.SetColor(color); }
+ void SetAlpha(uint8 alpha) { m_line1.SetAlpha(alpha); m_line2.SetAlpha(alpha); }
+};
+
+// No trace of this in the game but it makes the other classes simpler
+class CShadowInfo
+{
+public:
+ bool m_bRightJustify;
+ bool m_bDropShadow;
+ CRGBA m_shadowColor;
+ CVector2D m_shadowOffset;
+
+ CShadowInfo(void)
+ : m_bRightJustify(false), m_bDropShadow(false),
+ m_shadowColor(255, 255, 255, 255),
+ m_shadowOffset(-1.0f, -1.0f) {}
+ CRGBA GetShadowColor(void) { return m_shadowColor; }
+ void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){
+ m_bDropShadow = bDropShadows;
+ m_shadowColor = shadowColor;
+ m_shadowOffset = shadowOffset;
+ }
+};
+
+// No trace of this in the game but it makes the other classes simpler
+class CSelectable
+{
+public:
+ bool m_bSelected;
+ CRGBA m_selectedColor;
+
+ CSelectable(void) : m_bSelected(false) {}
+ CRGBA GetSelectedColor(void) { return m_selectedColor; }
+};
+
+class CPlaceableShText : public CPlaceableText, public CShadowInfo
+{
+public:
+ using CPlaceableText::SetPosition;
+ void SetPosition(float x, float y, bool bRightJustify) { SetPosition(x, y); m_bRightJustify = bRightJustify; }
+ void SetAlpha(uint8 alpha) { m_shadowColor.alpha = alpha; CPlaceableText::SetAlpha(alpha); }
+
+ void Draw(float x, float y);
+ void Draw(const CRGBA &color, float x, float y);
+ // unused arguments it seems
+ void DrawShWrap(float x, float y, float wrapX, float wrapY) { Draw(x, y); }
+};
+
+class CPlaceableShTextTwoLines : public CPlaceableTextTwoLines, public CShadowInfo
+{
+public:
+ void SetAlpha(uint8 alpha) { m_shadowColor.alpha = alpha; CPlaceableTextTwoLines::SetAlpha(alpha); }
+
+ void Draw(float x, float y);
+ void Draw(const CRGBA &color, float x, float y);
+};
+
+class CPlaceableShOption : public CPlaceableShText, public CSelectable
+{
+public:
+ void SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShText::SetColor(normal); m_selectedColor = selection; }
+ void SetAlpha(uint8 alpha) { m_selectedColor.alpha = alpha; CPlaceableShText::SetAlpha(alpha); }
+
+ using CPlaceableShText::Draw;
+ void Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);
+};
+
+class CPlaceableShOptionTwoLines : public CPlaceableShTextTwoLines, public CSelectable
+{
+public:
+ void SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShTextTwoLines::SetColor(normal); m_selectedColor = selection; }
+ void SetAlpha(uint8 alpha) { m_selectedColor.alpha = alpha; CPlaceableShTextTwoLines::SetAlpha(alpha); }
+
+ using CPlaceableShTextTwoLines::Draw;
+ void Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);
+};
+
+class CPlaceableSprite
+{
+public:
+ CSprite2d *m_pSprite;
+ CVector2D m_position;
+ CVector2D m_size;
+ CRGBA m_color;
+
+ CPlaceableSprite(void)
+ : m_pSprite(nil), m_position(0.0f, 0.0f),
+ m_size(0.0f, 0.0f), m_color(255, 255, 255, 255) {}
+
+ void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
+ void SetAlpha(uint8 alpha) { m_color.alpha = alpha; }
+
+ void Draw(float x, float y);
+ void Draw(const CRGBA &color, float x, float y);
+};
+
+class CPlaceableShSprite
+{
+public:
+ CPlaceableSprite m_sprite;
+ CPlaceableSprite m_shadow;
+ bool m_bDropShadow;
+
+ CPlaceableShSprite(void) : m_bDropShadow(false) {}
+
+ void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){
+ m_bDropShadow = bDropShadows;
+ m_shadow.m_color = shadowColor;
+ m_shadow.m_position = shadowOffset;
+ }
+ void SetAlpha(uint8 alpha) { m_sprite.SetAlpha(alpha); m_shadow.SetAlpha(alpha); }
+
+ void Draw(float x, float y);
+};
+
+
+class CMenuBase
+{
+public:
+ CVector2D m_position;
+ bool m_bTwoState;
+
+ CMenuBase(void)
+ : m_position(0.0f, 0.0f), m_bTwoState(false) {}
+ void SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y) = 0;
+ virtual void DrawNormal(float x, float y) = 0;
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) = 0;
+ virtual void SetAlpha(uint8 alpha) = 0;
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) = 0;
+ virtual bool GoNext(void) = 0;
+ virtual bool GoPrev(void) = 0;
+ virtual bool GoDown(void) = 0;
+ virtual bool GoUp(void) = 0;
+ virtual bool GoDownStill(void) = 0;
+ virtual bool GoUpStill(void) = 0;
+ virtual bool GoLeft(void) = 0;
+ virtual bool GoRight(void) = 0;
+ virtual bool GoLeftStill(void) = 0;
+ virtual bool GoRightStill(void) = 0;
+ virtual bool GoFirst(void) = 0;
+ virtual bool GoLast(void) = 0;
+ virtual void SelectCurrentOptionUnderCursor(void) = 0;
+ virtual void SelectDefaultCancelAction(void) = 0;
+ virtual void ActivateMenu(bool first) = 0;
+ virtual void DeactivateMenu(void) = 0;
+ virtual int GetMenuSelection(void) = 0;
+ virtual void SetMenuSelection(int selection) = 0;
+};
+
+class CMenuDummy : public CMenuBase
+{
+public:
+ bool m_bActive;
+
+ virtual void Draw(const CRGBA &, const CRGBA &, float x, float y) {}
+ virtual void DrawNormal(float x, float y) {}
+ virtual void DrawHighlighted(const CRGBA &, float x, float y) {}
+ virtual void SetAlpha(uint8 alpha) {}
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) {}
+ virtual bool GoNext(void) { DeactivateMenu(); return false; }
+ virtual bool GoPrev(void) { DeactivateMenu(); return false; }
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return false; }
+ virtual bool GoUpStill(void) { return false; }
+ virtual bool GoLeft(void) { return true; }
+ virtual bool GoRight(void) { return true; }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { ActivateMenu(true); return true; }
+ virtual bool GoLast(void) { ActivateMenu(true); return true; }
+ virtual void SelectCurrentOptionUnderCursor(void) {}
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) { m_bActive = true; }
+ virtual void DeactivateMenu(void) { m_bActive = false; }
+ virtual int GetMenuSelection(void) { return -1; }
+ virtual void SetMenuSelection(int) {}
+};
+
+class CMenuPictureAndText : public CMenuBase
+{
+public:
+ int m_numSprites;
+ CPlaceableShSprite m_sprites[5];
+ int m_numTexts;
+ CPlaceableShText m_texts[20];
+
+ CVector2D m_oldTextScale;
+ CVector2D m_textScale;
+ bool m_bSetTextScale;
+
+ float m_wrapX;
+ float m_oldWrapx;
+ bool m_bWrap;
+ // missing some?
+
+
+ CMenuPictureAndText(void)
+ : m_numSprites(0), m_numTexts(0),
+ m_bSetTextScale(false), m_bWrap(false) {}
+
+ void SetNewOldShadowWrapX(bool bWrapX, float newWrapX, float oldWrapX);
+ void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale);
+ void SetTextsColor(const CRGBA &color);
+ void AddText(wchar *text, float positionX, float positionY, const CRGBA &color, bool bRightJustify);
+ void AddPicture(CSprite2d *sprite, CSprite2d *shadow, float positionX, float positionY, float width, float height, const CRGBA &color);
+ void AddPicture(CSprite2d *sprite, float positionX, float positionY, float width, float height, const CRGBA &color);
+
+ virtual void Draw(const CRGBA &, const CRGBA &, float x, float y);
+ virtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
+ virtual void DrawHighlighted(const CRGBA &, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void) { return false; }
+ virtual bool GoPrev(void) { return false; }
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return false; }
+ virtual bool GoUpStill(void) { return false; }
+ virtual bool GoLeft(void) { return true; }
+ virtual bool GoRight(void) { return true; }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { return false; }
+ virtual bool GoLast(void) { return false; }
+ virtual void SelectCurrentOptionUnderCursor(void) {}
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) {}
+ virtual void DeactivateMenu(void) {}
+ virtual int GetMenuSelection(void) { return -1; }
+ virtual void SetMenuSelection(int) {}
+};
+
+class CMenuMultiChoice : public CMenuBase
+{
+public:
+ int m_numOptions;
+ CPlaceableShText m_title;
+ CPlaceableShOption m_options[NUM_MULTICHOICE_OPTIONS];
+ int m_cursor;
+ CVector2D m_oldTextScale;
+ CVector2D m_textScale;
+ bool m_bSetTextScale;
+ bool m_bSetTitleTextScale;
+
+ CMenuMultiChoice(void)
+ : m_numOptions(0), m_cursor(-1),
+ m_bSetTextScale(false), m_bSetTitleTextScale(false) {}
+
+ void AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);
+ CPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);
+ void SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);
+ void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void);
+ virtual bool GoPrev(void);
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return false; }
+ virtual bool GoUpStill(void) { return false; }
+ virtual bool GoLeft(void) { return GoPrev(); }
+ virtual bool GoRight(void) { return GoNext(); }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { m_cursor = 0; return true; }
+ virtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }
+ virtual void SelectCurrentOptionUnderCursor(void);
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }
+ virtual void DeactivateMenu(void) { m_cursor = -1; }
+ virtual int GetMenuSelection(void);
+ virtual void SetMenuSelection(int selection);
+};
+
+class CMenuMultiChoiceTriggered : public CMenuMultiChoice
+{
+public:
+ typedef void (*Trigger)(CMenuMultiChoiceTriggered *);
+
+ Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
+ Trigger m_defaultCancel;
+
+ CMenuMultiChoiceTriggered(void) { Initialise(); }
+
+ void Initialise(void);
+ CPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);
+
+ virtual void SelectCurrentOptionUnderCursor(void);
+ virtual void SelectDefaultCancelAction(void);
+};
+
+class CMenuMultiChoiceTriggeredAlways : public CMenuMultiChoiceTriggered
+{
+public:
+ Trigger m_alwaysNormalTrigger;
+ Trigger m_alwaysHighlightTrigger;
+ Trigger m_alwaysTrigger;
+
+ CMenuMultiChoiceTriggeredAlways(void)
+ : m_alwaysNormalTrigger(nil), m_alwaysHighlightTrigger(nil), m_alwaysTrigger(nil) {}
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+};
+
+class CMenuMultiChoicePictured : public CMenuMultiChoice
+{
+public:
+ CPlaceableSprite m_sprites[NUM_MULTICHOICE_OPTIONS];
+ bool m_bHasSprite[NUM_MULTICHOICE_OPTIONS];
+
+ CMenuMultiChoicePictured(void) { Initialise(); }
+ void Initialise(void);
+ using CMenuMultiChoice::AddOption;
+ CPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, bool bSelected);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ virtual void SetAlpha(uint8 alpha);
+ // unnecessary - same as base class
+// virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+};
+
+class CMenuMultiChoicePicturedTriggered : public CMenuMultiChoicePictured
+{
+public:
+ typedef void (*Trigger)(CMenuMultiChoicePicturedTriggered *);
+
+ Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
+ Trigger m_defaultCancel;
+
+ CMenuMultiChoicePicturedTriggered(void) { Initialise(); }
+
+ void Initialise(void);
+ using CMenuMultiChoicePictured::AddOption;
+ CPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);
+
+ virtual void SelectCurrentOptionUnderCursor(void);
+ virtual void SelectDefaultCancelAction(void);
+};
+
+struct FEC_MOVETAB
+{
+ int8 right;
+ int8 left;
+ int8 down;
+ int8 up;
+};
+
+class CMenuMultiChoicePicturedTriggeredAnyMove : public CMenuMultiChoicePicturedTriggered
+{
+public:
+ FEC_MOVETAB m_moveTab[NUM_MULTICHOICE_OPTIONS];
+
+ CMenuMultiChoicePicturedTriggeredAnyMove(void) { Initialise(); }
+
+ void Initialise(void);
+ using CMenuMultiChoicePicturedTriggered::AddOption;
+ CPlaceableShOption *AddOption(CSprite2d *sprite, FEC_MOVETAB *moveTab, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);
+
+ virtual bool GoDown(void);
+ virtual bool GoUp(void);
+ virtual bool GoLeft(void);
+ virtual bool GoRight(void);
+};
+
+// copy of CMenuMultiChoice pretty much except for m_options type
+class CMenuMultiChoiceTwoLines : public CMenuBase
+{
+public:
+ int m_numOptions;
+ CPlaceableShText m_title;
+ CPlaceableShOptionTwoLines m_options[NUM_MULTICHOICE_OPTIONS];
+ int m_cursor;
+ CVector2D m_oldTextScale;
+ CVector2D m_textScale;
+ bool m_bSetTextScale;
+ bool m_bSetTitleTextScale;
+
+ CMenuMultiChoiceTwoLines(void)
+ : m_numOptions(0), m_cursor(-1),
+ m_bSetTextScale(false), m_bSetTitleTextScale(false) {}
+
+ void AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);
+ CPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);
+ CPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, bool bSelected, bool bRightJustify);
+ void SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);
+ void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void);
+ virtual bool GoPrev(void);
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return true; }
+ virtual bool GoUpStill(void) { return true; }
+ virtual bool GoLeft(void) { return GoPrev(); }
+ virtual bool GoRight(void) { return GoNext(); }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { m_cursor = 0; return true; }
+ virtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }
+ virtual void SelectCurrentOptionUnderCursor(void);
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }
+ virtual void DeactivateMenu(void) { m_cursor = -1; }
+ virtual int GetMenuSelection(void);
+ virtual void SetMenuSelection(int selection);
+};
+
+// copy of CMenuMultiChoiceTriggered except for m_options
+class CMenuMultiChoiceTwoLinesTriggered : public CMenuMultiChoiceTwoLines
+{
+public:
+ typedef void (*Trigger)(CMenuMultiChoiceTwoLinesTriggered *);
+
+ Trigger m_triggers[NUM_MULTICHOICE_OPTIONS];
+ Trigger m_defaultCancel;
+
+ CMenuMultiChoiceTwoLinesTriggered(void) { Initialise(); }
+
+ void Initialise(void);
+ CPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);
+ CPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, Trigger trigger, bool bSelected, bool bRightJustify);
+
+ virtual void SelectCurrentOptionUnderCursor(void);
+ virtual void SelectDefaultCancelAction(void);
+};
+
+
+class CMenuOnOff : public CMenuBase
+{
+public:
+ CPlaceableShOption m_title;
+ CPlaceableShText m_options[2];
+ bool m_bActive;
+ bool m_bSetTextScale;
+ bool m_bSetTitleTextScale;
+ CVector2D m_textScale;
+ CVector2D m_oldTextScale;
+ int m_type; // 0: on/off 1: yes/no
+
+ void SetColors(const CRGBA &title, const CRGBA &options);
+ void SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);
+ void SetOptionPosition(float x, float y, bool bRightJustify);
+ void AddTitle(wchar *text, bool bSelected, float positionX, float positionY, bool bRightJustify);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void) { DeactivateMenu(); return false; }
+ virtual bool GoPrev(void) { DeactivateMenu(); return false; }
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return false; }
+ virtual bool GoUpStill(void) { return false; }
+ virtual bool GoLeft(void) { SelectCurrentOptionUnderCursor(); return true; }
+ virtual bool GoRight(void) { SelectCurrentOptionUnderCursor(); return true; }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { ActivateMenu(true); return true; }
+ virtual bool GoLast(void) { ActivateMenu(true); return true; }
+ virtual void SelectCurrentOptionUnderCursor(void) { m_title.m_bSelected ^= 1; }
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) { m_bActive = true; }
+ virtual void DeactivateMenu(void) { m_bActive = false; }
+ virtual int GetMenuSelection(void) { return m_title.m_bSelected; }
+ virtual void SetMenuSelection(int selection) { m_title.m_bSelected = selection; }
+};
+
+class CMenuOnOffTriggered : public CMenuOnOff
+{
+public:
+ typedef void (*Trigger)(CMenuOnOffTriggered *);
+
+ Trigger m_trigger;
+
+ void SetOptionPosition(float x, float y, Trigger trigger, bool bRightJustify);
+
+ virtual void SelectCurrentOptionUnderCursor(void);
+};
+
+class CMenuSlider : public CMenuBase
+{
+public:
+ CPlaceableShText m_title;
+ CPlaceableShText m_box; // not really a text
+ CRGBA m_colors[2]; // left and right
+ CVector2D m_size[2]; // left and right
+ int m_value;
+ CPlaceableShText m_percentageText;
+ bool m_bDrawPercentage;
+// char field_8D;
+// char field_8E;
+// char field_8F;
+ uint8 m_someAlpha;
+// char field_91;
+// char field_92;
+// char field_93;
+ bool m_bActive;
+ int m_style;
+
+ static char Buf8[8];
+ static wchar Buf16[8];
+
+ CMenuSlider(void)
+ : m_value(0), m_bDrawPercentage(false), m_bActive(false), m_style(0) {}
+
+ void SetColors(const CRGBA &title, const CRGBA &percentage, const CRGBA &left, const CRGBA &right);
+ void DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &selCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);
+ void DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);
+ void AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight);
+ void AddTitle(wchar *text, float positionX, float positionY);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y);
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void) { DeactivateMenu(); return false; }
+ virtual bool GoPrev(void) { DeactivateMenu(); return false; }
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { return false; }
+ virtual bool GoUpStill(void) { return false; }
+ virtual bool GoLeft(void) { if(m_value < 0) m_value = 0; return true; }
+ virtual bool GoRight(void) { if(m_value > 1000) m_value = 1000; return true; }
+ virtual bool GoLeftStill(void) { m_value -= 8; if(m_value < 0) m_value = 0; return true; }
+ virtual bool GoRightStill(void) { m_value += 8; if(m_value > 1000) m_value = 1000; return true; }
+ virtual bool GoFirst(void) { ActivateMenu(true); return true; }
+ virtual bool GoLast(void) { ActivateMenu(true); return true; }
+ virtual void SelectCurrentOptionUnderCursor(void) {}
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) { m_bActive = true; }
+ virtual void DeactivateMenu(void) { m_bActive = false; }
+ virtual int GetMenuSelection(void) { return m_value/10; }
+ virtual void SetMenuSelection(int selection) { m_value = selection*10; }
+};
+
+class CMenuSliderTriggered : public CMenuSlider
+{
+public:
+ typedef void (*Trigger)(CMenuSliderTriggered *);
+
+ Trigger m_trigger;
+ Trigger m_alwaysTrigger;
+
+ CMenuSliderTriggered(void)
+ : m_trigger(nil), m_alwaysTrigger(nil) {}
+
+ void AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight, Trigger trigger, Trigger alwaysTrigger);
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual bool GoLeft(void);
+ virtual bool GoRight(void);
+ virtual bool GoLeftStill(void);
+ virtual bool GoRightStill(void);
+};
+
+
+class CMenuLineLister : public CMenuBase
+{
+public:
+ float m_width;
+ float m_height;
+ int m_numLines;
+ CPlaceableShText m_linesLeft[NUM_LINELISTER_LINES_TOTAL];
+ CPlaceableShText m_linesRight[NUM_LINELISTER_LINES_TOTAL];
+ uint8 m_lineAlphas[NUM_LINELISTER_LINES_TOTAL];
+ int8 m_lineFade[NUM_LINELISTER_LINES_TOTAL];
+ float m_scrollPosition;
+ float m_scrollSpeed;
+ int field_10E8;
+ float m_lineSpacing;
+
+ CMenuLineLister(void);
+
+ void SetLinesColor(const CRGBA &color);
+ void ResetNumberOfTextLines(void);
+ bool AddTextLine(wchar *left, wchar *right);
+
+ CPlaceableShText *GetLeftLine(int i) { return &m_linesLeft[(i%NUM_LINELISTER_LINES) + 15]; };
+ CPlaceableShText *GetRightLine(int i) { return &m_linesRight[(i%NUM_LINELISTER_LINES) + 15]; };
+
+ virtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);
+ virtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
+ virtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }
+ virtual void SetAlpha(uint8 alpha);
+ virtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);
+ virtual bool GoNext(void) { return false; }
+ virtual bool GoPrev(void) { return false; }
+ virtual bool GoDown(void) { return GoNext(); }
+ virtual bool GoUp(void) { return GoPrev(); }
+ virtual bool GoDownStill(void) { m_scrollSpeed = 0.0f; return true; }
+ virtual bool GoUpStill(void) { m_scrollSpeed *= 6.0f; return true; }
+ virtual bool GoLeft(void) { return true; }
+ virtual bool GoRight(void) { return true; }
+ virtual bool GoLeftStill(void) { return true; }
+ virtual bool GoRightStill(void) { return true; }
+ virtual bool GoFirst(void) { return true; }
+ virtual bool GoLast(void) { return true; }
+ virtual void SelectCurrentOptionUnderCursor(void) {}
+ virtual void SelectDefaultCancelAction(void) {}
+ virtual void ActivateMenu(bool first) {}
+ virtual void DeactivateMenu(void) {}
+ virtual int GetMenuSelection(void) { return -1; }
+ virtual void SetMenuSelection(int selection) {}
+};
+
+class CMenuPage
+{
+public:
+ CMenuBase *m_controls[NUM_PAGE_WIDGETS];
+ int m_numControls;
+ CMenuBase *m_pCurrentControl;
+ int m_cursor;
+
+ CMenuPage(void) { Initialise(); }
+ void Initialise(void);
+ bool AddMenu(CMenuBase *widget);
+
+ bool IsActiveMenuTwoState(void);
+ void ActiveMenuTwoState_SelectNextPosition(void);
+ void Draw(const CRGBA &,const CRGBA &, float, float);
+ void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);
+ void DrawNormal(float x, float y);
+ void ActivatePage(void);
+ void SetAlpha(uint8 alpha);
+ void SetShadows(bool, const CRGBA &, const CVector2D &);
+ void GoPrev(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoPrev()) m_pCurrentControl->GoLast(); } }
+ void GoNext(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoNext()) m_pCurrentControl->GoFirst(); } }
+ void GoLeft(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoLeft()) m_pCurrentControl->GoLast(); } }
+ void GoRight(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoRight()) m_pCurrentControl->GoFirst(); } }
+ void GoUp(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoUp()) m_pCurrentControl->GoLast(); } }
+ void GoDown(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoDown()) m_pCurrentControl->GoFirst(); } }
+ void GoLeftStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoLeftStill(); }
+ void GoRightStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoRightStill(); }
+ void GoUpStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoUpStill(); }
+ void GoDownStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoDownStill(); }
+ void SelectDefaultCancelAction(void) { if(m_pCurrentControl) m_pCurrentControl->SelectDefaultCancelAction(); }
+ void SelectCurrentOptionUnderCursor(void) { if(m_pCurrentControl) m_pCurrentControl->SelectCurrentOptionUnderCursor(); }
+
+ virtual void GoUpMenuOnPage(void);
+ virtual void GoDownMenuOnPage(void);
+ virtual void GoLeftMenuOnPage(void);
+ virtual void GoRightMenuOnPage(void);
+};
+
+class CMenuPageAnyMove : public CMenuPage
+{
+public:
+ FEC_MOVETAB m_moveTab[NUM_PAGE_WIDGETS];
+
+ CMenuPageAnyMove(void) { Initialise(); }
+ void Initialise(void);
+ using CMenuPage::AddMenu;
+ bool AddMenu(CMenuBase *widget, FEC_MOVETAB *moveTab);
+
+ virtual void GoUpMenuOnPage(void);
+ virtual void GoDownMenuOnPage(void);
+ virtual void GoLeftMenuOnPage(void);
+ virtual void GoRightMenuOnPage(void);
+}; \ No newline at end of file
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index fa97dd13..e509de28 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -527,7 +527,7 @@ WRAPPER void CMenuManager::DoSettingsBeforeStartingAGame() { EAXJMP(0x48AB40); }
#else
void CMenuManager::DoSettingsBeforeStartingAGame()
{
- CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDART;
+ CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD;
if (m_PrefsVsyncDisp != m_PrefsVsync)
m_PrefsVsync = m_PrefsVsyncDisp;
@@ -2824,7 +2824,7 @@ void CMenuManager::Process(void)
}
if (m_nCurrScreen == MENUPAGE_LOADING_IN_PROGRESS) {
if (CheckSlotDataValid(m_nCurrSaveSlot)) {
- TheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDART;
+ TheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD;
if (m_PrefsVsyncDisp != m_PrefsVsync)
m_PrefsVsync = m_PrefsVsyncDisp;
DMAudio.Service();
@@ -3921,7 +3921,7 @@ CMenuManager::ProcessButtonPresses(void)
PSGLOBAL(joy1)->GetCapabilities(&devCaps);
ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons);
}
- CMenuManager::m_ControlMethod = CONTROL_STANDART;
+ CMenuManager::m_ControlMethod = CONTROL_STANDARD;
MousePointerStateHelper.bInvertVertically = false;
TheCamera.m_fMouseAccelHorzntl = 0.0025f;
CVehicle::m_bDisableMouseSteering = true;
@@ -3934,7 +3934,7 @@ CMenuManager::ProcessButtonPresses(void)
#ifndef TIDY_UP_PBP
if (CMenuManager::m_ControlMethod == CONTROL_CLASSIC) {
CCamera::m_bUseMouse3rdPerson = true;
- CMenuManager::m_ControlMethod = CONTROL_STANDART;
+ CMenuManager::m_ControlMethod = CONTROL_STANDARD;
} else {
CCamera::m_bUseMouse3rdPerson = false;
CMenuManager::m_ControlMethod = CONTROL_CLASSIC;
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 9a3209c0..4eee198f 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -386,7 +386,7 @@ enum
enum eControlMethod
{
- CONTROL_STANDART = 0,
+ CONTROL_STANDARD = 0,
CONTROL_CLASSIC,
};
diff --git a/src/core/Pad.h b/src/core/Pad.h
index 84919f32..ca44a9f7 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -2,7 +2,7 @@
enum {
PLAYERCONTROL_ENABLED = 0,
- PLAYERCONTROL_DISABLED_1 = 1,
+ PLAYERCONTROL_DISABLED_1 = 1, // used by first person camera
PLAYERCONTROL_DISABLED_2 = 2,
PLAYERCONTROL_GARAGE = 4,
PLAYERCONTROL_DISABLED_8 = 8,
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 9478479b..aeb7afe5 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -12,7 +12,7 @@ bool& CStats::SuburbanPassed = *(bool*)0x8F2740;
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
-int32 *CStats::PedsKilledOfThisType = (int32*)0x880DBC;
+int32(&CStats::PedsKilledOfThisType)[NUM_PEDTYPES] = *(int32(*)[NUM_PEDTYPES]) * (uintptr*)0x880DBC;
int32 &CStats::TimesDied = *(int32*)0x8E2BDC;
int32 &CStats::TimesArrested = *(int32*)0x8E2BEC;
int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C;
@@ -48,11 +48,73 @@ int32& CStats::LongestFlightInDodo = *(int32*)0x8F5FE4;
int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24;
int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884;
int32& CStats::TotalNumberMissions = *(int32*)0x8E2820;
-int32& CStats::KgOfExplosivesUsed = *(int32*)0x8F2510;
+int32& CStats::ShotsMade = *(int32*)0x8E2BE8;
+int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510;
+int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070;
+int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C;
+int32& CStats::BestTimeBombDefusal = *(int32*)0x880E24;
+int32& CStats::mmRain = *(int32*)0x8F2C98;
int32& CStats::CarsCrushed = *(int32*)0x943050;
int32(&CStats::FastestTimes)[CStats::TOTAL_FASTEST_TIMES] = *(int32(*)[CStats::TOTAL_FASTEST_TIMES])*(uintptr*)0x6E9128;
int32(&CStats::HighestScores)[CStats::TOTAL_HIGHEST_SCORES] = *(int32(*)[CStats::TOTAL_HIGHEST_SCORES]) * (uintptr*)0x8622B0;
+void CStats::Init()
+{
+ PeopleKilledByOthers = 0;
+ PeopleKilledByPlayer = 0;
+ ShotsMade = 0;
+ CarsExploded = 0;
+ HelisDestroyed = 0;
+ ProgressMade = 0;
+ KgsOfExplosivesUsed = 0;
+ InstantHitsFiredByPlayer = 0;
+ InstantHitsHitByPlayer = 0;
+ CarsCrushed = 0;
+ HeadsPopped = 0;
+ TimesArrested = 0;
+ TimesDied = 0;
+ DaysPassed = 0;
+ NumberOfUniqueJumpsFound = 0;
+ mmRain = 0;
+ MaximumJumpFlips = 0;
+ MaximumJumpSpins = 0;
+ MaximumJumpDistance = 0;
+ MaximumJumpHeight = 0;
+ BestStuntJump = 0;
+ TotalNumberOfUniqueJumps = 0;
+ Record4x4One = 0;
+ LongestFlightInDodo = 0;
+ Record4x4Two = 0;
+ PassengersDroppedOffWithTaxi = 0;
+ Record4x4Three = 0;
+ MoneyMadeWithTaxi = 0;
+ Record4x4Mayhem = 0;
+ LivesSavedWithAmbulance = 0;
+ ElBurroTime = 0;
+ CriminalsCaught = 0;
+ MissionsGiven = 0;
+ HighestLevelAmbulanceMission = 0;
+ MissionsPassed = 0;
+ FiresExtinguished = 0;
+ DistanceTravelledOnFoot = 0;
+ TimeTakenDefuseMission = 0;
+ NumberKillFrenziesPassed = 0;
+ DistanceTravelledInVehicle = 0;
+ TotalNumberKillFrenzies = 0;
+ TotalNumberMissions = 0;
+ KillsSinceLastCheckpoint = 0;
+ TotalLegitimateKills = 0;
+ for (int i = 0; i < TOTAL_FASTEST_TIMES; i++)
+ FastestTimes[i] = 0;
+ for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++)
+ HighestScores[i] = 0;
+ for (int i = 0; i < NUM_PEDTYPES; i++)
+ PedsKilledOfThisType[i] = 0;
+ IndustrialPassed = 0;
+ CommercialPassed = 0;
+ SuburbanPassed = 0;
+}
+
void CStats::RegisterFastestTime(int32 index, int32 time)
{
assert(index >= 0 && index < TOTAL_FASTEST_TIMES);
@@ -138,4 +200,6 @@ void CStats::SetTotalNumberMissions(int32 total)
TotalNumberMissions = total;
}
-WRAPPER void CStats::Init() { EAXJMP(0x4AAC60); } \ No newline at end of file
+STARTPATCHES
+ InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables
+ENDPATCHES \ No newline at end of file
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 1d220905..029b2307 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -1,5 +1,7 @@
#pragma once
+#include "PedType.h"
+
class CStats
{
public:
@@ -8,14 +10,14 @@ public:
TOTAL_HIGHEST_SCORES = 16
};
static int32 &DaysPassed;
- static int32 &HeadsPopped;
+ static int32 &HeadsPopped;
static bool& CommercialPassed;
static bool& IndustrialPassed;
static bool& SuburbanPassed;
static int32 &NumberKillFrenziesPassed;
static int32 &PeopleKilledByOthers;
static int32 &HelisDestroyed;
- static int32 *PedsKilledOfThisType; //[NUM_PEDTYPES]
+ static int32(&PedsKilledOfThisType)[ePedType::NUM_PEDTYPES];
static int32 &TimesDied;
static int32 &TimesArrested;
static int32 &KillsSinceLastCheckpoint;
@@ -50,11 +52,16 @@ public:
static int32 &LongestFlightInDodo;
static int32 &TimeTakenDefuseMission;
static int32 &TotalNumberKillFrenzies;
- static int32 &TotalNumberMissions;
+ static int32 &TotalNumberMissions;
+ static int32 &ShotsMade;
+ static int32 &KgsOfExplosivesUsed;
+ static int32 &InstantHitsFiredByPlayer;
+ static int32 &InstantHitsHitByPlayer;
+ static int32 &BestTimeBombDefusal;
+ static int32 &mmRain;
+ static int32 &CarsCrushed;
static int32(&FastestTimes)[TOTAL_FASTEST_TIMES];
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
- static int32 &KgOfExplosivesUsed;
- static int32 &CarsCrushed;
public:
static void RegisterFastestTime(int32, int32);
@@ -76,6 +83,5 @@ public:
static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
static void RegisterElBurroTime(int32);
static void SaveStats(uint8 *buf, uint32 *size);
-
static void Init(void);
};
diff --git a/src/core/config.h b/src/core/config.h
index 2d1bfff1..d813a1f2 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -120,7 +120,9 @@ enum Config {
NUM_AUDIO_REFLECTIONS = 5,
NUM_SCRIPT_MAX_ENTITIES = 40,
- NUM_GARAGE_STORED_CARS = 6
+ NUM_GARAGE_STORED_CARS = 6,
+
+ NUM_CRANES = 8
};
// We'll use this once we're ready to become independent of the game
@@ -216,4 +218,4 @@ enum Config {
// Camera
#define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future
-//#define FREE_CAM // Rotating cam
+#define FREE_CAM // Rotating cam
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 05d28167..6d4ff252 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -372,11 +372,9 @@ DebugMenuPopulate(void)
extern bool PrintDebugCode;
extern int16 &DebugCamMode;
+ DebugMenuAddVarBool8("Cam", "Use mouse Cam", (int8*)&CCamera::m_bUseMouse3rdPerson, nil);
#ifdef FREE_CAM
- extern bool bFreePadCam;
- extern bool bFreeMouseCam;
- DebugMenuAddVarBool8("Cam", "Free Gamepad Cam", (int8*)&bFreePadCam, nil);
- DebugMenuAddVarBool8("Cam", "Free Mouse Cam", (int8*)&bFreeMouseCam, nil);
+ DebugMenuAddVarBool8("Cam", "Free Cam", (int8*)&CCamera::bFreeCam, nil);
#endif
DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil);
DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil);