re3/src/core/Cam.cpp

5244 lines
174 KiB
C++
Raw Normal View History

2020-03-26 13:16:06 +00:00
#include "common.h"
2020-04-17 13:31:11 +00:00
2020-03-26 13:16:06 +00:00
#include "main.h"
#include "Draw.h"
#include "World.h"
#include "Vehicle.h"
#include "Automobile.h"
2020-06-02 21:35:20 +00:00
#include "Boat.h"
2020-03-26 13:16:06 +00:00
#include "Ped.h"
#include "PlayerPed.h"
#include "CopPed.h"
#include "RpAnimBlend.h"
#include "ControllerConfig.h"
#include "Pad.h"
#include "Frontend.h"
#include "General.h"
#include "Renderer.h"
#include "Shadows.h"
#include "Hud.h"
#include "ZoneCull.h"
#include "SurfaceTable.h"
#include "WaterLevel.h"
#include "MBlur.h"
#include "SceneEdit.h"
#include "Debug.h"
#include "Camera.h"
#include "DMAudio.h"
#include "Bike.h"
2020-06-09 13:50:00 +00:00
#include "Pickups.h"
2020-03-26 13:16:06 +00:00
bool PrintDebugCode = false;
2020-04-17 05:54:14 +00:00
int16 DebugCamMode;
2020-06-09 13:50:00 +00:00
extern float fRangePlayerRadius;
extern float fCloseNearClipLimit;
#ifdef FREE_CAM
bool CCamera::bFreeCam;
int nPreviousMode = -1;
#endif
2020-03-26 13:16:06 +00:00
void
CCam::Init(void)
{
Mode = MODE_FOLLOWPED;
Front = CVector(0.0f, 0.0f, -1.0f);
Up = CVector(0.0f, 0.0f, 1.0f);
2020-06-09 13:50:00 +00:00
Rotating = false;
2020-03-26 13:16:06 +00:00
m_iDoCollisionChecksOnFrameNum = 1;
m_iDoCollisionCheckEveryNumOfFrames = 9;
m_iFrameNumWereAt = 0;
2020-06-09 13:50:00 +00:00
m_bCollisionChecksOn = false;
2020-03-26 13:16:06 +00:00
m_fRealGroundDist = 0.0f;
BetaSpeed = 0.0f;
AlphaSpeed = 0.0f;
DistanceSpeed = 0.0f;
f_max_role_angle = DEGTORAD(5.0f);
Distance = 30.0f;
DistanceSpeed = 0.0f;
2020-06-09 13:50:00 +00:00
m_pLastCarEntered = nil;
m_pLastPedLookedAt = nil;
ResetStatics = true;
2020-03-26 13:16:06 +00:00
Beta = 0.0f;
2020-06-09 13:50:00 +00:00
m_fTilt = 0.0f;
m_fTiltSpeed = 0.0f;
m_bFixingBeta = false;
2020-03-26 13:16:06 +00:00
CA_MIN_DISTANCE = 0.0f;
CA_MAX_DISTANCE = 0.0f;
2020-06-09 13:50:00 +00:00
LookingBehind = false;
LookingLeft = false;
LookingRight = false;
2020-03-26 13:16:06 +00:00
m_fPlayerInFrontSyphonAngleOffSet = DEGTORAD(20.0f);
m_fSyphonModeTargetZOffSet = 0.5f;
m_fRadiusForDead = 1.5f;
DirectionWasLooking = LOOKING_FORWARD;
2020-06-09 13:50:00 +00:00
LookBehindCamWasInFront = false;
2020-03-26 13:16:06 +00:00
f_Roll = 0.0f;
f_rollSpeed = 0.0f;
m_fCloseInPedHeightOffset = 0.0f;
m_fCloseInPedHeightOffsetSpeed = 0.0f;
m_fCloseInCarHeightOffset = 0.0f;
m_fCloseInCarHeightOffsetSpeed = 0.0f;
m_fPedBetweenCameraHeightOffset = 0.0f;
m_fTargetBeta = 0.0f;
m_fBufferedTargetBeta = 0.0f;
m_fBufferedTargetOrientation = 0.0f;
m_fBufferedTargetOrientationSpeed = 0.0f;
m_fDimensionOfHighestNearCar = 0.0f;
m_fRoadOffSet = 0.0f;
}
void
CCam::Process(void)
{
CVector CameraTarget;
float TargetSpeedVar = 0.0f;
float TargetOrientation = 0.0f;
if(CamTargetEntity == nil)
CamTargetEntity = TheCamera.pTargetEntity;
m_iFrameNumWereAt++;
if(m_iFrameNumWereAt > m_iDoCollisionCheckEveryNumOfFrames)
m_iFrameNumWereAt = 1;
m_bCollisionChecksOn = m_iFrameNumWereAt == m_iDoCollisionChecksOnFrameNum;
if(m_bCamLookingAtVector){
CameraTarget = m_cvecCamFixedModeVector;
}else if(CamTargetEntity->IsVehicle()){
CameraTarget = CamTargetEntity->GetPosition();
if(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)
TargetOrientation = 0.0f;
else
TargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);
CVector Fwd(0.0f, 0.0f, 0.0f);
Fwd.x = CamTargetEntity->GetForward().x;
Fwd.y = CamTargetEntity->GetForward().y;
Fwd.Normalise();
// Game normalizes again here manually. useless, so skipped
float FwdSpeedX = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().x * Fwd.x;
float FwdSpeedY = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().y * Fwd.y;
if(FwdSpeedX + FwdSpeedY > 0.0f)
2020-04-19 16:34:08 +00:00
TargetSpeedVar = Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/0.9f, 1.0f);
2020-03-26 13:16:06 +00:00
else
2020-04-19 16:34:08 +00:00
TargetSpeedVar = -Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f);
2020-03-26 13:16:06 +00:00
SpeedVar = 0.895f*SpeedVar + 0.105*TargetSpeedVar;
}else{
CameraTarget = CamTargetEntity->GetPosition();
if(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)
TargetOrientation = 0.0f;
else
TargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);
TargetSpeedVar = 0.0f;
SpeedVar = 0.0f;
}
switch(Mode){
case MODE_TOPDOWN:
case MODE_GTACLASSIC:
Process_TopDown(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_BEHINDCAR:
Process_BehindCar(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_FOLLOWPED:
if(CCamera::m_bUseMouse3rdPerson)
Process_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#ifdef FREE_CAM
2020-04-02 10:48:01 +00:00
if(CCamera::bFreeCam)
Process_FollowPed_Rotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
2020-03-26 13:16:06 +00:00
Process_FollowPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
// case MODE_AIMING:
case MODE_DEBUG:
Process_Debug(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_SNIPER:
Process_Sniper(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_ROCKETLAUNCHER:
Process_Rocket(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_MODELVIEW:
Process_ModelView(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
// case MODE_BILL:
case MODE_SYPHON:
Process_Syphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_CIRCLE:
Process_Circle(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
// case MODE_CHEESYZOOM:
case MODE_WHEELCAM:
Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_FIXED:
Process_Fixed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_1STPERSON:
Process_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_FLYBY:
Process_FlyBy(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_CAM_ON_A_STRING:
#ifdef FREE_CAM
2020-04-02 10:48:01 +00:00
if(CCamera::bFreeCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
Process_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
2020-03-26 13:16:06 +00:00
break;
2020-03-27 17:19:08 +00:00
case MODE_REACTION:
Process_ReactionCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_FOLLOW_PED_WITH_BIND:
Process_FollowPed_WithBinding(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_CHRIS:
Process_Chris_With_Binding_PlusRotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
2020-03-26 13:16:06 +00:00
case MODE_BEHINDBOAT:
#ifdef FREE_CAM
2020-04-02 10:48:01 +00:00
if (CCamera::bFreeCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
Process_BehindBoat(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
2020-03-26 13:16:06 +00:00
break;
case MODE_PLAYER_FALLEN_WATER:
Process_Player_Fallen_Water(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
// case MODE_CAM_ON_TRAIN_ROOF:
// case MODE_CAM_RUNNING_SIDE_TRAIN:
// case MODE_BLOOD_ON_THE_TRACKS:
// case MODE_IM_THE_PASSENGER_WOOWOO:
case MODE_SYPHON_CRIM_IN_FRONT:
Process_Syphon_Crim_In_Front(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_PED_DEAD_BABY:
ProcessPedsDeadBaby();
break;
// case MODE_PILLOWS_PAPS:
// case MODE_LOOK_AT_CARS:
case MODE_ARRESTCAM_ONE:
ProcessArrestCamOne();
break;
case MODE_ARRESTCAM_TWO:
ProcessArrestCamTwo();
break;
case MODE_M16_1STPERSON:
2020-06-09 13:50:00 +00:00
case MODE_HELICANNON_1STPERSON:
2020-03-26 13:16:06 +00:00
Process_M16_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_SPECIAL_FIXED_FOR_SYPHON:
Process_SpecialFixedForSyphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_FIGHT_CAM:
Process_Fight_Cam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_TOP_DOWN_PED:
Process_TopDownPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_SNIPER_RUNABOUT:
case MODE_ROCKETLAUNCHER_RUNABOUT:
case MODE_1STPERSON_RUNABOUT:
case MODE_M16_1STPERSON_RUNABOUT:
case MODE_FIGHT_CAM_RUNABOUT:
Process_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
case MODE_EDITOR:
Process_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
default:
Source = CVector(0.0f, 0.0f, 0.0f);
Front = CVector(0.0f, 1.0f, 0.0f);
Up = CVector(0.0f, 0.0f, 1.0f);
}
#ifdef FREE_CAM
nPreviousMode = Mode;
#endif
2020-03-26 13:16:06 +00:00
CVector TargetToCam = Source - m_cvecTargetCoorsForFudgeInter;
float DistOnGround = TargetToCam.Magnitude2D();
m_fTrueBeta = CGeneral::GetATanOfXY(TargetToCam.x, TargetToCam.y);
m_fTrueAlpha = CGeneral::GetATanOfXY(TargetToCam.z, DistOnGround);
2020-04-02 10:48:01 +00:00
if(TheCamera.m_uiTransitionState == 0)
2020-03-26 13:16:06 +00:00
KeepTrackOfTheSpeed(Source, m_cvecTargetCoorsForFudgeInter, Up, m_fTrueAlpha, m_fTrueBeta, FOV);
// Look Behind, Left, Right
LookingBehind = false;
LookingLeft = false;
LookingRight = false;
SourceBeforeLookBehind = Source;
if(&TheCamera.Cams[TheCamera.ActiveCam] == this){
if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_1STPERSON || Mode == MODE_BEHINDBOAT) &&
CamTargetEntity->IsVehicle()){
if(CPad::GetPad(0)->GetLookBehindForCar()){
LookBehind();
if(DirectionWasLooking != LOOKING_BEHIND)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_BEHIND;
}else if(!((CVehicle*)CamTargetEntity)->IsRealHeli() && CPad::GetPad(0)->GetLookLeft()){
2020-03-26 13:16:06 +00:00
LookLeft();
if(DirectionWasLooking != LOOKING_LEFT)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_LEFT;
}else if(!((CVehicle*)CamTargetEntity)->IsRealHeli() && CPad::GetPad(0)->GetLookRight()){
2020-03-26 13:16:06 +00:00
LookRight();
if(DirectionWasLooking != LOOKING_RIGHT)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_RIGHT;
}else{
if(DirectionWasLooking != LOOKING_FORWARD)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_FORWARD;
}
}
if(Mode == MODE_FOLLOWPED && CamTargetEntity->IsPed()){
if(CPad::GetPad(0)->GetLookBehindForPed()){
LookBehind();
if(DirectionWasLooking != LOOKING_BEHIND)
TheCamera.m_bJust_Switched = true;
DirectionWasLooking = LOOKING_BEHIND;
}else
DirectionWasLooking = LOOKING_FORWARD;
}
}
if(Mode == MODE_SNIPER || Mode == MODE_ROCKETLAUNCHER || Mode == MODE_M16_1STPERSON ||
Mode == MODE_1STPERSON || Mode == MODE_HELICANNON_1STPERSON || Mode == MODE_CAMERA || GetWeaponFirstPersonOn())
2020-03-26 13:16:06 +00:00
ClipIfPedInFrontOfPlayer();
}
// MaxSpeed is a limit of how fast the value is allowed to change. 1.0 = to Target in up to 1ms
// Acceleration is how fast the speed will change to MaxSpeed. 1.0 = to MaxSpeed in 1ms
void
WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle)
{
float Delta = Target - *CurrentValue;
if(IsAngle){
while(Delta >= PI) Delta -= 2*PI;
while(Delta < -PI) Delta += 2*PI;
}
float TargetSpeed = Delta * MaxSpeed;
// Add or subtract absolute depending on sign, genius!
// if(TargetSpeed - *CurrentSpeed > 0.0f)
// *CurrentSpeed += Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
// else
// *CurrentSpeed -= Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
// this is simpler:
*CurrentSpeed += Acceleration * (TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();
// Clamp speed if we overshot
if(TargetSpeed < 0.0f && *CurrentSpeed < TargetSpeed)
*CurrentSpeed = TargetSpeed;
else if(TargetSpeed > 0.0f && *CurrentSpeed > TargetSpeed)
*CurrentSpeed = TargetSpeed;
2020-04-19 16:34:08 +00:00
*CurrentValue += *CurrentSpeed * Min(10.0f, CTimer::GetTimeStep());
2020-03-26 13:16:06 +00:00
}
void
MakeAngleLessThan180(float &Angle)
{
while(Angle >= PI) Angle -= 2*PI;
while(Angle < -PI) Angle += 2*PI;
}
void
CCam::ProcessSpecialHeightRoutines(void)
{
int i = 0;
bool StandingOnBoat = false;
static bool PreviouslyFailedRoadHeightCheck = false;
CVector CamToTarget, CamToPed;
float DistOnGround, BetaAngle;
CPed *Player;
int ClosestPed = 0;
bool FoundPed = false;
float ClosestPedDist, PedZDist;
CColPoint colPoint;
CamToTarget = TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();
DistOnGround = CamToTarget.Magnitude2D();
BetaAngle = CGeneral::GetATanOfXY(CamToTarget.x, CamToTarget.y);
m_bTheHeightFixerVehicleIsATrain = false;
ClosestPedDist = 0.0f;
// CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);
Player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
if(DistOnGround > 10.0f)
DistOnGround = 10.0f;
if(CamTargetEntity && CamTargetEntity->IsPed()){
if(FindPlayerPed()->m_pCurSurface && FindPlayerPed()->m_pCurSurface->IsVehicle() &&
((CVehicle*)FindPlayerPed()->m_pCurSurface)->IsBoat())
StandingOnBoat = true;
// Move up the camera if there is a ped close to it
if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM){
// Find ped closest to camera
while(i < Player->m_numNearPeds){
if(Player->m_nearPeds[i] && Player->m_nearPeds[i]->GetPedState() != PED_DEAD){
CamToPed = Player->m_nearPeds[i]->GetPosition() - TheCamera.GetGameCamPosition();
if(FoundPed){
if(CamToPed.Magnitude2D() < ClosestPedDist){
ClosestPed = i;
ClosestPedDist = CamToPed.Magnitude2D();
}
}else{
FoundPed = true;
ClosestPed = i;
ClosestPedDist = CamToPed.Magnitude2D();
}
}
i++;
}
if(FoundPed){
float Offset = 0.0f;
CPed *Ped = Player->m_nearPeds[ClosestPed];
CamToPed = Ped->GetPosition() - TheCamera.GetGameCamPosition();
PedZDist = 0.0f;
float dist = CamToPed.Magnitude2D(); // should be same as ClosestPedDist
if(dist < 2.1f){
// Ped is close to camera, move up
// Z Distance between player and close ped
PedZDist = 0.0f;
if(Ped->bIsStanding)
PedZDist = Ped->GetPosition().z - Player->GetPosition().z;
// Ignore if too distant
if(PedZDist > 1.2f || PedZDist < -1.2f)
PedZDist = 0.0f;
float DistScale = (2.1f - dist)/2.1f;
if(Mode == MODE_FOLLOWPED){
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_1)
2020-03-26 13:16:06 +00:00
Offset = 0.45*DistScale + PedZDist;
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_2)
2020-03-26 13:16:06 +00:00
Offset = 0.35*DistScale + PedZDist;
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_3)
2020-03-26 13:16:06 +00:00
Offset = 0.25*DistScale + PedZDist;
if(Abs(CGeneral::GetRadianAngleBetweenPoints(CamToPed.x, CamToPed.y, CamToTarget.x, CamToTarget.y)) > HALFPI)
Offset += 0.3f;
m_fPedBetweenCameraHeightOffset = Offset + 1.3f;
PedZDist = 0.0f;
}else if(Mode == MODE_FIGHT_CAM)
m_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.5f;
}else
m_fPedBetweenCameraHeightOffset = 0.0f;
}else{
PedZDist = 0.0f;
m_fPedBetweenCameraHeightOffset = 0.0f;
}
}else
PedZDist = 0.0f;
// Move camera up for vehicles in the way
if(m_bCollisionChecksOn && (Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM)){
bool FoundCar = false;
CEntity *vehicle = nil;
float TestDist = DistOnGround + 1.25f;
float HighestCar = 0.0f;
CVector TestBase = CamTargetEntity->GetPosition();
CVector TestPoint;
TestBase.z -= 0.15f;
TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f);
if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
vehicle->IsVehicle()){
float height = vehicle->GetColModel()->boundingBox.GetSize().z;
FoundCar = true;
HighestCar = height;
if(((CVehicle*)vehicle)->IsTrain())
m_bTheHeightFixerVehicleIsATrain = true;
}
TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle+DEGTORAD(28.0f)), Sin(BetaAngle+DEGTORAD(28.0f)), 0.0f);
if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
vehicle->IsVehicle()){
float height = vehicle->GetColModel()->boundingBox.GetSize().z;
if(FoundCar){
2020-04-19 16:34:08 +00:00
HighestCar = Max(HighestCar, height);
2020-03-26 13:16:06 +00:00
}else{
FoundCar = true;
HighestCar = height;
}
if(((CVehicle*)vehicle)->IsTrain())
m_bTheHeightFixerVehicleIsATrain = true;
}
TestPoint = TestBase - TestDist * CVector(Cos(BetaAngle-DEGTORAD(28.0f)), Sin(BetaAngle-DEGTORAD(28.0f)), 0.0f);
if(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&
vehicle->IsVehicle()){
float height = vehicle->GetColModel()->boundingBox.GetSize().z;
if(FoundCar){
2020-04-19 16:34:08 +00:00
HighestCar = Max(HighestCar, height);
2020-03-26 13:16:06 +00:00
}else{
FoundCar = true;
HighestCar = height;
}
if(((CVehicle*)vehicle)->IsTrain())
m_bTheHeightFixerVehicleIsATrain = true;
}
if(FoundCar){
m_fDimensionOfHighestNearCar = HighestCar + 0.1f;
if(Mode == MODE_FIGHT_CAM)
m_fDimensionOfHighestNearCar += 0.75f;
}else
m_fDimensionOfHighestNearCar = 0.0f;
}
// Move up for road
if(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM ||
Mode == MODE_SYPHON || Mode == MODE_SYPHON_CRIM_IN_FRONT || Mode == MODE_SPECIAL_FIXED_FOR_SYPHON){
bool Inside = false;
bool OnRoad = false;
switch(((CPhysical*)CamTargetEntity)->m_nSurfaceTouched)
case SURFACE_GRASS:
2020-05-26 09:34:20 +00:00
case SURFACE_GRAVEL:
case SURFACE_MUD_DRY:
case SURFACE_THICK_METAL_PLATE:
case SURFACE_RUBBER:
case SURFACE_STEEP_CLIFF:
2020-03-26 13:16:06 +00:00
OnRoad = true;
if(CCullZones::PlayerNoRain())
Inside = true;
if((m_bCollisionChecksOn || PreviouslyFailedRoadHeightCheck || OnRoad) &&
m_fCloseInPedHeightOffset < 0.0001f && !Inside){
CVector TestPoint;
CEntity *road;
float GroundZ = 0.0f;
bool FoundGround = false;
float RoofZ = 0.0f;
bool FoundRoof = false;
static float MinHeightAboveRoad = 0.9f;
TestPoint = CamTargetEntity->GetPosition() - DistOnGround * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f);
m_fRoadOffSet = 0.0f;
if(CWorld::ProcessVerticalLine(TestPoint, -1000.0f, colPoint, road, true, false, false, false, false, false, nil)){
FoundGround = true;
GroundZ = colPoint.point.z;
}
// Move up if too close to ground
if(FoundGround){
if(TestPoint.z - GroundZ < MinHeightAboveRoad){
m_fRoadOffSet = GroundZ + MinHeightAboveRoad - TestPoint.z;
PreviouslyFailedRoadHeightCheck = true;
}else{
if(m_bCollisionChecksOn)
PreviouslyFailedRoadHeightCheck = false;
else
m_fRoadOffSet = 0.0f;
}
}else{
if(CWorld::ProcessVerticalLine(TestPoint, 1000.0f, colPoint, road, true, false, false, false, false, false, nil)){
FoundRoof = true;
RoofZ = colPoint.point.z;
}
if(FoundRoof){
if(TestPoint.z - RoofZ < MinHeightAboveRoad){
m_fRoadOffSet = RoofZ + MinHeightAboveRoad - TestPoint.z;
PreviouslyFailedRoadHeightCheck = true;
}else{
if(m_bCollisionChecksOn)
PreviouslyFailedRoadHeightCheck = false;
else
m_fRoadOffSet = 0.0f;
}
}
}
}
}
if(PreviouslyFailedRoadHeightCheck && m_fCloseInPedHeightOffset < 0.0001f){
if(colPoint.surfaceB != SURFACE_TARMAC &&
colPoint.surfaceB != SURFACE_GRASS &&
2020-05-26 09:34:20 +00:00
colPoint.surfaceB != SURFACE_GRAVEL &&
colPoint.surfaceB != SURFACE_MUD_DRY &&
colPoint.surfaceB != SURFACE_STEEP_CLIFF){
2020-03-26 13:16:06 +00:00
if(m_fRoadOffSet > 1.4f)
m_fRoadOffSet = 1.4f;
}else{
if(Mode == MODE_FOLLOWPED){
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_1)
2020-03-26 13:16:06 +00:00
m_fRoadOffSet += 0.2f;
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_2)
2020-03-26 13:16:06 +00:00
m_fRoadOffSet += 0.5f;
2020-04-02 10:48:01 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_3)
2020-03-26 13:16:06 +00:00
m_fRoadOffSet += 0.95f;
}
}
}
}
if(StandingOnBoat){
m_fRoadOffSet = 0.0f;
m_fDimensionOfHighestNearCar = 1.0f;
m_fPedBetweenCameraHeightOffset = 0.0f;
}
}
void
CCam::GetVectorsReadyForRW(void)
{
CVector right;
Up = CVector(0.0f, 0.0f, 1.0f);
Front.Normalise();
if(Front.x == 0.0f && Front.y == 0.0f){
Front.x = 0.0001f;
Front.y = 0.0001f;
}
right = CrossProduct(Front, Up);
right.Normalise();
Up = CrossProduct(right, Front);
}
void
CCam::LookBehind(void)
{
float Dist, DeltaBeta, TargetOrientation, Angle;
CVector TargetCoors, TargetFwd, TestCoors;
CColPoint colPoint;
CEntity *entity;
TargetCoors = CamTargetEntity->GetPosition();
Front = CamTargetEntity->GetPosition() - Source;
if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
LookingBehind = true;
Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 15.5f;
TargetFwd = CamTargetEntity->GetForward();
TargetFwd.Normalise();
TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
DeltaBeta = TargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
2020-04-05 13:27:30 +00:00
if(DirectionWasLooking != LOOKING_BEHIND)
2020-03-26 13:16:06 +00:00
LookBehindCamWasInFront = DeltaBeta <= -HALFPI || DeltaBeta >= HALFPI;
if(LookBehindCamWasInFront)
TargetOrientation += PI;
Source.x = Dist*Cos(TargetOrientation) + TargetCoors.x;
Source.y = Dist*Sin(TargetOrientation) + TargetCoors.y;
Source.z -= 1.0f;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
2020-04-02 10:48:01 +00:00
RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
2020-03-26 13:16:06 +00:00
Source = colPoint.point;
}
Source.z += 1.0f;
Front = CamTargetEntity->GetPosition() - Source;
GetVectorsReadyForRW();
}
if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
LookingBehind = true;
RwCameraSetNearClipPlane(Scene.camera, 0.25f);
Front = CamTargetEntity->GetForward();
Front.Normalise();
if(((CVehicle*)CamTargetEntity)->IsBoat())
Source.z -= 0.5f;
Source += 0.25f*Front;
Front = -Front;
#ifdef FIX_BUGS
// not sure if this is a bug...
GetVectorsReadyForRW();
#endif
}
if(CamTargetEntity->IsPed()){
Angle = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y) + PI;
Source.x = 4.5f*Cos(Angle) + TargetCoors.x;
Source.y = 4.5f*Sin(Angle) + TargetCoors.y;
Source.z = 1.15f + TargetCoors.z;
TestCoors = TargetCoors;
TestCoors.z = Source.z;
if(CWorld::ProcessLineOfSight(TestCoors, Source, colPoint, entity, true, true, false, true, false, true, true)){
Source.x = colPoint.point.x;
Source.y = colPoint.point.y;
if((TargetCoors - Source).Magnitude2D() < 1.15f)
RwCameraSetNearClipPlane(Scene.camera, 0.05f);
}
Front = TargetCoors - Source;
GetVectorsReadyForRW();
}
}
void
CCam::LookLeft(void)
{
float Dist, TargetOrientation;
CVector TargetCoors, TargetFwd;
CColPoint colPoint;
CEntity *entity;
if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
LookingLeft = true;
TargetCoors = CamTargetEntity->GetPosition();
Front = CamTargetEntity->GetPosition() - Source;
Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f;
TargetFwd = CamTargetEntity->GetForward();
TargetFwd.Normalise();
TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
Source.x = Dist*Cos(TargetOrientation - HALFPI) + TargetCoors.x;
Source.y = Dist*Sin(TargetOrientation - HALFPI) + TargetCoors.y;
Source.z -= 1.0f;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source = colPoint.point;
}
Source.z += 1.0f;
Front = CamTargetEntity->GetPosition() - Source;
Front.z += 1.1f;
if(Mode == MODE_BEHINDBOAT)
Front.z += 1.2f;
GetVectorsReadyForRW();
}
if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
LookingLeft = true;
RwCameraSetNearClipPlane(Scene.camera, 0.25f);
if(((CVehicle*)CamTargetEntity)->IsBoat())
Source.z -= 0.5f;
Up = CamTargetEntity->GetUp();
Up.Normalise();
Front = CamTargetEntity->GetForward();
Front.Normalise();
Front = -CrossProduct(Front, Up);
Front.Normalise();
#ifdef FIX_BUGS
// not sure if this is a bug...
GetVectorsReadyForRW();
#endif
}
}
void
CCam::LookRight(void)
{
float Dist, TargetOrientation;
CVector TargetCoors, TargetFwd;
CColPoint colPoint;
CEntity *entity;
if((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){
LookingRight = true;
TargetCoors = CamTargetEntity->GetPosition();
Front = CamTargetEntity->GetPosition() - Source;
Dist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 9.0f;
TargetFwd = CamTargetEntity->GetForward();
TargetFwd.Normalise();
TargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);
Source.x = Dist*Cos(TargetOrientation + HALFPI) + TargetCoors.x;
Source.y = Dist*Sin(TargetOrientation + HALFPI) + TargetCoors.y;
Source.z -= 1.0f;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source = colPoint.point;
}
Source.z += 1.0f;
Front = CamTargetEntity->GetPosition() - Source;
Front.z += 1.1f;
if(Mode == MODE_BEHINDBOAT)
Front.z += 1.2f;
GetVectorsReadyForRW();
}
if(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){
LookingRight = true;
RwCameraSetNearClipPlane(Scene.camera, 0.25f);
if(((CVehicle*)CamTargetEntity)->IsBoat())
Source.z -= 0.5f;
Up = CamTargetEntity->GetUp();
Up.Normalise();
Front = CamTargetEntity->GetForward();
Front.Normalise();
Front = CrossProduct(Front, Up);
Front.Normalise();
#ifdef FIX_BUGS
// not sure if this is a bug...
GetVectorsReadyForRW();
#endif
}
}
void
CCam::ClipIfPedInFrontOfPlayer(void)
{
float FwdAngle, PedAngle, DeltaAngle, fDist, Near;
CVector vDist;
CPed *Player;
bool found = false;
int ped = 0;
// unused: TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();
FwdAngle = CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);
Player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
while(ped < Player->m_numNearPeds && !found)
if(Player->m_nearPeds[ped] && Player->m_nearPeds[ped]->GetPedState() != PED_DEAD)
found = true;
else
ped++;
if(found){
vDist = Player->m_nearPeds[ped]->GetPosition() - TheCamera.GetGameCamPosition();
PedAngle = CGeneral::GetATanOfXY(vDist.x, vDist.y);
DeltaAngle = FwdAngle - PedAngle;
while(DeltaAngle >= PI) DeltaAngle -= 2*PI;
while(DeltaAngle < -PI) DeltaAngle += 2*PI;
if(Abs(DeltaAngle) < HALFPI){
fDist = Sqrt(SQR(vDist.x) + SQR(vDist.y));
if(fDist < 1.25f){
2020-04-02 10:48:01 +00:00
Near = DEFAULT_NEAR - (1.25f - fDist);
2020-03-26 13:16:06 +00:00
if(Near < 0.05f)
Near = 0.05f;
RwCameraSetNearClipPlane(Scene.camera, Near);
}
}
}
}
void
CCam::KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov)
{
static CVector PreviousSource = source;
static CVector PreviousTarget = target;
static CVector PreviousUp = up;
static float PreviousBeta = beta;
static float PreviousAlpha = alpha;
static float PreviousFov = fov;
if(TheCamera.m_bJust_Switched){
PreviousSource = source;
PreviousTarget = target;
PreviousUp = up;
}
m_cvecSourceSpeedOverOneFrame = PreviousSource - source;
m_cvecTargetSpeedOverOneFrame = PreviousTarget - target;
m_cvecUpOverOneFrame = PreviousUp - up;
m_fFovSpeedOverOneFrame = fov - PreviousFov;
m_fBetaSpeedOverOneFrame = beta - PreviousBeta;
MakeAngleLessThan180(m_fBetaSpeedOverOneFrame);
m_fAlphaSpeedOverOneFrame = alpha - PreviousAlpha;
MakeAngleLessThan180(m_fAlphaSpeedOverOneFrame);
PreviousSource = source;
PreviousTarget = target;
PreviousUp = up;
PreviousBeta = beta;
PreviousAlpha = alpha;
PreviousFov = fov;
}
bool
CCam::Using3rdPersonMouseCam(void)
{
return CCamera::m_bUseMouse3rdPerson &&
(Mode == MODE_FOLLOWPED ||
TheCamera.m_bPlayerIsInGarage &&
FindPlayerPed() && FindPlayerPed()->m_nPedState != PED_DRIVING &&
Mode != MODE_TOPDOWN && this->CamTargetEntity == FindPlayerPed());
}
bool
CCam::GetWeaponFirstPersonOn(void)
{
CEntity *target = this->CamTargetEntity;
if (target && target->IsPed())
return ((CPed*)target)->GetWeapon()->m_bAddRotOffset;
return false;
}
bool
CCam::IsTargetInWater(const CVector &CamCoors)
{
if(CamTargetEntity == nil)
return false;
if(CamTargetEntity->IsPed()){
if(!((CPed*)CamTargetEntity)->bIsInWater)
return false;
if(!((CPed*)CamTargetEntity)->bIsStanding)
return true;
return false;
}
return ((CPhysical*)CamTargetEntity)->bIsInWater;
}
void
CCam::PrintMode(void)
{
// Doesn't do anything
char buf[256];
if(PrintDebugCode){
sprintf(buf, " ");
sprintf(buf, " ");
sprintf(buf, " ");
2020-05-11 23:24:57 +00:00
static Const char *modes[] = { "None",
2020-03-26 13:16:06 +00:00
"Top Down", "GTA Classic", "Behind Car", "Follow Ped",
"Aiming", "Debug", "Sniper", "Rocket", "Model Viewer", "Bill",
"Syphon", "Circle", "Cheesy Zoom", "Wheel", "Fixed",
"1st Person", "Fly by", "on a String", "Reaction",
"Follow Ped with Bind", "Chris", "Behind Boat",
"Player fallen in Water", "Train Roof", "Train Side",
"Blood on the tracks", "Passenger", "Syphon Crim in Front",
"Dead Baby", "Pillow Paps", "Look at Cars", "Arrest One",
"Arrest Two", "M16", "Special fixed for Syphon", "Fight",
2020-06-09 13:50:00 +00:00
"Top Down Ped", "Lighthouse",
2020-03-26 13:16:06 +00:00
"Sniper run about", "Rocket run about",
"1st Person run about", "M16 run about", "Fight run about",
2020-06-09 13:50:00 +00:00
"Editor", "Helicannon", "Camera"
2020-03-26 13:16:06 +00:00
};
sprintf(buf, "Cam: %s", modes[TheCamera.Cams[TheCamera.ActiveCam].Mode]);
CDebug::PrintAt(buf, 2, 5);
}
if(DebugCamMode != MODE_NONE){
switch(Mode){
case MODE_FOLLOWPED:
sprintf(buf, "Debug:- Cam Choice1. No Locking, used as game default");
break;
case MODE_REACTION:
sprintf(buf, "Debug:- Cam Choice2. Reaction Cam On A String ");
2020-03-27 17:19:08 +00:00
sprintf(buf, " Uses Locking Button LeftShoulder 1. "); // lie
2020-03-26 13:16:06 +00:00
break;
case MODE_FOLLOW_PED_WITH_BIND:
sprintf(buf, "Debug:- Cam Choice3. Game ReactionCam with Locking ");
sprintf(buf, " Uses Locking Button LeftShoulder 1. ");
break;
case MODE_CHRIS:
sprintf(buf, "Debug:- Cam Choice4. Chris's idea. ");
sprintf(buf, " Uses Locking Button LeftShoulder 1. ");
sprintf(buf, " Also control the camera using the right analogue stick.");
break;
}
}
}
// This code is really bad. wtf R*?
CVector
CCam::DoAverageOnVector(const CVector &vec)
{
int i;
CVector Average = { 0.0f, 0.0f, 0.0f };
if(ResetStatics){
m_iRunningVectorArrayPos = 0;
m_iRunningVectorCounter = 1;
}
// TODO: make this work with NUMBER_OF_VECTORS_FOR_AVERAGE != 2
if(m_iRunningVectorCounter == 3){
m_arrPreviousVectors[0] = m_arrPreviousVectors[1];
m_arrPreviousVectors[1] = vec;
}else
m_arrPreviousVectors[m_iRunningVectorArrayPos] = vec;
for(i = 0; i <= m_iRunningVectorArrayPos; i++)
Average += m_arrPreviousVectors[i];
Average /= i;
m_iRunningVectorArrayPos++;
m_iRunningVectorCounter++;
if(m_iRunningVectorArrayPos >= NUMBER_OF_VECTORS_FOR_AVERAGE)
m_iRunningVectorArrayPos = NUMBER_OF_VECTORS_FOR_AVERAGE-1;
if(m_iRunningVectorCounter > NUMBER_OF_VECTORS_FOR_AVERAGE+1)
m_iRunningVectorCounter = NUMBER_OF_VECTORS_FOR_AVERAGE+1;
return Average;
}
// Rotate Beta in direction opposite of BetaOffset in 5 deg. steps.
// Return the first angle for which Beta + BetaOffset + Angle has a clear view.
// i.e. BetaOffset is a safe zone so that Beta + Angle is really clear.
// If BetaOffset == 0, try both directions.
float
CCam::GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
{
CColPoint point;
CEntity *ent = nil;
CVector ToSource;
float a;
// This would be so much nicer if we just got the step variable before the loop...R*
for(a = 0.0f; a <= PI; a += DEGTORAD(5.0f)){
if(BetaOffset <= 0.0f){
ToSource = CVector(Cos(Beta + BetaOffset + a), Sin(Beta + BetaOffset + a), 0.0f)*Dist;
if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
point, ent, checkBuildings, checkVehicles, checkPeds,
checkObjects, checkDummies, true, true))
return a;
}
if(BetaOffset >= 0.0f){
ToSource = CVector(Cos(Beta + BetaOffset - a), Sin(Beta + BetaOffset - a), 0.0f)*Dist;
if(!CWorld::ProcessLineOfSight(Target, Target + ToSource,
point, ent, checkBuildings, checkVehicles, checkPeds,
checkObjects, checkDummies, true, true))
return -a;
}
}
return 0.0f;
}
2020-06-09 13:50:00 +00:00
float DefaultAcceleration = 0.045f;
float DefaultMaxStep = 0.15f;
float fDefaultSpeedStep = 0.025f;
float fDefaultSpeedMultiplier = 0.09f;
float fDefaultSpeedLimit = 0.15f;
float fDefaultSpeedStep4Avoid = 0.02f;
float fDefaultSpeedMultiplier4Avoid = 0.05f;
float fDefaultSpeedLimit4Avoid = 0.25f;
float fAvoidGeomThreshhold = 1.5f;
float fMiniGunBetaOffset = 0.3f;
2020-03-26 13:16:06 +00:00
void
CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float)
{
2020-06-09 13:50:00 +00:00
if(!CamTargetEntity->IsPed())
return;
2020-03-26 13:16:06 +00:00
CVector TargetCoors, Dist, IdealSource;
float Length = 0.0f;
static bool PickedASide;
static float FixedTargetOrientation = 0.0f;
float AngleToGoTo = 0.0f;
2020-06-09 13:50:00 +00:00
bool StandingInTrain = false;
float ZoomGroundTarget = 0.0f;
float ZoomZTarget = 0.0f;
2020-03-26 13:16:06 +00:00
static int TimeIndicatedWantedToGoDown = 0;
static bool StartedCountingForGoDown = false;
2020-06-09 13:50:00 +00:00
static float ZoomGround = 0.0f;
static float ZoomGroundSpeed = 0.0f;
static float ZoomZ = 0.0f;
static float ZoomZSpeed = 0.0f;
2020-03-26 13:16:06 +00:00
float DeltaBeta;
m_bFixingBeta = false;
bBelowMinDist = false;
bBehindPlayerDesired = false;
FOV = DefaultFOV;
if(ResetStatics){
Rotating = false;
m_bCollisionChecksOn = true;
FixedTargetOrientation = 0.0f;
PickedASide = false;
StartedCountingForGoDown = false;
AngleToGoTo = 0.0f;
2020-06-09 13:50:00 +00:00
ZoomGround = 0.0f;
ZoomGroundSpeed = 0.0f;
ZoomZ = 0.0f;
ZoomZSpeed = 0.0f;
Distance = 500.0f;
2020-03-26 13:16:06 +00:00
}
TargetCoors = CameraTarget;
2020-06-09 13:50:00 +00:00
// Take speed of thing we're standing on into account
CVector GroundMovement(0.0f, 0.0f, 0.0f);
CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;
if(ground && (ground->IsVehicle() || ground->IsObject()))
GroundMovement += ground->GetSpeed(CamTargetEntity->GetPosition() - ground->GetPosition()) * CTimer::GetTimeStep();
Source += GroundMovement;
2020-03-26 13:16:06 +00:00
IdealSource = Source;
TargetCoors.z += m_fSyphonModeTargetZOffSet;
2020-06-09 13:50:00 +00:00
TargetCoors.z = DoAverageOnVector(TargetCoors).z;
2020-03-26 13:16:06 +00:00
Dist.x = IdealSource.x - TargetCoors.x;
Dist.y = IdealSource.y - TargetCoors.y;
Length = Dist.Magnitude2D();
// Cam on a string. With a fixed distance. Zoom in/out is done later.
2020-06-09 13:50:00 +00:00
if(Length != 0.0f){
IdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * m_fMinRealGroundDist;
IdealSource.z += GroundMovement.z;
}else
2020-03-26 13:16:06 +00:00
IdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f);
if(TheCamera.m_bUseTransitionBeta && ResetStatics){
CVector VecDistance;
2020-06-09 13:50:00 +00:00
IdealSource.x = TargetCoors.x + m_fMinRealGroundDist*Cos(m_fTransitionBeta);
IdealSource.y = TargetCoors.y + m_fMinRealGroundDist*Sin(m_fTransitionBeta);
2020-03-26 13:16:06 +00:00
Beta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y);
}else
Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
if(TheCamera.m_bCamDirectlyBehind){
m_bCollisionChecksOn = true;
Beta = TargetOrientation + PI;
}
if(FindPlayerVehicle())
if(FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)
2020-06-09 13:50:00 +00:00
StandingInTrain = true;
2020-03-26 13:16:06 +00:00
if(TheCamera.m_bCamDirectlyInFront){
m_bCollisionChecksOn = true;
Beta = TargetOrientation;
}
while(Beta >= PI) Beta -= 2.0f * PI;
while(Beta < -PI) Beta += 2.0f * PI;
2020-06-09 13:50:00 +00:00
if(TheCamera.PedZoomIndicator == CAM_ZOOM_1 &&
((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR &&
((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK){
ZoomGroundTarget = m_fTargetZoomGroundOne;
ZoomZTarget = m_fTargetZoomOneZExtra;
}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1){
ZoomGroundTarget = m_fTargetZoomGroundTwo;
ZoomZTarget = m_fTargetZoomTwoZExtra;
}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_3){
ZoomGroundTarget = m_fTargetZoomGroundThree;
ZoomZTarget = m_fTargetZoomThreeZExtra;
}
if(m_fCloseInPedHeightOffset > 0.00001f){
ZoomGroundTarget = m_fTargetCloseInDist;
ZoomZTarget = m_fTargetZoomZCloseIn;
}
2020-03-26 13:16:06 +00:00
if(ResetStatics){
2020-06-09 13:50:00 +00:00
ZoomGround = ZoomGroundTarget;
ZoomZ = ZoomZTarget;
2020-03-26 13:16:06 +00:00
}
2020-06-09 13:50:00 +00:00
float SpeedStep = fDefaultSpeedStep;
float SpeedMultiplier = fDefaultSpeedMultiplier;
float SpeedLimit = fDefaultSpeedLimit;
2020-03-26 13:16:06 +00:00
bool Shooting = false;
CPed *ped = (CPed*)CamTargetEntity;
if(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
if(CPad::GetPad(0)->GetWeapon())
Shooting = true;
if(ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||
ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)
Shooting = false;
// Figure out if and where we want to rotate
2020-06-09 13:50:00 +00:00
if(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup || Shooting){
2020-03-26 13:16:06 +00:00
// Center cam behind player
if(PickedASide){
2020-06-09 13:50:00 +00:00
if(AngleToGoTo == 0.0f){
2020-03-26 13:16:06 +00:00
FixedTargetOrientation = TargetOrientation + PI;
2020-06-09 13:50:00 +00:00
if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)
FixedTargetOrientation -= fMiniGunBetaOffset;
}
2020-03-26 13:16:06 +00:00
Rotating = true;
}else{
2020-06-09 13:50:00 +00:00
FixedTargetOrientation = TargetOrientation + PI;
2020-03-26 13:16:06 +00:00
Rotating = true;
PickedASide = true;
2020-06-09 13:50:00 +00:00
if(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)
FixedTargetOrientation -= fMiniGunBetaOffset;
2020-03-26 13:16:06 +00:00
}
2020-06-09 13:50:00 +00:00
}else if(Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold && !Rotating ){
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
if(TheCamera.m_fAvoidTheGeometryProbsTimer < 0.0f)
FixedTargetOrientation = TargetOrientation;
else
FixedTargetOrientation = TargetOrientation + PI;
float dist = (Source - TargetCoors).Magnitude();
float mult = dist > 0.1f ? 1.0f/dist : 10.0f;
SpeedStep = mult * fDefaultSpeedStep4Avoid;
SpeedMultiplier = mult * fDefaultSpeedMultiplier4Avoid;
SpeedLimit = mult * fDefaultSpeedLimit4Avoid;
2020-03-26 13:16:06 +00:00
}
int MoveState = ((CPed*)CamTargetEntity)->m_nMoveState;
if(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL &&
2020-06-09 13:50:00 +00:00
!(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup) && !Shooting){
2020-03-26 13:16:06 +00:00
Rotating = false;
2020-06-09 13:50:00 +00:00
if(TheCamera.m_fAvoidTheGeometryProbsTimer <= fAvoidGeomThreshhold)
BetaSpeed = 0.0f;
2020-03-26 13:16:06 +00:00
}
// Now do the Beta rotation
2020-06-09 13:50:00 +00:00
float RotDistance = m_fMinRealGroundDist;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
if(Rotating || TheCamera.m_fAvoidTheGeometryProbsTimer > fAvoidGeomThreshhold){
2020-03-26 13:16:06 +00:00
m_bFixingBeta = true;
while(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI;
while(FixedTargetOrientation < -PI) FixedTargetOrientation += 2*PI;
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
2020-06-09 13:50:00 +00:00
// This is inlined WellBufferMe - unfortunately modified so we can't just call it
{
2020-03-26 13:16:06 +00:00
DeltaBeta = FixedTargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
2020-06-09 13:50:00 +00:00
// this is the added bit
if(!Rotating){
if(TheCamera.m_nAvoidTheGeometryProbsDirn == -1 && DeltaBeta > 0.0f ||
TheCamera.m_nAvoidTheGeometryProbsDirn == 1 && DeltaBeta < 0.0f)
DeltaBeta *= -1.0f;
}
float ReqSpeed = DeltaBeta * SpeedMultiplier;
// this is also added
ReqSpeed = clamp(ReqSpeed, -SpeedLimit, SpeedLimit);
2020-03-26 13:16:06 +00:00
// Add or subtract absolute depending on sign, genius!
if(ReqSpeed - BetaSpeed > 0.0f)
BetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
else
BetaSpeed -= SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();
// this would be simpler:
// BetaSpeed += SpeedStep * (ReqSpeed - BetaSpeed) * CTimer::ms_fTimeStep;
if(ReqSpeed < 0.0f && BetaSpeed < ReqSpeed)
BetaSpeed = ReqSpeed;
else if(ReqSpeed > 0.0f && BetaSpeed > ReqSpeed)
BetaSpeed = ReqSpeed;
2020-04-19 16:34:08 +00:00
Beta += BetaSpeed * Min(10.0f, CTimer::GetTimeStep());
2020-06-09 13:50:00 +00:00
}
2020-03-26 13:16:06 +00:00
if(ResetStatics){
Beta = FixedTargetOrientation;
BetaSpeed = 0.0f;
}
2020-04-02 10:48:01 +00:00
Source.x = TargetCoors.x + RotDistance * Cos(Beta);
Source.y = TargetCoors.y + RotDistance * Sin(Beta);
2020-03-26 13:16:06 +00:00
// Check if we can stop rotating
DeltaBeta = FixedTargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < DEGTORAD(1.0f) && !bBehindPlayerDesired){
// Stop rotation
PickedASide = false;
Rotating = false;
BetaSpeed = 0.0f;
}
}
if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront ||
2020-06-09 13:50:00 +00:00
StandingInTrain || Rotating ||
TheCamera.m_bUseTransitionBeta && ResetStatics ||
Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold){
if(TheCamera.m_bUseTransitionBeta){
Beta = m_fTransitionBeta;
Source.x = TargetCoors.x + RotDistance * Cos(m_fTransitionBeta);
Source.y = TargetCoors.y + RotDistance * Sin(m_fTransitionBeta);
}
2020-03-26 13:16:06 +00:00
if(TheCamera.m_bCamDirectlyBehind){
Beta = TargetOrientation + PI;
2020-04-02 10:48:01 +00:00
Source.x = TargetCoors.x + RotDistance * Cos(Beta);
Source.y = TargetCoors.y + RotDistance * Sin(Beta);
2020-03-26 13:16:06 +00:00
}
if(TheCamera.m_bCamDirectlyInFront){
Beta = TargetOrientation;
2020-04-02 10:48:01 +00:00
Source.x = TargetCoors.x + RotDistance * Cos(Beta);
Source.y = TargetCoors.y + RotDistance * Sin(Beta);
2020-03-26 13:16:06 +00:00
}
2020-06-09 13:50:00 +00:00
if(StandingInTrain){
2020-03-26 13:16:06 +00:00
Beta = TargetOrientation + PI;
2020-04-02 10:48:01 +00:00
Source.x = TargetCoors.x + RotDistance * Cos(Beta);
Source.y = TargetCoors.y + RotDistance * Sin(Beta);
2020-03-26 13:16:06 +00:00
m_fDimensionOfHighestNearCar = 0.0f;
m_fCamBufferedHeight = 0.0f;
m_fCamBufferedHeightSpeed = 0.0f;
}
2020-06-09 13:50:00 +00:00
if(StandingInTrain){
Beta = TargetOrientation + PI;
Source.x = TargetCoors.x + RotDistance * Cos(Beta);
Source.y = TargetCoors.y + RotDistance * Sin(Beta);
m_fDimensionOfHighestNearCar = 0.0f;
m_fCamBufferedHeight = 0.0f;
m_fCamBufferedHeightSpeed = 0.0f;
}
2020-03-26 13:16:06 +00:00
// Beta and Source already set in the rotation code
}else{
Source = IdealSource;
BetaSpeed = 0.0f;
}
2020-06-09 13:50:00 +00:00
Source.z = IdealSource.z;
2020-03-26 13:16:06 +00:00
// Zoom out camera
Front = TargetCoors - Source;
Front.Normalise();
2020-06-09 13:50:00 +00:00
WellBufferMe(ZoomGroundTarget, &ZoomGround, &ZoomGroundSpeed, 0.2f, 0.07f, false);
WellBufferMe(ZoomZTarget, &ZoomZ, &ZoomZSpeed, 0.2f, 0.07f, false);
Source.x -= Front.x*ZoomGround;
Source.y -= Front.y*ZoomGround;
Source.z += ZoomZ;
2020-03-26 13:16:06 +00:00
// Process height offset to avoid peds and cars
2020-06-09 13:50:00 +00:00
float TargetZOffSet = Max(m_fDimensionOfHighestNearCar, m_fPedBetweenCameraHeightOffset);
2020-03-26 13:16:06 +00:00
float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z;
if(TargetHeight > m_fCamBufferedHeight){
// Have to go up
if(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight)
WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false);
2020-06-09 13:50:00 +00:00
else
2020-03-26 13:16:06 +00:00
WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);
StartedCountingForGoDown = false;
}else{
// Have to go down
if(StartedCountingForGoDown){
if(CTimer::GetTimeInMilliseconds() != TimeIndicatedWantedToGoDown){
if(TargetHeight > 0.0f)
WellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
else
WellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);
}
}else{
StartedCountingForGoDown = true;
TimeIndicatedWantedToGoDown = CTimer::GetTimeInMilliseconds();
}
}
Source.z += m_fCamBufferedHeight;
2020-04-19 16:34:08 +00:00
TargetCoors.z += Min(1.0f, m_fCamBufferedHeight/2.0f);
2020-03-26 13:16:06 +00:00
m_cvecTargetCoorsForFudgeInter = TargetCoors;
2020-06-09 13:50:00 +00:00
CVector OrigSource = Source;
TheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);
float TargetDist = (TargetCoors - Source).Magnitude();
if(TargetDist < Distance)
Distance = TargetDist;
else{
float f = Pow(0.97f, CTimer::GetTimeStep());
Distance = (1.0f - f)*TargetDist + f*Distance;
if(TargetDist > 0.05f)
Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;
float clip = Distance-fRangePlayerRadius;
if(clip < RwCameraGetNearClipPlane(Scene.camera))
RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));
}
2020-03-26 13:16:06 +00:00
Front = TargetCoors - Source;
m_fRealGroundDist = Front.Magnitude2D();
m_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist;
Front.Normalise();
GetVectorsReadyForRW();
TheCamera.m_bCamDirectlyBehind = false;
TheCamera.m_bCamDirectlyInFront = false;
ResetStatics = false;
}
2020-06-09 13:50:00 +00:00
float fBaseDist = 1.7f;
float fAngleDist = 2.0f;
float fFalloff = 3.0f;
float fStickSens = 0.01f;
float fTweakFOV = 1.1f;
float fTranslateCamUp = 0.8f;
int16 nFadeControlThreshhold = 45;
float fDefaultAlphaOrient = -0.22f;
float fMouseAvoidGeomReturnRate = 0.92f;
2020-03-26 13:16:06 +00:00
void
CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float)
{
FOV = DefaultFOV;
if(!CamTargetEntity->IsPed())
return;
CVector TargetCoors;
float CamDist;
CColPoint colPoint;
CEntity *entity;
if(ResetStatics){
Rotating = false;
m_bCollisionChecksOn = true;
CPad::GetPad(0)->ClearMouseHistory();
ResetStatics = false;
}
bool OnTrain = FindPlayerVehicle() && FindPlayerVehicle()->IsTrain();
2020-06-09 13:50:00 +00:00
TargetCoors = CameraTarget;
TargetCoors.z += fTranslateCamUp;
2020-03-26 13:16:06 +00:00
float AlphaOffset, BetaOffset;
2020-06-09 13:50:00 +00:00
if(CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
CVector ToCam = Source - TargetCoors;
ToCam.Normalise();
if(ToCam.z < -0.9f)
BetaOffset = TargetOrientation + PI;
else
BetaOffset = Atan2(ToCam.y, ToCam.x);
AlphaOffset = 0.0f;
2020-03-26 13:16:06 +00:00
}else{
2020-06-09 13:50:00 +00:00
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
UseMouse = true;
LookLeftRight = -2.5f*MouseX;
LookUpDown = 4.0f*MouseY;
}else{
LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
}
if(UseMouse){
BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
}else{
BetaOffset = LookLeftRight * fStickSens * (1.0f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();
AlphaOffset = LookUpDown * fStickSens * (0.6f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();
}
2020-03-26 13:16:06 +00:00
}
if(TheCamera.GetFading() && TheCamera.GetFadingDirection() == FADE_IN && nFadeControlThreshhold < CDraw::FadeValue ||
2020-06-09 13:50:00 +00:00
CDraw::FadeValue > 200 ||
CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
2020-03-26 13:16:06 +00:00
if(Alpha < fDefaultAlphaOrient-0.05f)
AlphaOffset = 0.05f;
else if(Alpha < fDefaultAlphaOrient)
AlphaOffset = fDefaultAlphaOrient - Alpha;
else if(Alpha > fDefaultAlphaOrient+0.05f)
AlphaOffset = -0.05f;
else if(Alpha > fDefaultAlphaOrient)
AlphaOffset = fDefaultAlphaOrient - Alpha;
else
AlphaOffset = 0.0f;
}
Alpha += AlphaOffset;
Beta += BetaOffset;
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);
2020-06-09 13:50:00 +00:00
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
2020-03-26 13:16:06 +00:00
// SA code
#ifdef FREE_CAM
2020-04-02 10:48:01 +00:00
if((CCamera::bFreeCam && Alpha > 0.0f) || (!CCamera::bFreeCam && Alpha > fBaseDist))
#else
2020-03-26 13:16:06 +00:00
if(Alpha > fBaseDist) // comparing an angle against a distance?
#endif
2020-04-19 16:34:08 +00:00
CamDist = fBaseDist + Cos(Min(Alpha*fFalloff, HALFPI))*fAngleDist;
2020-03-26 13:16:06 +00:00
else
CamDist = fBaseDist + Cos(Alpha)*fAngleDist;
if(TheCamera.m_bUseTransitionBeta)
2020-06-09 13:50:00 +00:00
Beta = m_fTransitionBeta;
2020-03-26 13:16:06 +00:00
if(TheCamera.m_bCamDirectlyBehind)
Beta = TheCamera.m_PedOrientForBehindOrInFront + PI;
2020-06-09 13:50:00 +00:00
if(TheCamera.m_bCamDirectlyInFront)
Beta = TheCamera.m_PedOrientForBehindOrInFront;
2020-03-26 13:16:06 +00:00
if(OnTrain)
Beta = TargetOrientation;
Front.x = Cos(Alpha) * Cos(Beta);
Front.y = Cos(Alpha) * Sin(Beta);
Front.z = Sin(Alpha);
Source = TargetCoors - Front*CamDist;
m_cvecTargetCoorsForFudgeInter = TargetCoors;
// Clip Source and fix near clip
CWorld::pIgnoreEntity = CamTargetEntity;
entity = nil;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){
float PedColDist = (TargetCoors - colPoint.point).Magnitude();
float ColCamDist = CamDist - PedColDist;
2020-06-09 13:50:00 +00:00
if(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){
2020-03-26 13:16:06 +00:00
// Ped in the way but not clipping through
if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){
PedColDist = (TargetCoors - colPoint.point).Magnitude();
Source = colPoint.point;
2020-04-02 10:48:01 +00:00
if(PedColDist < DEFAULT_NEAR + 0.3f)
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));
2020-03-26 13:16:06 +00:00
}else{
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR));
2020-03-26 13:16:06 +00:00
}
}else{
Source = colPoint.point;
2020-04-02 10:48:01 +00:00
if(PedColDist < DEFAULT_NEAR + 0.3f)
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));
2020-03-26 13:16:06 +00:00
}
}
CWorld::pIgnoreEntity = nil;
float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);
2020-05-23 23:59:30 +00:00
float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV;
2020-03-26 13:16:06 +00:00
float Near = RwCameraGetNearClipPlane(Scene.camera);
float radius = ViewPlaneWidth*Near;
entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
int i = 0;
while(entity){
CVector CamToCol = gaTempSphereColPoints[0].point - Source;
float frontDist = DotProduct(CamToCol, Front);
float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;
// Try to decrease near clip
2020-04-19 16:34:08 +00:00
dist = Max(Min(Near, dist), 0.1f);
2020-03-26 13:16:06 +00:00
if(dist < Near)
RwCameraSetNearClipPlane(Scene.camera, dist);
// Move forward a bit
if(dist == 0.1f)
Source += (TargetCoors - Source)*0.3f;
2020-06-09 13:50:00 +00:00
Near = RwCameraGetNearClipPlane(Scene.camera);
2020-03-26 13:16:06 +00:00
#ifndef FIX_BUGS
2020-06-09 13:50:00 +00:00
// this is wrong...DEGTORAD missing
radius = Tan(FOV / 2.0f) * CDraw::CalculateAspectRatio() * fTweakFOV * Near;
#else
radius = ViewPlaneWidth*Near;
2020-03-26 13:16:06 +00:00
#endif
// Keep testing
entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
i++;
if(i > 5)
entity = nil;
}
2020-06-09 13:50:00 +00:00
float TargetDist = (TargetCoors - Source).Magnitude();
if(TargetDist < Distance)
Distance = TargetDist;
else{
float f = Pow(fMouseAvoidGeomReturnRate, CTimer::GetTimeStep());
Distance = (1.0f - f)*TargetDist + f*Distance;
if(TargetDist > 0.05f)
Source = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;
float clip = Distance-fRangePlayerRadius;
if(clip < RwCameraGetNearClipPlane(Scene.camera))
RwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));
}
2020-03-26 13:16:06 +00:00
TheCamera.m_bCamDirectlyInFront = false;
TheCamera.m_bCamDirectlyBehind = false;
GetVectorsReadyForRW();
if(((CPed*)CamTargetEntity)->CanStrafeOrMouseControl() && CDraw::FadeValue < 250 &&
2020-06-09 13:50:00 +00:00
(TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100) &&
!CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_DISABLED_20)){
2020-03-26 13:16:06 +00:00
float Heading = Front.Heading();
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
TheCamera.pTargetEntity->SetHeading(Heading);
TheCamera.pTargetEntity->GetMatrix().UpdateRW();
}
}
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float)
{
FOV = DefaultFOV;
if(!CamTargetEntity->IsVehicle())
return;
CVector TargetCoors = CameraTarget;
TargetCoors.z -= 0.2f;
CA_MAX_DISTANCE = 9.95f;
CA_MIN_DISTANCE = 8.5f;
CVector Dist = Source - TargetCoors;
float Length = Dist.Magnitude2D();
m_fDistanceBeforeChanges = Length;
if(Length < 0.002f)
Length = 0.002f;
Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
if(Length > CA_MAX_DISTANCE){
Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
}else if(Length < CA_MIN_DISTANCE){
Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
}
TargetCoors.z += 0.8f;
2020-06-09 13:50:00 +00:00
Alpha = DEGTORAD(25.0f);
Source.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);
2020-03-26 13:16:06 +00:00
RotCamIfInFrontCar(TargetCoors, TargetOrientation);
2020-06-09 13:50:00 +00:00
m_cvecTargetCoorsForFudgeInter = TargetCoors;
CVector OrigSource = Source;
TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);
2020-03-26 13:16:06 +00:00
Front = TargetCoors - Source;
ResetStatics = false;
GetVectorsReadyForRW();
}
2020-06-09 13:50:00 +00:00
float ZmOneAlphaOffset[] = { -0.01f, 0.1f, 0.125f, -0.1f, -0.06f };
float ZmTwoAlphaOffset[] = { 0.045f, 0.12f, 0.045f, 0.045f, -0.035f };
float ZmThreeAlphaOffset[] = { 0.005f, 0.005f, 0.15f, 0.005f, 0.12f };
float INIT_RC_HELI_HORI_EXTRA = 6.0f;
float INIT_RC_PLANE_HORI_EXTRA = 9.5f;
float INIT_RC_HELI_ALPHA_EXTRA = 0.2f;
float INIT_RC_PLANE_ALPHA_EXTRA = 0.295f;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight)
{
2020-06-09 13:50:00 +00:00
if(!CamTargetEntity->IsVehicle())
return;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
static float AlphaOffset = 0.0;
static float AlphaOffsetSpeed = 0.0;
static float AlphaDec = 0.0f;
bool isHeli = false;
bool isBike = false;
int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
if(appearance == VEHICLE_APPEARANCE_BIKE)
isBike = true;
if(appearance == VEHICLE_APPEARANCE_HELI)
isHeli = true;
int index = 0;
TheCamera.GetArrPosForVehicleType(appearance, index);
float ExtraOffset = 0.0f;
int id = CamTargetEntity->GetModelIndex();
if(id == MI_RCRAIDER || id == MI_RCGOBLIN)
ExtraOffset = INIT_RC_HELI_ALPHA_EXTRA;
else if(id == MI_RCBARON)
ExtraOffset = INIT_RC_PLANE_ALPHA_EXTRA;
2020-03-26 13:16:06 +00:00
if(ResetStatics){
2020-06-09 13:50:00 +00:00
AlphaOffset = 0.0f;
AlphaOffsetSpeed = 0.0f;
AlphaDec = 0.0f;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
if(TheCamera.CarZoomIndicator == CAM_ZOOM_1)
AlphaOffset = ZmOneAlphaOffset[index] + ExtraOffset;
else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)
AlphaOffset = ZmTwoAlphaOffset[index] + ExtraOffset;
else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)
AlphaOffset = ZmThreeAlphaOffset[index] + ExtraOffset;
}
2020-03-26 13:16:06 +00:00
2020-04-02 10:48:01 +00:00
if(TheCamera.CarZoomIndicator == CAM_ZOOM_1)
2020-06-09 13:50:00 +00:00
WellBufferMe(ZmOneAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
2020-04-02 10:48:01 +00:00
else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)
2020-06-09 13:50:00 +00:00
WellBufferMe(ZmTwoAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
2020-04-02 10:48:01 +00:00
else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)
2020-06-09 13:50:00 +00:00
WellBufferMe(ZmThreeAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);
2020-03-26 13:16:06 +00:00
float Length = (Source - TargetCoors).Magnitude2D();
2020-06-09 13:50:00 +00:00
CVector Forward = CamTargetEntity->GetForward();
float CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);
// this shouldn't be necessary....
while(CarAlpha >= PI) CarAlpha -= 2*PI;
while(CarAlpha < -PI) CarAlpha += 2*PI;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
float DeltaBeta = Beta - TargetOrientation;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
float BehindCarNess = Cos(DeltaBeta); // 1 if behind car, 0 if side, -1 if in front
CarAlpha = -CarAlpha * BehindCarNess;
float fwdSpeed = DotProduct(((CPhysical*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward())*180.0f;
if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired()){
CarAlpha = DEGTORAD(10.0f);
}else if(isHeli){
CarAlpha = 0.0f;
float heliFwdZ = CamTargetEntity->GetForward().z;
float heliFwdXY = CamTargetEntity->GetForward().Magnitude2D();
float alphaAmount = Min(Abs(fwdSpeed/90.0f), 1.0f);
if(heliFwdXY != 0.0f || heliFwdZ != 0.0f)
CarAlpha = CGeneral::GetATanOfXY(heliFwdXY, Abs(heliFwdZ)) * alphaAmount;
CColPoint point;
CEntity *entity = nil;
CVector Test = Source;
Test.z = TargetCoors.z + 0.2f + Length*Sin(CarAlpha+AlphaOffset) + m_fCloseInCarHeightOffset;
if(CWorld::ProcessVerticalLine(Test, CamTargetEntity->GetPosition().z, point, entity, true, false, false, false, false, false, nil)){
float sin = (point.point.z - TargetCoors.z - 0.2f - m_fCloseInCarHeightOffset)/Length;
CarAlpha = Asin(clamp(sin, -1.0f, 1.0f)) - AlphaOffset;
if(CarAlpha < 0.0f)
AlphaOffset += CarAlpha;
}
}
CarAlpha = CGeneral::LimitRadianAngle(CarAlpha);
if(CarAlpha < 0.0f) CarAlpha = 0.0f;
if(CarAlpha > DEGTORAD(89.0f)) CarAlpha = DEGTORAD(89.0f);
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
if(ResetStatics)
Alpha = CarAlpha;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
float TargetAlpha = Alpha;
float DeltaAlpha = CarAlpha - TargetAlpha;
while(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;
while(DeltaAlpha < -PI) DeltaAlpha += 2*PI;
if(Abs(DeltaAlpha) > 0.0f && !TheCamera.m_bVehicleSuspenHigh)
TargetAlpha = CarAlpha;
if(isBike)
WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);
else if(isHeli)
WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);
else
WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true);
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
Source.z = TargetCoors.z + Sin(Alpha + AlphaOffset)*Length + m_fCloseInCarHeightOffset;
AlphaOffset -= AlphaDec;
2020-03-26 13:16:06 +00:00
}
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
// Rotate cam behind the car when the car is moving forward
bool
CCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)
{
2020-06-09 13:50:00 +00:00
float BetaMaxSpeed = 0.15f;
float BetaAcceleration = 0.007f;
2020-03-26 13:16:06 +00:00
bool MovingForward = false;
2020-06-09 13:50:00 +00:00
float MaxDiffBeta = DEGTORAD(160.0f);
2020-03-26 13:16:06 +00:00
CPhysical *phys = (CPhysical*)CamTargetEntity;
float ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
if(ForwardSpeed > 0.02f)
MovingForward = true;
2020-06-09 13:50:00 +00:00
if(phys->IsVehicle() && (phys->GetModelIndex() == MI_SPARROW || phys->GetModelIndex() == MI_HUNTER)){
MaxDiffBeta = DEGTORAD(160.0f);
BetaMaxSpeed = 0.1f;
BetaAcceleration = 0.003f;
CVector speed = phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f));
speed.z = 0.0f;
if(50.0f*speed.Magnitude() > 3.13f)
TargetOrientation = CGeneral::GetATanOfXY(speed.x, speed.y);
}
2020-03-26 13:16:06 +00:00
float Dist = (Source - TargetCoors).Magnitude2D();
float DeltaBeta = TargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
2020-06-09 13:50:00 +00:00
if(Abs(DeltaBeta) > PI-MaxDiffBeta && MovingForward && TheCamera.m_uiTransitionState == 0)
2020-03-26 13:16:06 +00:00
m_bFixingBeta = true;
CPad *pad = CPad::GetPad(0);
if(!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))
if(DirectionWasLooking != LOOKING_FORWARD)
TheCamera.m_bCamDirectlyBehind = true;
if(!m_bFixingBeta && !TheCamera.m_bUseTransitionBeta && !TheCamera.m_bCamDirectlyBehind && !TheCamera.m_bCamDirectlyInFront)
return false;
bool SetBeta = false;
if(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront || TheCamera.m_bUseTransitionBeta)
if(&TheCamera.Cams[TheCamera.ActiveCam] == this)
SetBeta = true;
if(m_bFixingBeta || SetBeta){
2020-06-09 13:50:00 +00:00
WellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true);
2020-03-26 13:16:06 +00:00
if(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this)
Beta = TargetOrientation;
if(TheCamera.m_bCamDirectlyInFront && &TheCamera.Cams[TheCamera.ActiveCam] == this)
Beta = TargetOrientation + PI;
if(TheCamera.m_bUseTransitionBeta && &TheCamera.Cams[TheCamera.ActiveCam] == this)
Beta = m_fTransitionBeta;
Source.x = TargetCoors.x - Cos(Beta)*Dist;
Source.y = TargetCoors.y - Sin(Beta)*Dist;
// Check if we're done
DeltaBeta = TargetOrientation - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < DEGTORAD(2.0f))
m_bFixingBeta = false;
}
TheCamera.m_bCamDirectlyBehind = false;
TheCamera.m_bCamDirectlyInFront = false;
return true;
}
2020-06-09 13:50:00 +00:00
float FIRETRUCK_TRACKING_MULT = 0.1f;
float fTestShiftHeliCamTarget = 0.6f;
float TiltTopSpeed[] = { 0.035f, 0.035f, 0.001f, 0.005f, 0.035f };
float TiltSpeedStep[] = { 0.016f, 0.016f, 0.0002f, 0.0014f, 0.016f };
float TiltOverShoot[] = { 1.05f, 1.05f, 0.0f, 0.0f, 1.0f };
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float)
{
if(!CamTargetEntity->IsVehicle())
return;
2020-06-09 13:50:00 +00:00
// unused
// ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
if(ResetStatics){
AlphaSpeed = 0.0f;
2020-06-09 13:50:00 +00:00
m_fTilt = 0.0f;
m_fTiltSpeed = 0.0;
2020-03-26 13:16:06 +00:00
}
CBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
CVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min;
CVector TargetCoors = CameraTarget;
2020-06-09 13:50:00 +00:00
float BaseDist = Dimensions.Magnitude();
if(((CVehicle*)CamTargetEntity)->IsBike())
BaseDist *= 1.45f;
if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI &&
CamTargetEntity->GetStatus() != STATUS_PLAYER_REMOTE)
TargetCoors += fTestShiftHeliCamTarget * CamTargetEntity->GetUp() * Dimensions.z;
else
TargetCoors.z += 0.8f*Dimensions.z;
2020-03-26 13:16:06 +00:00
Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
2020-06-09 13:50:00 +00:00
Alpha = CGeneral::LimitRadianAngle(Alpha);
Beta = CGeneral::LimitRadianAngle(Beta);
if(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired() &&
((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude2D() < 0.01f){
float TargetBeta = CamTargetEntity->GetForward().Heading() - ((CAutomobile*)CamTargetEntity)->m_fCarGunLR + HALFPI;
TargetBeta = CGeneral::LimitRadianAngle(TargetBeta);
float DeltaBeta = TargetBeta - Beta;
if(DeltaBeta > PI) DeltaBeta -= TWOPI;
else if(DeltaBeta < -PI) DeltaBeta += TWOPI;
float dist = (TargetCoors - Source).Magnitude();
dist = FIRETRUCK_TRACKING_MULT*dist*clamp(DeltaBeta, -0.8f, 0.8f);
Source += dist*CrossProduct(Front, CVector(0.0f, 0.0f, 1.0f));
}
2020-03-26 13:16:06 +00:00
m_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D();
Cam_On_A_String_Unobscured(TargetCoors, BaseDist);
WorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z);
RotCamIfInFrontCar(TargetCoors, TargetOrientation);
FixCamWhenObscuredByVehicle(TargetCoors);
m_cvecTargetCoorsForFudgeInter = TargetCoors;
2020-06-09 13:50:00 +00:00
CVector OrigSource = Source;
if(CWorld::GetIsLineOfSightClear(CamTargetEntity->GetPosition(), m_cvecTargetCoorsForFudgeInter, true, false, false, true, false, false, true))
TheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);
else
TheCamera.AvoidTheGeometry(OrigSource, CamTargetEntity->GetPosition(), Source, FOV);
2020-03-26 13:16:06 +00:00
Front = TargetCoors - Source;
Front.Normalise();
2020-06-09 13:50:00 +00:00
int appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();
int index = 0;
TheCamera.GetArrPosForVehicleType(appearance, index);
if(appearance == VEHICLE_APPEARANCE_HELI){
float TargetTilt = DotProduct(Front, ((CVehicle*)CamTargetEntity)->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));
CVector UpTarget = CamTargetEntity->GetUp();
UpTarget.Normalise();
int dir = TargetTilt < 0.0f ? -1 : 1;
if(m_fTilt != 0.0f)
TargetTilt += TiltOverShoot[index]*TargetTilt/m_fTilt * dir;
WellBufferMe(TargetTilt, &m_fTilt, &m_fTiltSpeed, TiltTopSpeed[index], TiltSpeedStep[index], false);
Up = CVector(0.0f, 0.0f, 1.0f) - (CVector(0.0f, 0.0f, 1.0f) - UpTarget)*m_fTilt;
Up.Normalise();
Front.Normalise();
CVector Left = CrossProduct(Up, Front);
Up = CrossProduct(Front, Left);
Up.Normalise();
}else{
float TargetRoll;
if(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){
float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());
if(fwdSpeed > 210.0f) fwdSpeed = 210.0f;
if(CPad::GetPad(0)->GetDPadLeft())
TargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle;
else
TargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle);
CVector FwdTarget = CamTargetEntity->GetForward();
FwdTarget.Normalise();
float AngleDiff = DotProduct(FwdTarget, Front);
AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));
TargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff);
}else{
float fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());
if(fwdSpeed > 210.0f) fwdSpeed = 210.0f;
TargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f;
CVector FwdTarget = CamTargetEntity->GetForward();
FwdTarget.Normalise();
float AngleDiff = DotProduct(FwdTarget, Front);
AngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));
TargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff);
}
WellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false);
Up = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI));
Up.Normalise();
Front.Normalise();
CVector Left = CrossProduct(Up, Front);
Left.Normalise();
Up = CrossProduct(Front, Left);
Up.Normalise();
}
2020-03-26 13:16:06 +00:00
ResetStatics = false;
}
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
// Basic Cam on a string algorithm
void
CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)
{
2020-06-09 13:50:00 +00:00
int id = CamTargetEntity->GetModelIndex();
float ExtraDist = 0.0f;
if(id == MI_RCRAIDER || id == MI_RCGOBLIN)
ExtraDist = INIT_RC_HELI_HORI_EXTRA;
else if(id == MI_RCBARON)
ExtraDist = INIT_RC_PLANE_HORI_EXTRA;
CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth + ExtraDist;
2020-04-19 16:34:08 +00:00
CA_MIN_DISTANCE = Min(BaseDist*0.6f, 3.5f);
2020-06-09 13:50:00 +00:00
if(CA_MIN_DISTANCE > CA_MAX_DISTANCE)
CA_MIN_DISTANCE = CA_MAX_DISTANCE - 0.05f;
2020-03-26 13:16:06 +00:00
CVector Dist = Source - TargetCoors;
if(ResetStatics)
Source = TargetCoors + Dist*(CA_MAX_DISTANCE + 1.0f);
2020-06-09 13:50:00 +00:00
Dist = Source - TargetCoors;
2020-03-26 13:16:06 +00:00
float Length = Dist.Magnitude2D();
if(Length < 0.001f){
// This probably shouldn't happen. reset view
CVector Forward = CamTargetEntity->GetForward();
Forward.z = 0.0f;
Forward.Normalise();
Source = TargetCoors - Forward*CA_MAX_DISTANCE;
Dist = Source - TargetCoors;
Length = Dist.Magnitude2D();
}
if(Length > CA_MAX_DISTANCE){
Source.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;
Source.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;
}else if(Length < CA_MIN_DISTANCE){
Source.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;
Source.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;
}
}
2020-06-09 13:50:00 +00:00
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)
{
// BUG? is this never reset
static float HeightFixerCarsObscuring = 0.0f;
static float HeightFixerCarsObscuringSpeed = 0.0f;
CColPoint colPoint;
2020-06-09 13:50:00 +00:00
CEntity *entity = nil;
2020-03-26 13:16:06 +00:00
float HeightTarget = 0.0f;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, false, true, false, false, false, false, false)){
CBaseModelInfo *mi = CModelInfo::GetModelInfo(entity->GetModelIndex());
HeightTarget = mi->GetColModel()->boundingBox.max.z + 1.0f + TargetCoors.z - Source.z;
if(HeightTarget < 0.0f)
HeightTarget = 0.0f;
}
WellBufferMe(HeightTarget, &HeightFixerCarsObscuring, &HeightFixerCarsObscuringSpeed, 0.2f, 0.025f, false);
Source.z += HeightFixerCarsObscuring;
}
void
CCam::Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)
{
FOV = DefaultFOV;
if(!CamTargetEntity->IsVehicle())
return;
float Dist;
float HeightTarget = 0.0f;
static float AdjustHeightTargetMoveBuffer = 0.0f;
static float AdjustHeightTargetMoveSpeed = 0.0f;
static float NearClipDistance = 1.5f;
const float FarClipDistance = 200.0f;
CVector TargetFront, Target;
CVector TestSource, TestTarget;
CColPoint colPoint;
CEntity *entity;
TargetFront = CameraTarget;
TargetFront.x += 18.0f*CamTargetEntity->GetForward().x*SpeedVar;
TargetFront.y += 18.0f*CamTargetEntity->GetForward().y*SpeedVar;
if(ResetStatics){
AdjustHeightTargetMoveBuffer = 0.0f;
AdjustHeightTargetMoveSpeed = 0.0f;
}
float f = Pow(0.8f, 4.0f);
Target = f*CameraTarget + (1.0f-f)*TargetFront;
if(Mode == MODE_GTACLASSIC)
SpeedVar = TargetSpeedVar;
Source = Target + CVector(0.0f, 0.0f, (40.0f*SpeedVar + 30.0f)*0.8f);
// What is this? looks horrible
if(Mode == MODE_GTACLASSIC)
Source.x += (uint8)(100.0f*CameraTarget.x)/500.0f;
TestSource = Source;
TestTarget = TestSource;
TestTarget.z = Target.z;
if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
if(Source.z < colPoint.point.z+3.0f)
HeightTarget = colPoint.point.z+3.0f - Source.z;
}else{
TestSource = Source;
TestTarget = TestSource;
TestTarget.z += 10.0f;
if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false))
if(Source.z < colPoint.point.z+3.0f)
HeightTarget = colPoint.point.z+3.0f - Source.z;
}
WellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.2f, 0.02f, false);
Source.z += AdjustHeightTargetMoveBuffer;
if(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)
RwCameraSetFarClipPlane(Scene.camera, FarClipDistance);
RwCameraSetNearClipPlane(Scene.camera, NearClipDistance);
Front = CVector(-0.01f, -0.01f, -1.0f); // look down
Front.Normalise();
Dist = (Source - CameraTarget).Magnitude();
m_cvecTargetCoorsForFudgeInter = Dist*Front + Source;
Up = CVector(0.0f, 1.0f, 0.0f);
ResetStatics = false;
}
void
CCam::AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit)
{
float Target = 0.0f;
float MaxSpeed = 0.13f;
float Acceleration = 0.015f;
float SpeedMult;
float dy;
CVector TestPoint2;
CVector TestPoint1;
CColPoint colPoint;
CEntity *entity;
TestPoint2 = TargetCoors + Offset;
TestPoint1 = TargetCoors;
TestPoint1.z = TestPoint2.z;
if(CWorld::ProcessLineOfSight(TestPoint1, TestPoint2, colPoint, entity, true, false, false, false, false, false, false)){
// What is this even?
dy = TestPoint1.y - colPoint.point.y;
if(dy > yDistLimit)
dy = yDistLimit;
SpeedMult = yDistLimit - Abs(dy/yDistLimit);
Target = 2.5f;
MaxSpeed += SpeedMult*0.3f;
Acceleration += SpeedMult*0.03f;
}
WellBufferMe(Target, Adjuster, AdjusterSpeed, MaxSpeed, Acceleration, false);
}
void
CCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float)
{
if(!CamTargetEntity->IsPed())
return;
float Dist;
float HeightTarget;
static int NumPedPosCountsSoFar = 0;
static float PedAverageSpeed = 0.0f;
static float AdjustHeightTargetMoveBuffer = 0.0f;
static float AdjustHeightTargetMoveSpeed = 0.0f;
static float PedSpeedSoFar = 0.0f;
static float FarClipDistance = 200.0f;
static float NearClipDistance = 1.5f;
static float TargetAdjusterForSouth = 0.0f;
static float TargetAdjusterSpeedForSouth = 0.0f;
static float TargetAdjusterForNorth = 0.0f;
static float TargetAdjusterSpeedForNorth = 0.0f;
static float TargetAdjusterForEast = 0.0f;
static float TargetAdjusterSpeedForEast = 0.0f;
static float TargetAdjusterForWest = 0.0f;
static float TargetAdjusterSpeedForWest = 0.0f;
static CVector PreviousPlayerMoveSpeedVec;
CVector TargetCoors, PlayerMoveSpeed;
CVector TestSource, TestTarget;
CColPoint colPoint;
CEntity *entity;
FOV = DefaultFOV;
TargetCoors = CameraTarget;
PlayerMoveSpeed = ((CPed*)CamTargetEntity)->GetMoveSpeed();
if(ResetStatics){
PreviousPlayerMoveSpeedVec = PlayerMoveSpeed;
AdjustHeightTargetMoveBuffer = 0.0f;
AdjustHeightTargetMoveSpeed = 0.0f;
NumPedPosCountsSoFar = 0;
PedSpeedSoFar = 0.0f;
PedAverageSpeed = 0.0f;
TargetAdjusterForWest = 0.0f;
TargetAdjusterSpeedForWest = 0.0f;
TargetAdjusterForEast = 0.0f;
TargetAdjusterSpeedForEast = 0.0f;
TargetAdjusterForNorth = 0.0f;
TargetAdjusterSpeedForNorth = 0.0f;
TargetAdjusterForSouth = 0.0f;
TargetAdjusterSpeedForSouth = 0.0f;
}
if(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)
RwCameraSetFarClipPlane(Scene.camera, FarClipDistance);
RwCameraSetNearClipPlane(Scene.camera, NearClipDistance);
// Average ped speed
NumPedPosCountsSoFar++;
PedSpeedSoFar += PlayerMoveSpeed.Magnitude();
if(NumPedPosCountsSoFar == 5){
PedAverageSpeed = 0.4f*PedAverageSpeed + 0.6*(PedSpeedSoFar/5.0f);
NumPedPosCountsSoFar = 0;
PedSpeedSoFar = 0.0f;
}
PreviousPlayerMoveSpeedVec = PlayerMoveSpeed;
// Zoom out depending on speed
if(PedAverageSpeed > 0.01f && PedAverageSpeed <= 0.04f)
HeightTarget = 2.5f;
else if(PedAverageSpeed > 0.04f && PedAverageSpeed <= 0.145f)
HeightTarget = 4.5f;
else if(PedAverageSpeed > 0.145f)
HeightTarget = 7.0f;
else
HeightTarget = 0.0f;
// Zoom out if locked on target is far away
if(FindPlayerPed()->m_pPointGunAt){
Dist = (FindPlayerPed()->m_pPointGunAt->GetPosition() - CameraTarget).Magnitude2D();
if(Dist > 6.0f)
2020-04-19 16:34:08 +00:00
HeightTarget = Max(HeightTarget, Dist/22.0f*37.0f);
2020-03-26 13:16:06 +00:00
}
Source = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
// Collision checks
entity = nil;
TestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
TestTarget = TestSource;
TestTarget.z = TargetCoors.z;
if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
if(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)
HeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);
}else{
TestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);
TestTarget = TestSource;
TestSource.z += HeightTarget;
TestTarget.z = TestSource.z + 10.0f;
if(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){
if(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)
HeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);
}
}
WellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.3f, 0.03f, false);
Source.z += AdjustHeightTargetMoveBuffer;
// Wall checks
AvoidWallsTopDownPed(TargetCoors, CVector(0.0f, -3.0f, 3.0f), &TargetAdjusterForSouth, &TargetAdjusterSpeedForSouth, 1.0f);
Source.y += TargetAdjusterForSouth;
AvoidWallsTopDownPed(TargetCoors, CVector(0.0f, 3.0f, 3.0f), &TargetAdjusterForNorth, &TargetAdjusterSpeedForNorth, 1.0f);
Source.y -= TargetAdjusterForNorth;
// BUG: east and west flipped
AvoidWallsTopDownPed(TargetCoors, CVector(3.0f, 0.0f, 3.0f), &TargetAdjusterForWest, &TargetAdjusterSpeedForWest, 1.0f);
Source.x -= TargetAdjusterForWest;
AvoidWallsTopDownPed(TargetCoors, CVector(-3.0f, 0.0f, 3.0f), &TargetAdjusterForEast, &TargetAdjusterSpeedForEast, 1.0f);
Source.x += TargetAdjusterForEast;
TargetCoors.y = Source.y + 1.0f;
TargetCoors.y += TargetAdjusterForSouth;
TargetCoors.x += TargetAdjusterForEast;
TargetCoors.x -= TargetAdjusterForWest;
Front = TargetCoors - Source;
Front.Normalise();
#ifdef FIX_BUGS
if(Front.x == 0.0f && Front.y == 0.0f)
Front.y = 0.0001f;
#else
// someone used = instead of == in the above check by accident
Front.x = 0.0f;
#endif
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Up = CrossProduct(Front, CVector(-1.0f, 0.0f, 0.0f));
Up.Normalise();
ResetStatics = false;
}
void
CCam::Process_Rocket(const CVector &CameraTarget, float, float, float)
{
if(!CamTargetEntity->IsPed())
return;
static bool FailedTestTwelveFramesAgo = false;
RwV3d HeadPos;
CVector TargetCoors;
FOV = DefaultFOV;
TargetCoors = CameraTarget;
if(ResetStatics){
Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
Alpha = 0.0f;
m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
FailedTestTwelveFramesAgo = false;
// static DPadVertical unused
// static DPadHorizontal unused
m_bCollisionChecksOn = true;
ResetStatics = false;
}
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
2020-03-26 13:16:06 +00:00
Source = HeadPos;
Source.z += 0.1f;
Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
if(MouseX != 0.0f || MouseY != 0.0f){
UseMouse = true;
LookLeftRight = -3.0f*MouseX;
LookUpDown = 4.0f*MouseY;
}else{
LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
}
if(UseMouse){
Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
}else{
float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
2020-06-09 13:50:00 +00:00
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
}
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
Front = TargetCoors - Source;
Front.Normalise();
Source += Front*0.4f;
if(m_bCollisionChecksOn){
if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
CVector TestPoint;
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else
FailedTestTwelveFramesAgo = false;
}
}
}
if(FailedTestTwelveFramesAgo)
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source -= Front*0.4f;
GetVectorsReadyForRW();
float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
}
2020-06-09 13:50:00 +00:00
float fDuckingBackOffset = 0.5f;
float fDuckingRightOffset = 0.18f;
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
{
if(!CamTargetEntity->IsPed())
return;
2020-06-09 13:50:00 +00:00
float BackOffset = 0.3f;
2020-03-26 13:16:06 +00:00
static bool FailedTestTwelveFramesAgo = false;
RwV3d HeadPos;
CVector TargetCoors;
2020-06-09 13:50:00 +00:00
bool isAttached = ((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo;
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
TargetCoors = CameraTarget;
if(ResetStatics){
2020-06-09 13:50:00 +00:00
if(isAttached)
Beta = 0.0f;
else
Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
2020-03-26 13:16:06 +00:00
Alpha = 0.0f;
m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
FailedTestTwelveFramesAgo = false;
// static DPadVertical unused
// static DPadHorizontal unused
m_bCollisionChecksOn = true;
ResetStatics = false;
}
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
if(MouseX != 0.0f || MouseY != 0.0f){
UseMouse = true;
LookLeftRight = -3.0f*MouseX;
LookUpDown = 4.0f*MouseY;
}else{
LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
}
if(UseMouse){
Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
2020-06-09 13:50:00 +00:00
}else if(Mode == MODE_HELICANNON_1STPERSON){
LookLeftRight /= 128.0f;
LookUpDown /= 128.0f;
Beta += LookLeftRight*Abs(LookLeftRight)*0.56f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += LookUpDown*Abs(LookUpDown)*0.48f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
}else{
float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
2020-06-09 13:50:00 +00:00
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
}
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
2020-06-09 13:50:00 +00:00
if(((CPed*)CamTargetEntity)->bIsDucking)
BackOffset = 0.8f;
if(isAttached){
CMatrix mat, rot;
CPed *TargetPed = (CPed*)CamTargetEntity;
TargetPed->PositionAttachedPed();
CamTargetEntity->GetMatrix().UpdateRW();
CamTargetEntity->UpdateRwFrame();
CamTargetEntity->UpdateRpHAnim();
HeadPos.x = 0.0f;
HeadPos.y = 0.0f;
HeadPos.z = 0.0f;
TargetPed->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
Source = HeadPos;
Source += 0.1f*CamTargetEntity->GetUp();
Source -= BackOffset*CamTargetEntity->GetForward();
if(TargetPed->m_attachRotStep < PI){
if(Beta > TargetPed->m_attachRotStep){
Beta = TargetPed->m_attachRotStep;
CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;
if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){
float heliOrient = heli->m_fHeliOrientation + CTimer::GetTimeStep()*0.01f;
if(heliOrient < 0.0f) heliOrient += TWOPI;
else if(heliOrient > TWOPI) heliOrient -= TWOPI;
heli->SetHeliOrientation(heliOrient);
}
}else if(Beta < -TargetPed->m_attachRotStep){
Beta = -TargetPed->m_attachRotStep;
CAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;
if(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){
float heliOrient = heli->m_fHeliOrientation - CTimer::GetTimeStep()*0.01f;
if(heliOrient < 0.0f) heliOrient += TWOPI;
else if(heliOrient > TWOPI) heliOrient -= TWOPI;
heli->SetHeliOrientation(heliOrient);
}
}
}else{
while(Beta < -PI) Beta += 2*PI;
while(Beta >= PI) Beta -= 2*PI;
}
2020-04-19 14:38:10 +00:00
2020-06-09 13:50:00 +00:00
mat = TargetPed->m_attachedTo->GetMatrix();
rot.SetRotateX(Alpha);
switch(TargetPed->m_attachType){
case 1: rot.RotateZ(Beta + HALFPI); break;
case 2: rot.RotateZ(Beta + PI); break;
case 3: rot.RotateZ(Beta - HALFPI); break;
}
mat = mat * rot;
Front = mat.GetForward();
Up = mat.GetUp();
TargetCoors = Source + 3.0f*Front;
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
}else{
CamTargetEntity->GetMatrix().UpdateRW();
CamTargetEntity->UpdateRwFrame();
CamTargetEntity->UpdateRpHAnim();
HeadPos.x = 0.0f;
HeadPos.y = 0.0f;
HeadPos.z = 0.0f;
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
Source = HeadPos;
Source.z += 0.1f;
if(((CPed*)CamTargetEntity)->bIsDucking){
Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;
Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;
Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;
Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;
2020-03-26 13:16:06 +00:00
}else{
2020-06-09 13:50:00 +00:00
Source.x -= BackOffset*CamTargetEntity->GetForward().x;
Source.y -= BackOffset*CamTargetEntity->GetForward().y;
}
TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
Front = TargetCoors - Source;
Front.Normalise();
Source += Front*0.4f;
if(m_bCollisionChecksOn){
if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
2020-03-26 13:16:06 +00:00
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
2020-06-09 13:50:00 +00:00
CVector TestPoint;
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
2020-03-26 13:16:06 +00:00
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
2020-06-09 13:50:00 +00:00
}else{
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else
FailedTestTwelveFramesAgo = false;
}
2020-03-26 13:16:06 +00:00
}
}
2020-06-09 13:50:00 +00:00
if(FailedTestTwelveFramesAgo)
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source -= Front*0.4f;
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
GetVectorsReadyForRW();
float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
}
2020-03-26 13:16:06 +00:00
}
2020-06-09 13:50:00 +00:00
float fBike1stPersonOffsetZ = 0.15f;
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
2020-06-09 13:50:00 +00:00
CCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)
2020-03-26 13:16:06 +00:00
{
2020-06-09 13:50:00 +00:00
float BackOffset = 0.3f;
2020-03-26 13:16:06 +00:00
static float DontLookThroughWorldFixer = 0.0f;
CVector TargetCoors;
FOV = DefaultFOV;
TargetCoors = CameraTarget;
if(CamTargetEntity->m_rwObject == nil)
return;
if(ResetStatics){
Beta = TargetOrientation;
Alpha = 0.0f;
m_fInitialPlayerOrientation = TargetOrientation;
if(CamTargetEntity->IsPed()){
Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
Alpha = 0.0f;
m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
}
2020-06-09 13:50:00 +00:00
TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
2020-03-26 13:16:06 +00:00
DontLookThroughWorldFixer = 0.0f;
}
if(CamTargetEntity->IsPed()){
static bool FailedTestTwelveFramesAgo = false;
RwV3d HeadPos;
TargetCoors = CameraTarget;
if(ResetStatics){
Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
Alpha = 0.0f;
m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
FailedTestTwelveFramesAgo = false;
// static DPadVertical unused
// static DPadHorizontal unused
m_bCollisionChecksOn = true;
ResetStatics = false;
}
2020-06-09 13:50:00 +00:00
CamTargetEntity->GetMatrix().UpdateRW();
CamTargetEntity->UpdateRwFrame();
CamTargetEntity->UpdateRpHAnim();
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
2020-03-26 13:16:06 +00:00
Source = HeadPos;
Source.z += 0.1f;
2020-06-09 13:50:00 +00:00
if(((CPed*)CamTargetEntity)->bIsDucking){
Source.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;
Source.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;
Source.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;
Source.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;
}else{
Source.x -= BackOffset*CamTargetEntity->GetForward().x;
Source.y -= BackOffset*CamTargetEntity->GetForward().y;
}
2020-03-26 13:16:06 +00:00
float LookLeftRight, LookUpDown;
LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
2020-06-09 13:50:00 +00:00
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
2020-06-09 13:50:00 +00:00
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
2020-03-26 13:16:06 +00:00
TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
Front = TargetCoors - Source;
Front.Normalise();
Source += Front*0.4f;
if(m_bCollisionChecksOn){
if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
CVector TestPoint;
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else
FailedTestTwelveFramesAgo = false;
}
}
}
if(FailedTestTwelveFramesAgo)
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source -= Front*0.4f;
GetVectorsReadyForRW();
float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
}else{
assert(CamTargetEntity->IsVehicle());
2020-06-09 13:50:00 +00:00
if(((CVehicle*)CamTargetEntity)->IsBike() &&
(((CBike*)CamTargetEntity)->bWheelieCam || TheCamera.m_fAvoidTheGeometryProbsTimer > 0.0f)){
if(CPad::GetPad(0)->GetLeftShoulder2() || CPad::GetPad(0)->GetRightShoulder2()){
TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
((CBike*)CamTargetEntity)->bWheelieCam = false;
}else if(Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar)){
if(((CBike*)CamTargetEntity)->bWheelieCam)
TheCamera.m_fAvoidTheGeometryProbsTimer = 50.0f;
else{
TheCamera.m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep();
((CBike*)CamTargetEntity)->bWheelieCam = true;
}
return;
}else{
TheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;
((CBike*)CamTargetEntity)->bWheelieCam = false;
}
}
CMatrix *matrix = &CamTargetEntity->GetMatrix();
if(((CVehicle*)CamTargetEntity)->IsBike()){
((CBike*)CamTargetEntity)->CalculateLeanMatrix();
matrix = &((CBike*)CamTargetEntity)->m_leanMatrix;
}
2020-03-26 13:16:06 +00:00
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());
2020-06-02 21:35:20 +00:00
CVector CamPos = mi->GetFrontSeatPosn();
2020-03-26 13:16:06 +00:00
CamPos.x = 0.0f;
2020-06-09 13:50:00 +00:00
CamPos.y += 0.08f;
2020-03-26 13:16:06 +00:00
CamPos.z += 0.62f;
FOV = 60.0f;
2020-06-09 13:50:00 +00:00
Source = Multiply3x3(*matrix, CamPos);
2020-03-26 13:16:06 +00:00
Source += CamTargetEntity->GetPosition();
if(((CVehicle*)CamTargetEntity)->IsBoat())
Source.z += 0.5f;
2020-06-09 13:50:00 +00:00
else if(((CVehicle*)CamTargetEntity)->IsBike() && ((CVehicle*)CamTargetEntity)->pDriver){
CVector Neck(0.0f, 0.0f, 0.0f);
((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(*(RwV3d*)&Neck, PED_NECK);
Neck += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep();
Source.z = Neck.z + fBike1stPersonOffsetZ;
}
2020-03-26 13:16:06 +00:00
if(((CVehicle*)CamTargetEntity)->IsUpsideDown()){
if(DontLookThroughWorldFixer < 0.5f)
DontLookThroughWorldFixer += 0.03f;
else
DontLookThroughWorldFixer = 0.5f;
}else{
if(DontLookThroughWorldFixer < 0.0f)
#ifdef FIX_BUGS
DontLookThroughWorldFixer += 0.03f;
#else
DontLookThroughWorldFixer -= 0.03f;
#endif
else
DontLookThroughWorldFixer = 0.0f;
}
Source.z += DontLookThroughWorldFixer;
2020-06-09 13:50:00 +00:00
Front = matrix->GetForward();
2020-03-26 13:16:06 +00:00
Front.Normalise();
2020-06-09 13:50:00 +00:00
Up = matrix->GetUp();
2020-03-26 13:16:06 +00:00
Up.Normalise();
CVector Right = CrossProduct(Front, Up);
Right.Normalise();
Up = CrossProduct(Right, Front);
Up.Normalise();
}
ResetStatics = false;
}
static CVector vecHeadCamOffset(0.06f, 0.05f, 0.0f);
void
CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, float)
{
// static int DontLookThroughWorldFixer = 0; // unused
static CVector InitialHeadPos;
if(Mode != MODE_SNIPER_RUNABOUT)
FOV = DefaultFOV;
TheCamera.m_1rstPersonRunCloseToAWall = false;
if(CamTargetEntity->m_rwObject == nil)
return;
if(CamTargetEntity->IsPed()){
// static bool FailedTestTwelveFramesAgo = false; // unused
CVector HeadPos = vecHeadCamOffset;
2020-03-26 13:16:06 +00:00
CVector TargetCoors;
((CPed*)CamTargetEntity)->TransformToNode(HeadPos, PED_HEAD);
// This is done on PC, but checking for the clump frame is not necessary apparently
/*
RwFrame *frm = ((CPed*)CamTargetEntity)->m_pFrames[PED_HEAD]->frame;
2020-03-26 13:16:06 +00:00
while(frm){
RwV3dTransformPoints(&HeadPos, &HeadPos, 1, RwFrameGetMatrix(frm));
frm = RwFrameGetParent(frm);
if(frm == RpClumpGetFrame(CamTargetEntity->GetClump()))
frm = nil;
}
*/
2020-03-26 13:16:06 +00:00
if(ResetStatics){
Beta = TargetOrientation;
Alpha = 0.0f;
m_fInitialPlayerOrientation = TargetOrientation;
if(CamTargetEntity->IsPed()){ // useless check
Beta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
Alpha = 0.0f;
m_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;
// FailedTestTwelveFramesAgo = false;
m_bCollisionChecksOn = true;
}
// DontLookThroughWorldFixer = false;
m_vecBufferedPlayerBodyOffset = HeadPos;
InitialHeadPos = HeadPos;
}
m_vecBufferedPlayerBodyOffset.y = HeadPos.y;
if(TheCamera.m_bHeadBob){
m_vecBufferedPlayerBodyOffset.x =
TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.x +
(1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.x;
m_vecBufferedPlayerBodyOffset.z =
TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.z +
(1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.z;
HeadPos = (CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset);
2020-03-26 13:16:06 +00:00
}else{
float HeadDelta = (HeadPos - InitialHeadPos).Magnitude2D();
CVector Fwd = CamTargetEntity->GetForward();
Fwd.z = 0.0f;
Fwd.Normalise();
HeadPos = (HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition());
2020-03-26 13:16:06 +00:00
HeadPos.z += 0.59f;
}
Source = HeadPos;
// unused:
// ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&MidPos, PED_MID);
// Source - MidPos;
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
if(MouseX != 0.0f || MouseY != 0.0f){
UseMouse = true;
LookLeftRight = -3.0f*MouseX;
LookUpDown = 4.0f*MouseY;
}else{
LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
LookUpDown = CPad::GetPad(0)->LookAroundUpDown();
}
if(UseMouse){
Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
}else{
float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
2020-06-09 13:50:00 +00:00
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
}
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
Front = TargetCoors - Source;
Front.Normalise();
Source += Front*0.4f;
TheCamera.m_AlphaForPlayerAnim1rstPerson = Alpha;
GetVectorsReadyForRW();
float Heading = Front.Heading();
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
TheCamera.pTargetEntity->SetHeading(Heading);
TheCamera.pTargetEntity->GetMatrix().UpdateRW();
if(Mode == MODE_SNIPER_RUNABOUT){
// no mouse wheel FOV buffering here like in normal sniper mode
if(CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()){
if(CPad::GetPad(0)->SniperZoomOut())
FOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
else
FOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
}
TheCamera.SetMotionBlur(180, 255, 180, 120, MBLUR_SNIPER);
if(FOV > DefaultFOV)
FOV = DefaultFOV;
if(FOV < 15.0f)
FOV = 15.0f;
}
}
ResetStatics = false;
RwCameraSetNearClipPlane(Scene.camera, 0.05f);
}
void
CCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float, float)
{
if(CamTargetEntity->m_rwObject == nil)
return;
#ifdef FIX_BUGS
if(!CamTargetEntity->IsPed())
return;
#endif
static bool FailedTestTwelveFramesAgo = false;
RwV3d HeadPos;
CVector TargetCoors;
TargetCoors = CameraTarget;
static float TargetFOV = 0.0f;
if(ResetStatics){
Beta = TargetOrientation;
Alpha = 0.0f;
m_fInitialPlayerOrientation = TargetOrientation;
FailedTestTwelveFramesAgo = false;
// static DPadVertical unused
// static DPadHorizontal unused
m_bCollisionChecksOn = true;
FOVSpeed = 0.0f;
TargetFOV = FOV;
ResetStatics = false;
}
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);
2020-03-26 13:16:06 +00:00
Source = HeadPos;
Source.z += 0.1f;
Source.x -= 0.19f*Cos(m_fInitialPlayerOrientation);
Source.y -= 0.19f*Sin(m_fInitialPlayerOrientation);
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
if(MouseX != 0.0f || MouseY != 0.0f){
UseMouse = true;
LookLeftRight = -3.0f*MouseX;
LookUpDown = 4.0f*MouseY;
}else{
LookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();
LookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();
}
if(UseMouse){
Beta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;
Alpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;
}else{
float xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;
float ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;
2020-06-09 13:50:00 +00:00
Beta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
Alpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();
2020-03-26 13:16:06 +00:00
}
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
TargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;
TargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;
TargetCoors.z = 3.0f * Sin(Alpha) + Source.z;
UseMouse = false;
int ZoomInButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN);
int ZoomOutButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT);
// TODO: enum? this should be mouse wheel up and down
if(ZoomInButton == 4 || ZoomInButton == 5 || ZoomOutButton == 4 || ZoomOutButton == 5){
if(CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetMouseWheelDown()){
if(CPad::GetPad(0)->SniperZoomIn()){
TargetFOV = FOV - 10.0f;
UseMouse = true;
}
if(CPad::GetPad(0)->SniperZoomOut()){
TargetFOV = FOV + 10.0f;
UseMouse = true;
}
}
}
if((CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()) && !UseMouse){
if(CPad::GetPad(0)->SniperZoomOut()){
FOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
TargetFOV = FOV;
FOVSpeed = 0.0f;
}else{
FOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;
TargetFOV = FOV;
FOVSpeed = 0.0f;
}
}else{
if(Abs(TargetFOV - FOV) > 0.5f)
WellBufferMe(TargetFOV, &FOV, &FOVSpeed, 0.5f, 0.25f, false);
else
FOVSpeed = 0.0f;
}
TheCamera.SetMotionBlur(180, 255, 180, 120, MBLUR_SNIPER);
if(FOV > DefaultFOV)
FOV = DefaultFOV;
if(FOV < 15.0f)
FOV = 15.0f;
Front = TargetCoors - Source;
Front.Normalise();
Source += Front*0.4f;
if(m_bCollisionChecksOn){
if(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
CVector TestPoint;
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else{
TestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;
TestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;
TestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;
if(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
FailedTestTwelveFramesAgo = true;
}else
FailedTestTwelveFramesAgo = false;
}
}
}
if(FailedTestTwelveFramesAgo)
RwCameraSetNearClipPlane(Scene.camera, 0.4f);
Source -= Front*0.4f;
GetVectorsReadyForRW();
float Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;
}
2020-06-09 13:50:00 +00:00
float INIT_SYPHON_GROUND_DIST = 2.419f;
float INIT_SYPHON_ALPHA_OFFSET = -DEGTORAD(3.0f);
float INIT_SYPHON_DEGREE_OFFSET = -DEGTORAD(30.0f);
float FrontOffsetSyphon = -DEGTORAD(25.5f); // unused
float INIT_SYPHON_Z_OFFSET = -0.5f;
//--MIAMI: done
2020-03-26 13:16:06 +00:00
void
CCam::Process_Syphon(const CVector &CameraTarget, float, float, float)
{
FOV = DefaultFOV;
if(!CamTargetEntity->IsPed())
return;
static bool CameraObscured = false;
// unused FailedClippingTestPrevously
2020-06-09 13:50:00 +00:00
static float BetaOffset = INIT_SYPHON_DEGREE_OFFSET;
2020-03-26 13:16:06 +00:00
// unused AngleToGoTo
// unused AngleToGoToSpeed
// unused DistBetweenPedAndPlayerPreviouslyOn
2020-06-09 13:50:00 +00:00
static float HeightDown = INIT_SYPHON_Z_OFFSET;
static float AlphaOffset = INIT_SYPHON_ALPHA_OFFSET;
static bool NegateBetaOffset = true;
2020-03-26 13:16:06 +00:00
CVector TargetCoors;
2020-06-09 13:50:00 +00:00
float fAimingDist;
2020-03-26 13:16:06 +00:00
float TargetAlpha;
2020-06-09 13:50:00 +00:00
bool StandingOnMovingThing = false;
2020-03-26 13:16:06 +00:00
TargetCoors = CameraTarget;
2020-06-09 13:50:00 +00:00
AlphaOffset = INIT_SYPHON_ALPHA_OFFSET;
float GroundDist = INIT_SYPHON_GROUND_DIST;
2020-03-26 13:16:06 +00:00
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
float NewBeta = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y) + PI;
if(ResetStatics){
2020-06-09 13:50:00 +00:00
BetaOffset = INIT_SYPHON_DEGREE_OFFSET;
Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
2020-03-26 13:16:06 +00:00
// some unuseds
ResetStatics = false;
}
2020-06-09 13:50:00 +00:00
if(NegateBetaOffset)
BetaOffset = -INIT_SYPHON_DEGREE_OFFSET;
2020-03-26 13:16:06 +00:00
Beta = NewBeta + BetaOffset;
Source = TargetCoors;
2020-06-09 13:50:00 +00:00
Source.x += GroundDist*Cos(Beta);
Source.y += GroundDist*Sin(Beta);
CPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;
if(ground && (ground->IsVehicle() || ground->IsObject()))
StandingOnMovingThing = true;
2020-03-26 13:16:06 +00:00
TargetCoors.z += m_fSyphonModeTargetZOffSet;
2020-06-09 13:50:00 +00:00
bool PlayerTooClose = false;
2020-03-26 13:16:06 +00:00
fAimingDist = (TheCamera.m_cvecAimingTargetCoors - TargetCoors).Magnitude2D();
2020-06-09 13:50:00 +00:00
if(fAimingDist < 6.5f){
2020-03-26 13:16:06 +00:00
fAimingDist = 6.5f;
2020-06-09 13:50:00 +00:00
PlayerTooClose = true;
}
2020-03-26 13:16:06 +00:00
TargetAlpha = CGeneral::GetATanOfXY(fAimingDist, TheCamera.m_cvecAimingTargetCoors.z - TargetCoors.z);
2020-06-09 13:50:00 +00:00
if(ResetStatics) // BUG: can never happen
Alpha = -TargetAlpha;
2020-03-26 13:16:06 +00:00
while(TargetAlpha >= PI) TargetAlpha -= 2*PI;
while(TargetAlpha < -PI) TargetAlpha += 2*PI;
2020-06-09 13:50:00 +00:00
while(Alpha >= PI) Alpha -= 2*PI;
while(Alpha < -PI) Alpha += 2*PI;
2020-03-26 13:16:06 +00:00
// inlined
2020-06-09 13:50:00 +00:00
if(StandingOnMovingThing)
WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f/2.0f, 0.015f/2.0f, true);
else
WellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true);
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
Source.z += GroundDist*Sin(Alpha+AlphaOffset) + GroundDist*0.2f;
2020-03-26 13:16:06 +00:00
if(Source.z < TargetCoors.z + HeightDown)
Source.z = TargetCoors.z + HeightDown;
2020-06-09 13:50:00 +00:00
if(!PlayerTooClose){
CColPoint point;
CEntity *entity = nil;
CWorld::pIgnoreEntity = CamTargetEntity;
if(CWorld::ProcessLineOfSight(TheCamera.m_cvecAimingTargetCoors, Source, point, entity, true, false, false, true, false, false, true)){
CVector TestFront = TheCamera.m_cvecAimingTargetCoors - Source;
TestFront.Normalise();
CVector CamToPlayer = CameraTarget - Source;
CVector CamToCol = point.point - Source;
if(DotProduct(TestFront, CamToCol) > DotProduct(TestFront, CamToPlayer)){
// collision is beyond player
float ColDist = (TheCamera.m_cvecAimingTargetCoors - point.point).Magnitude();
CVector PlayerToTarget = TheCamera.m_cvecAimingTargetCoors - CameraTarget;
float PlayerToTargetDist = PlayerToTarget.Magnitude();
PlayerToTarget.Normalise();
CVector Center = TheCamera.m_cvecAimingTargetCoors - ColDist*PlayerToTarget;
float Radius = (point.point - Center).Magnitude();
if(CWorld::TestSphereAgainstWorld(Center, Radius, nil, true, false, false, true, false, true)){
CVector LineToCol = gaTempSphereColPoints[0].point - Center;
LineToCol -= DotProduct(LineToCol, PlayerToTarget)*PlayerToTarget;
// unused
CVector LineToPrevCol = point.point - Center;
LineToPrevCol -= DotProduct(LineToPrevCol, PlayerToTarget)*PlayerToTarget;
float LineDist = LineToCol.Magnitude();
float NewBetaOffset = 0.0f;
if(LineDist > 0.0f && ColDist > 0.1f){
// scale offset at center to offset at player
float DistOffset = LineDist/ColDist * PlayerToTargetDist;
// turn into an angle
NewBetaOffset = 0.9f*Asin(Min(DistOffset/GroundDist, 1.0f));
}
if(NewBetaOffset < BetaOffset){
float Ratio = NewBetaOffset / BetaOffset;
BetaOffset = NewBetaOffset;
Beta = NewBeta + NewBetaOffset;
GroundDist *= Max(Ratio, 0.5f);
Source.x = TargetCoors.x + GroundDist*Cos(Beta);
Source.y = TargetCoors.y + GroundDist*Sin(Beta);
Source.z += (1.0f-Ratio)*0.5f;
}
}
}
}
CWorld::pIgnoreEntity = nil;
}
2020-03-26 13:16:06 +00:00
2020-06-09 13:50:00 +00:00
Front = TheCamera.m_cvecAimingTargetCoors - Source;
float TargetDistGround = Front.Magnitude2D();
2020-03-26 13:16:06 +00:00
Front.Normalise();
2020-06-09 13:50:00 +00:00
m_cvecTargetCoorsForFudgeInter = Source + TargetDistGround*Front;
m_cvecTargetCoorsForFudgeInter.z = TargetCoors.z;
CVector OrigSource = Source;
TheCamera.AvoidTheGeometry(OrigSource, CameraTarget + CVector(0.0f, 0.0f, 0.75f), Source, FOV);
Source.z = OrigSource.z;
2020-03-26 13:16:06 +00:00
GetVectorsReadyForRW();
}
void
CCam::Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float)
{
FOV = DefaultFOV;
if(!CamTargetEntity->IsPed())
return;
CVector TargetCoors = CameraTarget;
CVector vDist;
float fDist, TargetDist;
float zOffset;
float AimingAngle;
CColPoint colPoint;
CEntity *entity;
TargetDist = TheCamera.m_fPedZoomValueSmooth * 0.5f + 4.0f;
vDist = Source - TargetCoors;
fDist = vDist.Magnitude2D();
zOffset = TargetDist - 2.65f;
if(zOffset < 0.0f)
zOffset = 0.0f;
if(zOffset == 0.0f)
Source = TargetCoors + CVector(1.0f, 1.0f, zOffset);
else
Source = TargetCoors + CVector(vDist.x/fDist*TargetDist, vDist.y/fDist*TargetDist, zOffset);
AimingAngle = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y);
while(AimingAngle >= PI) AimingAngle -= 2*PI;
while(AimingAngle < -PI) AimingAngle += 2*PI;
if(TheCamera.PlayerWeaponMode.Mode == MODE_SYPHON)
Beta = AimingAngle + m_fPlayerInFrontSyphonAngleOffSet;
Source.x = TargetCoors.x;
Source.y = TargetCoors.y;
Source.x += Cos(Beta) * TargetDist;
Source.y += Sin(Beta) * TargetDist;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, false, false, true, false, true, true)){
Beta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);
fDist = (TargetCoors - colPoint.point).Magnitude2D();
Source.x = TargetCoors.x;
Source.y = TargetCoors.y;
Source.x += Cos(Beta) * fDist;
Source.y += Sin(Beta) * fDist;
}
TargetCoors = CameraTarget;
TargetCoors.z += m_fSyphonModeTargetZOffSet;
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Front = TargetCoors - Source;
GetVectorsReadyForRW();
}
void
CCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float)
{
if(!CamTargetEntity->IsVehicle()){
ResetStatics = false;
return;
}
CVector TargetCoors = CameraTarget;
float DeltaBeta = 0.0f;
static CColPoint colPoint;
CEntity *entity;
static float TargetWhenChecksWereOn = 0.0f;
static float CenterObscuredWhenChecksWereOn = 0.0f;
static float WaterZAddition = 2.75f;
float WaterLevel = 0.0f;
float s, c;
2020-04-02 10:48:01 +00:00
Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
if(ResetStatics){
CenterObscuredWhenChecksWereOn = 0.0f;
TargetWhenChecksWereOn = 0.0f;
Beta = TargetOrientation + PI;
}
CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterLevel);
WaterLevel += WaterZAddition;
static float FixerForGoingBelowGround = 0.4f;
if(-FixerForGoingBelowGround < TargetCoors.z-WaterLevel)
WaterLevel += TargetCoors.z-WaterLevel - FixerForGoingBelowGround;
bool Obscured;
if(m_bCollisionChecksOn || ResetStatics){
CVector TestPoint;
// Weird calculations here, also casting bool to float...
c = Cos(TargetOrientation);
s = Sin(TargetOrientation);
TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
(TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
TargetCoors;
TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
float Test1 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
c = Cos(TargetOrientation + 0.8f);
s = Sin(TargetOrientation + DEGTORAD(40.0f));
TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
(TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
TargetCoors;
TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
float Test2 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
c = Cos(TargetOrientation - 0.8);
s = Sin(TargetOrientation - DEGTORAD(40.0f));
TestPoint = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
(TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
TargetCoors;
TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
float Test3 = CWorld::GetIsLineOfSightClear(TestPoint, TargetCoors, true, false, false, true, false, true, true);
if(Test2 == 0.0f){
DeltaBeta = TargetOrientation - Beta - DEGTORAD(40.0f);
if(ResetStatics)
Beta = TargetOrientation - DEGTORAD(40.0f);
}else if(Test3 == 0.0f){
DeltaBeta = TargetOrientation - Beta + DEGTORAD(40.0f);
if(ResetStatics)
Beta = TargetOrientation + DEGTORAD(40.0f);
}else if(Test1 == 0.0f){
DeltaBeta = 0.0f;
}else if(Test2 != 0.0f && Test3 != 0.0f && Test1 != 0.0f){
if(ResetStatics)
Beta = TargetOrientation;
DeltaBeta = TargetOrientation - Beta;
}
c = Cos(Beta);
s = Sin(Beta);
TestPoint.x = TheCamera.CarZoomValueSmooth * -c +
(TheCamera.CarZoomValueSmooth + 7.0f) * -c +
TargetCoors.x;
TestPoint.y = TheCamera.CarZoomValueSmooth * -s +
(TheCamera.CarZoomValueSmooth + 7.0f) * -s +
TargetCoors.y;
TestPoint.z = WaterLevel + TheCamera.CarZoomValueSmooth;
Obscured = CWorld::ProcessLineOfSight(TestPoint, TargetCoors, colPoint, entity, true, false, false, true, false, true, true);
CenterObscuredWhenChecksWereOn = Obscured;
// now DeltaBeta == TargetWhenChecksWereOn - Beta, which we need for WellBufferMe below
TargetWhenChecksWereOn = DeltaBeta + Beta;
}else{
// DeltaBeta = TargetWhenChecksWereOn - Beta; // unneeded since we don't inline WellBufferMe
Obscured = CenterObscuredWhenChecksWereOn != 0.0f;
}
if(Obscured){
CWorld::ProcessLineOfSight(Source, TargetCoors, colPoint, entity, true, false, false, true, false, true, true);
Source = colPoint.point;
}else{
// inlined
WellBufferMe(TargetWhenChecksWereOn, &Beta, &BetaSpeed, 0.07f, 0.015f, true);
s = Sin(Beta);
c = Cos(Beta);
Source = TheCamera.CarZoomValueSmooth * CVector(-c, -s, 0.0f) +
(TheCamera.CarZoomValueSmooth+7.0f) * CVector(-c, -s, 0.0f) +
TargetCoors;
Source.z = WaterLevel + TheCamera.CarZoomValueSmooth;
}
if(TheCamera.CarZoomValueSmooth < 0.05f){
static float AmountUp = 2.2f;
TargetCoors.z += AmountUp * (0.0f - TheCamera.CarZoomValueSmooth);
}
TargetCoors.z += TheCamera.CarZoomValueSmooth + 0.5f;
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Front = TargetCoors - Source;
GetVectorsReadyForRW();
ResetStatics = false;
}
void
CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float)
{
if(!CamTargetEntity->IsPed())
return;
FOV = DefaultFOV;
float BetaLeft, BetaRight, DeltaBetaLeft, DeltaBetaRight;
float BetaFix;
float Dist;
float BetaMaxSpeed = 0.015f;
float BetaAcceleration = 0.007f;
static bool PreviouslyFailedBuildingChecks = false;
float TargetCamHeight;
CVector TargetCoors;
m_fMinDistAwayFromCamWhenInterPolating = 4.0f;
Front = Source - CameraTarget;
Beta = CGeneral::GetATanOfXY(Front.x, Front.y);
while(TargetOrientation >= PI) TargetOrientation -= 2*PI;
while(TargetOrientation < -PI) TargetOrientation += 2*PI;
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
// Figure out Beta
BetaLeft = TargetOrientation - HALFPI;
BetaRight = TargetOrientation + HALFPI;
DeltaBetaLeft = Beta - BetaLeft;
DeltaBetaRight = Beta - BetaRight;
while(DeltaBetaLeft >= PI) DeltaBetaLeft -= 2*PI;
while(DeltaBetaLeft < -PI) DeltaBetaLeft += 2*PI;
while(DeltaBetaRight >= PI) DeltaBetaRight -= 2*PI;
while(DeltaBetaRight < -PI) DeltaBetaRight += 2*PI;
if(ResetStatics){
if(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))
m_fTargetBeta = DeltaBetaLeft;
else
m_fTargetBeta = DeltaBetaRight;
m_fBufferedTargetOrientation = TargetOrientation;
m_fBufferedTargetOrientationSpeed = 0.0f;
m_bCollisionChecksOn = true;
BetaSpeed = 0.0f;
}else if(CPad::GetPad(0)->WeaponJustDown()){
if(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))
m_fTargetBeta = DeltaBetaLeft;
else
m_fTargetBeta = DeltaBetaRight;
}
// Check collisions
BetaFix = 0.0f;
Dist = Front.Magnitude2D();
if(m_bCollisionChecksOn || PreviouslyFailedBuildingChecks){
BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.25f, 0.0f, true, false, false, true, false);
if(BetaFix == 0.0f){
BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, DEGTORAD(24.0f), true, false, false, true, false);
if(BetaFix == 0.0f)
BetaFix = GetPedBetaAngleForClearView(CameraTarget, Dist+0.5f, -DEGTORAD(24.0f), true, false, false, true, false);
}
}
if(BetaFix != 0.0f){
BetaMaxSpeed = 0.1f;
PreviouslyFailedBuildingChecks = true;
BetaAcceleration = 0.025f;
m_fTargetBeta = Beta + BetaFix;
}
WellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true);
Source = CameraTarget + 4.0f*CVector(Cos(Beta), Sin(Beta), 0.0f);
Source.z -= 0.5f;
WellBufferMe(TargetOrientation, &m_fBufferedTargetOrientation, &m_fBufferedTargetOrientationSpeed, 0.07f, 0.004f, true);
TargetCoors = CameraTarget + 0.5f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f);
2020-04-19 16:34:08 +00:00
TargetCamHeight = CameraTarget.z - Source.z + Max(m_fPedBetweenCameraHeightOffset, m_fRoadOffSet + m_fDimensionOfHighestNearCar) - 0.5f;
2020-03-26 13:16:06 +00:00
if(TargetCamHeight > m_fCamBufferedHeight)
WellBufferMe(TargetCamHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.15f, 0.04f, false);
else
WellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.08f, 0.0175f, false);
Source.z += m_fCamBufferedHeight;
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Front = TargetCoors - Source;
Front.Normalise();
GetVectorsReadyForRW();
ResetStatics = false;
}
/*
// Spline format is this, but game doesn't seem to use any kind of struct:
struct Spline
{
float numFrames;
struct {
float time;
float f[3]; // CVector for Vector spline
} frames[1]; // numFrames
};
*/
// These two functions are pretty ugly
#define MS(t) (uint32)((t)*1000.0f)
void
FindSplinePathPositionFloat(float *out, float *spline, uint32 time, uint32 &marker)
{
// marker is at time
uint32 numFrames = spline[0];
uint32 timeDelta = MS(spline[marker] - spline[marker-4]);
uint32 endTime = MS(spline[4*(numFrames-1) + 1]);
if(time < endTime){
bool canAdvance = true;
if((marker-1)/4 > numFrames){
canAdvance = false;
marker = 4*(numFrames-1) + 1;
}
// skipping over small time deltas apparently?
while(timeDelta <= 75 && canAdvance){
marker += 4;
if((marker-1)/4 > numFrames){
canAdvance = false;
marker = 4*(numFrames-1) + 1;
}
timeDelta = (spline[marker] - spline[marker-4]) * 1000.0f;
}
}
float a = ((float)time - (float)MS(spline[marker-4])) / (float)MS(spline[marker] - spline[marker-4]);
a = clamp(a, 0.0f, 1.0f);
float b = 1.0f - a;
*out = b*b*b * spline[marker-3] +
3.0f*a*b*b * spline[marker-1] +
3.0f*a*a*b * spline[marker+2] +
a*a*a * spline[marker+1];
}
void
FindSplinePathPositionVector(CVector *out, float *spline, uint32 time, uint32 &marker)
{
// marker is at time
uint32 numFrames = spline[0];
uint32 timeDelta = MS(spline[marker] - spline[marker-10]);
uint32 endTime = MS(spline[10*(numFrames-1) + 1]);
if(time < endTime){
bool canAdvance = true;
if((marker-1)/10 > numFrames){
canAdvance = false;
marker = 10*(numFrames-1) + 1;
}
// skipping over small time deltas apparently?
while(timeDelta <= 75 && canAdvance){
marker += 10;
if((marker-1)/10 > numFrames){
canAdvance = false;
marker = 10*(numFrames-1) + 1;
}
timeDelta = (spline[marker] - spline[marker-10]) * 1000.0f;
}
}
if((marker-1)/10 > numFrames){
printf("Arraymarker %i \n", marker);
printf("Path zero %i \n", numFrames);
}
float a = ((float)time - (float)MS(spline[marker-10])) / (float)MS(spline[marker] - spline[marker-10]);
a = clamp(a, 0.0f, 1.0f);
float b = 1.0f - a;
out->x =
b*b*b * spline[marker-9] +
3.0f*a*b*b * spline[marker-3] +
3.0f*a*a*b * spline[marker+4] +
a*a*a * spline[marker+1];
out->y =
b*b*b * spline[marker-8] +
3.0f*a*b*b * spline[marker-2] +
3.0f*a*a*b * spline[marker+5] +
a*a*a * spline[marker+2];
out->z =
b*b*b * spline[marker-7] +
3.0f*a*b*b * spline[marker-1] +
3.0f*a*a*b * spline[marker+6] +
a*a*a * spline[marker+3];
*out += TheCamera.m_vecCutSceneOffset;
}
void
CCam::Process_FlyBy(const CVector&, float, float, float)
{
float UpAngle = 0.0f;
static float FirstFOVValue = 0.0f;
static float PsuedoFOV;
static uint32 ArrayMarkerFOV;
static uint32 ArrayMarkerUp;
static uint32 ArrayMarkerSource;
static uint32 ArrayMarkerFront;
if(TheCamera.m_bcutsceneFinished)
return;
Up = CVector(0.0f, 0.0f, 1.0f);
if(TheCamera.m_bStartingSpline)
2020-04-11 10:21:21 +00:00
m_fTimeElapsedFloat += CTimer::GetTimeStepNonClippedInMilliseconds();
2020-03-26 13:16:06 +00:00
else{
m_fTimeElapsedFloat = 0.0f;
m_uiFinishTime = MS(TheCamera.m_arrPathArray[2].m_arr_PathData[10*((int)TheCamera.m_arrPathArray[2].m_arr_PathData[0]-1) + 1]);
TheCamera.m_bStartingSpline = true;
FirstFOVValue = TheCamera.m_arrPathArray[0].m_arr_PathData[2];
PsuedoFOV = TheCamera.m_arrPathArray[0].m_arr_PathData[2];
ArrayMarkerFOV = 5;
ArrayMarkerUp = 5;
ArrayMarkerSource = 11;
ArrayMarkerFront = 11;
}
float fTime = m_fTimeElapsedFloat;
uint32 uiFinishTime = m_uiFinishTime;
uint32 uiTime = fTime;
if(uiTime < uiFinishTime){
TheCamera.m_fPositionAlongSpline = (float) uiTime / uiFinishTime;
while(uiTime >= (TheCamera.m_arrPathArray[2].m_arr_PathData[ArrayMarkerSource] - TheCamera.m_arrPathArray[2].m_arr_PathData[1])*1000.0f)
ArrayMarkerSource += 10;
FindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);
while(uiTime >= (TheCamera.m_arrPathArray[3].m_arr_PathData[ArrayMarkerFront] - TheCamera.m_arrPathArray[3].m_arr_PathData[1])*1000.0f)
ArrayMarkerFront += 10;
FindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);
while(uiTime >= (TheCamera.m_arrPathArray[1].m_arr_PathData[ArrayMarkerUp] - TheCamera.m_arrPathArray[1].m_arr_PathData[1])*1000.0f)
ArrayMarkerUp += 4;
FindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);
UpAngle = DEGTORAD(UpAngle) + HALFPI;
Up.x = Cos(UpAngle);
Up.z = Sin(UpAngle);
while(uiTime >= (TheCamera.m_arrPathArray[0].m_arr_PathData[ArrayMarkerFOV] - TheCamera.m_arrPathArray[0].m_arr_PathData[1])*1000.0f)
ArrayMarkerFOV += 4;
FindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);
m_cvecTargetCoorsForFudgeInter = Front;
Front = Front - Source;
Front.Normalise();
CVector Left = CrossProduct(Up, Front);
Up = CrossProduct(Front, Left);
Up.Normalise();
FOV = PsuedoFOV;
}else{
// end
ArrayMarkerSource = (TheCamera.m_arrPathArray[2].m_arr_PathData[0] - 1)*10 + 1;
ArrayMarkerFront = (TheCamera.m_arrPathArray[3].m_arr_PathData[0] - 1)*10 + 1;
ArrayMarkerUp = (TheCamera.m_arrPathArray[1].m_arr_PathData[0] - 1)*4 + 1;
ArrayMarkerFOV = (TheCamera.m_arrPathArray[0].m_arr_PathData[0] - 1)*4 + 1;
FindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);
FindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);
FindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);
UpAngle = DEGTORAD(UpAngle) + HALFPI;
Up.x = Cos(UpAngle);
Up.z = Sin(UpAngle);
FindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);
TheCamera.m_fPositionAlongSpline = 1.0f;
ArrayMarkerFOV = 0;
ArrayMarkerUp = 0;
ArrayMarkerSource = 0;
ArrayMarkerFront = 0;
m_cvecTargetCoorsForFudgeInter = Front;
Front = Front - Source;
Front.Normalise();
CVector Left = CrossProduct(Up, Front);
Up = CrossProduct(Front, Left);
Up.Normalise();
FOV = PsuedoFOV;
}
}
2020-06-09 13:50:00 +00:00
bool
2020-03-26 13:16:06 +00:00
CCam::Process_WheelCam(const CVector&, float, float, float)
{
FOV = DefaultFOV;
if(CamTargetEntity->IsPed()){
// what? ped with wheels or what?
Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-0.3f, -0.5f, 0.1f));
Source += CamTargetEntity->GetPosition();
Front = CVector(1.0f, 0.0f, 0.0f);
}else{
Source = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));
Source += CamTargetEntity->GetPosition();
Front = CamTargetEntity->GetForward();
}
CVector NewUp(0.0f, 0.0f, 1.0f);
CVector Left = CrossProduct(Front, NewUp);
Left.Normalise();
NewUp = CrossProduct(Left, Front);
float Roll = Cos((CTimer::GetTimeInMilliseconds()&0x1FFFF)/(float)0x1FFFF * TWOPI);
Up = Cos(Roll*0.4f)*NewUp + Sin(Roll*0.4f)*Left;
2020-06-09 13:50:00 +00:00
return true;
2020-03-26 13:16:06 +00:00
}
void
CCam::Process_Fixed(const CVector &CameraTarget, float, float, float)
{
Source = m_cvecCamFixedModeSource;
Front = CameraTarget - Source;
m_cvecTargetCoorsForFudgeInter = CameraTarget;
GetVectorsReadyForRW();
Up = CVector(0.0f, 0.0f, 1.0f) + m_cvecCamFixedModeUpOffSet;
Up.Normalise();
CVector Right = CrossProduct(Front, Up);
Right.Normalise();
Up = CrossProduct(Right, Front);
FOV = DefaultFOV;
if(TheCamera.m_bUseSpecialFovTrain)
FOV = TheCamera.m_fFovForTrain;
2020-05-21 23:44:01 +00:00
if(FrontEndMenuManager.m_ControlMethod == 0 && Using3rdPersonMouseCam()){
2020-03-26 13:16:06 +00:00
CPed *player = FindPlayerPed();
if(player && player->CanStrafeOrMouseControl()){
float Heading = Front.Heading();
((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;
((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;
TheCamera.pTargetEntity->SetHeading(Heading);
TheCamera.pTargetEntity->GetMatrix().UpdateRW();
}
}
}
void
CCam::Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float)
{
CColPoint colPoint;
CEntity *entity = nil;
FOV = DefaultFOV;
Source = CameraTarget;
Source.x += -4.5f*Cos(TargetOrientation);
Source.y += -4.5f*Sin(TargetOrientation);
Source.z = m_vecLastAboveWaterCamPosition.z + 4.0f;
m_cvecTargetCoorsForFudgeInter = CameraTarget;
Front = CameraTarget - Source;
Front.Normalise();
if(CWorld::ProcessLineOfSight(CameraTarget, Source, colPoint, entity, true, false, false, true, false, true, true))
Source = colPoint.point;
GetVectorsReadyForRW();
Front = CameraTarget - Source;
Front.Normalise();
}
// unused
void
CCam::Process_Circle(const CVector &CameraTarget, float, float, float)
{
FOV = DefaultFOV;
Front.x = Cos(0.7f) * Cos((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI);
Front.y = Cos(0.7f) * Sin((CTimer::GetTimeInMilliseconds()&0xFFF)/(float)0xFFF * TWOPI);
Front.z = -Sin(0.7f);
Source = CameraTarget - 4.0f*Front;
Source.z += 1.0f;
GetVectorsReadyForRW();
}
void
CCam::Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float)
{
Source = m_cvecCamFixedModeSource;
m_cvecTargetCoorsForFudgeInter = CameraTarget;
m_cvecTargetCoorsForFudgeInter.z += m_fSyphonModeTargetZOffSet;
Front = CameraTarget - Source;
Front.z += m_fSyphonModeTargetZOffSet;
GetVectorsReadyForRW();
Up += m_cvecCamFixedModeUpOffSet;
Up.Normalise();
CVector Left = CrossProduct(Up, Front);
Left.Normalise();
Front = CrossProduct(Left, Up);
Front.Normalise();
FOV = DefaultFOV;
}
#ifdef IMPROVED_CAMERA
#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)
#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k)
#define CTRLJUSTDOWN(key) \
((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \
(KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))
#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))
void
CCam::Process_Debug(const CVector&, float, float, float)
{
static float Speed = 0.0f;
static float PanSpeedX = 0.0f;
static float PanSpeedY = 0.0f;
CVector TargetCoors;
2020-04-02 10:48:01 +00:00
RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
if(CPad::GetPad(0)->GetLeftMouse()){
Alpha += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);
Beta -= DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);
}
TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 3.0f;
TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 3.0f;
TargetCoors.z = Source.z + Sin(Alpha) * 3.0f;
if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
if(CPad::GetPad(1)->GetSquare() || KEYDOWN('W'))
Speed += 0.1f;
else if(CPad::GetPad(1)->GetCross() || KEYDOWN('S'))
Speed -= 0.1f;
else
Speed = 0.0f;
if(Speed > 70.0f) Speed = 70.0f;
if(Speed < -70.0f) Speed = -70.0f;
if(KEYDOWN(rsRIGHT) || KEYDOWN('D'))
PanSpeedX += 0.1f;
else if(KEYDOWN(rsLEFT) || KEYDOWN('A'))
PanSpeedX -= 0.1f;
else
PanSpeedX = 0.0f;
if(PanSpeedX > 70.0f) PanSpeedX = 70.0f;
if(PanSpeedX < -70.0f) PanSpeedX = -70.0f;
if(KEYDOWN(rsUP))
PanSpeedY += 0.1f;
else if(KEYDOWN(rsDOWN))
PanSpeedY -= 0.1f;
else
PanSpeedY = 0.0f;
if(PanSpeedY > 70.0f) PanSpeedY = 70.0f;
if(PanSpeedY < -70.0f) PanSpeedY = -70.0f;
Front = TargetCoors - Source;
Front.Normalise();
Source = Source + Front*Speed;
Up = CVector{ 0.0f, 0.0f, 1.0f };
CVector Right = CrossProduct(Front, Up);
Up = CrossProduct(Right, Front);
Source = Source + Up*PanSpeedY + Right*PanSpeedX;
if(Source.z < -450.0f)
Source.z = -450.0f;
if(CPad::GetPad(1)->GetRightShoulder2JustDown() || KEYJUSTDOWN(rsENTER)){
if(FindPlayerVehicle())
FindPlayerVehicle()->Teleport(Source);
else
2020-05-31 15:05:49 +00:00
CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);
2020-03-26 13:16:06 +00:00
}
// stay inside sectors
while(CWorld::GetSectorX(Source.x) > 95.0f)
Source.x -= 1.0f;
while(CWorld::GetSectorX(Source.x) < 5.0f)
Source.x += 1.0f;
while(CWorld::GetSectorY(Source.y) > 95.0f)
Source.y -= 1.0f;
while(CWorld::GetSectorY(Source.y) < 5.0f)
Source.y += 1.0f;
GetVectorsReadyForRW();
CPad::GetPad(0)->DisablePlayerControls = PLAYERCONTROL_DISABLED_1;
if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
12.0f, 0.0f, 0.0f, -12.0f,
128, 128, 128, 128, 1000.0f, false, 1.0f);
if(CHud::m_Wants_To_Draw_Hud){
char str[256];
sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
}
}
#else
void
CCam::Process_Debug(const CVector&, float, float, float)
{
static float Speed = 0.0f;
CVector TargetCoors;
2020-04-02 10:48:01 +00:00
RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 3.0f;
TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 3.0f;
TargetCoors.z = Source.z + Sin(Alpha) * 3.0f;
if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
if(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())
Speed += 0.1f;
else if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())
Speed -= 0.1f;
else
Speed = 0.0f;
if(Speed > 70.0f) Speed = 70.0f;
if(Speed < -70.0f) Speed = -70.0f;
Front = TargetCoors - Source;
Front.Normalise();
Source = Source + Front*Speed;
if(Source.z < -450.0f)
Source.z = -450.0f;
if(CPad::GetPad(1)->GetRightShoulder2JustDown()){
if(FindPlayerVehicle())
FindPlayerVehicle()->Teleport(Source);
else
2020-05-31 15:05:49 +00:00
CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);
2020-03-26 13:16:06 +00:00
}
// stay inside sectors
while(CWorld::GetSectorX(Source.x) > 95.0f)
Source.x -= 1.0f;
while(CWorld::GetSectorX(Source.x) < 5.0f)
Source.x += 1.0f;
while(CWorld::GetSectorY(Source.y) > 95.0f)
Source.y -= 1.0f;
while(CWorld::GetSectorY(Source.y) < 5.0f)
Source.y += 1.0f;
GetVectorsReadyForRW();
if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
12.0f, 0.0f, 0.0f, -12.0f,
128, 128, 128, 128, 1000.0f, false, 1.0f);
if(CHud::m_Wants_To_Draw_Hud){
char str[256];
sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
}
}
#endif
void
CCam::Process_Editor(const CVector&, float, float, float)
{
static float Speed = 0.0f;
CVector TargetCoors;
if(ResetStatics){
Source = CVector(796.0f, -937.0, 40.0f);
CamTargetEntity = nil;
}
ResetStatics = false;
2020-04-02 10:48:01 +00:00
RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
2020-03-26 13:16:06 +00:00
FOV = DefaultFOV;
Alpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;
Beta += DEGTORAD(CPad::GetPad(1)->GetLeftStickX())*1.5f / 19.0f;
if(CamTargetEntity && CSceneEdit::m_bCameraFollowActor){
TargetCoors = CamTargetEntity->GetPosition();
}else if(CSceneEdit::m_bRecording){
TargetCoors.x = Source.x + Cos(Alpha) * Cos(Beta) * 7.0f;
TargetCoors.y = Source.y + Cos(Alpha) * Sin(Beta) * 7.0f;
TargetCoors.z = Source.z + Sin(Alpha) * 7.0f;
}else
TargetCoors = CSceneEdit::m_vecCamHeading + Source;
CSceneEdit::m_vecCurrentPosition = TargetCoors;
CSceneEdit::m_vecCamHeading = TargetCoors - Source;
if(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);
if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);
if(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())
Speed += 0.1f;
else if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())
Speed -= 0.1f;
else
Speed = 0.0f;
if(Speed > 70.0f) Speed = 70.0f;
if(Speed < -70.0f) Speed = -70.0f;
Front = TargetCoors - Source;
Front.Normalise();
Source = Source + Front*Speed;
if(Source.z < -450.0f)
Source.z = -450.0f;
if(CPad::GetPad(1)->GetRightShoulder2JustDown()){
if(FindPlayerVehicle())
FindPlayerVehicle()->Teleport(Source);
else
2020-05-02 12:28:19 +00:00
CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);
2020-03-26 13:16:06 +00:00
}
// stay inside sectors
while(CWorld::GetSectorX(Source.x) > 95.0f)
Source.x -= 1.0f;
while(CWorld::GetSectorX(Source.x) < 5.0f)
Source.x += 1.0f;
while(CWorld::GetSectorY(Source.y) > 95.0f)
Source.y -= 1.0f;
while(CWorld::GetSectorY(Source.y) < 5.0f)
Source.y += 1.0f;
GetVectorsReadyForRW();
if(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)
CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,
12.0f, 0.0f, 0.0f, -12.0f,
128, 128, 128, 128, 1000.0f, false, 1.0f);
if(CHud::m_Wants_To_Draw_Hud){
char str[256];
sprintf(str, "CamX: %f CamY: %f CamZ: %f", Source.x, Source.y, Source.z);
sprintf(str, "Frontx: %f, Fronty: %f, Frontz: %f ", Front.x, Front.y, Front.z);
sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
}
}
void
CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
{
CVector TargetCoors = CameraTarget;
float Angle = Atan2(Front.x, Front.y);
FOV = DefaultFOV;
Angle += CPad::GetPad(0)->GetLeftStickX()/1280.0f;
if(Distance < 10.0f)
Distance += CPad::GetPad(0)->GetLeftStickY()/1000.0f;
else
Distance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f;
if(Distance < 1.5f)
Distance = 1.5f;
Front.x = Cos(0.3f) * Sin(Angle);
Front.y = Cos(0.3f) * Cos(Angle);
Front.z = -Sin(0.3f);
Source = CameraTarget - Distance*Front;
GetVectorsReadyForRW();
}
void
CCam::ProcessPedsDeadBaby(void)
{
float Distance = 0.0f;
static bool SafeToRotate = false;
CVector TargetDist, TestPoint;
FOV = DefaultFOV;
TargetDist = Source - CamTargetEntity->GetPosition();
Distance = TargetDist.Magnitude();
Beta = CGeneral::GetATanOfXY(TargetDist.x, TargetDist.y);
while(Beta >= PI) Beta -= 2*PI;
while(Beta < -PI) Beta += 2*PI;
if(ResetStatics){
TestPoint = CamTargetEntity->GetPosition() +
CVector(4.0f * Cos(Alpha) * Cos(Beta),
4.0f * Cos(Alpha) * Sin(Beta),
4.0f * Sin(Alpha));
bool Safe1 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
TestPoint = CamTargetEntity->GetPosition() +
CVector(4.0f * Cos(Alpha) * Cos(Beta + DEGTORAD(120.0f)),
4.0f * Cos(Alpha) * Sin(Beta + DEGTORAD(120.0f)),
4.0f * Sin(Alpha));
bool Safe2 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
TestPoint = CamTargetEntity->GetPosition() +
CVector(4.0f * Cos(Alpha) * Cos(Beta - DEGTORAD(120.0f)),
4.0f * Cos(Alpha) * Sin(Beta - DEGTORAD(120.0f)),
4.0f * Sin(Alpha));
bool Safe3 = CWorld::GetIsLineOfSightClear(TestPoint, CamTargetEntity->GetPosition(), true, false, false, true, false, true, true);
SafeToRotate = Safe1 && Safe2 && Safe3;
ResetStatics = false;
}
if(SafeToRotate)
WellBufferMe(Beta + DEGTORAD(175.0f), &Beta, &BetaSpeed, 0.015f, 0.007f, true);
WellBufferMe(DEGTORAD(89.5f), &Alpha, &AlphaSpeed, 0.015f, 0.07f, true);
WellBufferMe(35.0f, &Distance, &DistanceSpeed, 0.006f, 0.007f, false);
Source = CamTargetEntity->GetPosition() +
CVector(Distance * Cos(Alpha) * Cos(Beta),
Distance * Cos(Alpha) * Sin(Beta),
Distance * Sin(Alpha));
m_cvecTargetCoorsForFudgeInter = CamTargetEntity->GetPosition();
Front = CamTargetEntity->GetPosition() - Source;
Front.Normalise();
GetVectorsReadyForRW();
}
bool
CCam::ProcessArrestCamOne(void)
{
FOV = 45.0f;
if(ResetStatics)
return true;
#ifdef FIX_BUGS
if(!CamTargetEntity->IsPed())
return true;
#endif
bool found;
float Ground;
CVector PlayerCoors = TheCamera.pTargetEntity->GetPosition();
CVector CopCoors = ((CPlayerPed*)TheCamera.pTargetEntity)->m_pArrestingCop->GetPosition();
Beta = CGeneral::GetATanOfXY(PlayerCoors.x - CopCoors.x, PlayerCoors.y - CopCoors.y);
Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f);
Source.z += 6.0f;
Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found);
if(!found){
Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found);
if(!found)
return false;
}
Source.z = Ground + 0.25f;
if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true)){
Beta += DEGTORAD(115.0f);
Source = PlayerCoors + 9.5f*CVector(Cos(Beta), Sin(Beta), 0.0f);
Source.z += 6.0f;
Ground = CWorld::FindGroundZFor3DCoord(Source.x, Source.y, Source.z, &found);
if(!found){
Ground = CWorld::FindRoofZFor3DCoord(Source.x, Source.y, Source.z, &found);
if(!found)
return false;
}
Source.z = Ground + 0.25f;
CopCoors.z += 0.35f;
Front = CopCoors - Source;
if(!CWorld::GetIsLineOfSightClear(Source, CopCoors, true, true, false, true, false, true, true))
return false;
}
CopCoors.z += 0.35f;
m_cvecTargetCoorsForFudgeInter = CopCoors;
Front = CopCoors - Source;
ResetStatics = false;
GetVectorsReadyForRW();
return true;
}
bool
CCam::ProcessArrestCamTwo(void)
{
CPed *player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
if(!ResetStatics)
return true;
ResetStatics = false;
CVector TargetCoors, ToCamera;
float BetaOffset;
float SourceX, SourceY;
CCam *ActiveCam = &TheCamera.Cams[TheCamera.ActiveCam];
if(&ActiveCam[1] == this){
SourceX = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.x;
SourceY = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.y;
}else{
SourceX = ActiveCam[1].Source.x;
SourceY = ActiveCam[1].Source.y;
}
for(int i = 0; i <= 1; i++){
int Dir = i == 0 ? 1 : -1;
TargetCoors = player->GetPosition();
Beta = CGeneral::GetATanOfXY(TargetCoors.x-SourceX, TargetCoors.y-SourceY);
BetaOffset = DEGTORAD(Dir*80);
Source = TargetCoors + 11.5f*CVector(Cos(Beta+BetaOffset), Sin(Beta+BetaOffset), 0.0f);
ToCamera = Source - TargetCoors;
ToCamera.Normalise();
TargetCoors.x += 0.4f*ToCamera.x;
TargetCoors.y += 0.4f*ToCamera.y;
if(CWorld::GetIsLineOfSightClear(Source, TargetCoors, true, true, false, true, false, true, true)){
Source.z += 5.5f;
TargetCoors += CVector(-0.8f*ToCamera.x, -0.8f*ToCamera.y, 2.2f);
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Front = TargetCoors - Source;
ResetStatics = false;
GetVectorsReadyForRW();
return true;
}
}
return false;
}
2020-03-27 17:19:08 +00:00
/*
* Unused PS2 cams
*/
void
CCam::Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float TargetOrientation, float, float)
{
static float AngleToBinned = 0.0f;
static float StartingAngleLastChange = 0.0f;
static float FixedTargetOrientation = 0.0f;
static float DeadZoneReachedOnePrevious;
FOV = DefaultFOV; // missing in game
bool FixOrientation = true;
if(ResetStatics){
Rotating = false;
DeadZoneReachedOnePrevious = 0.0f;
FixedTargetOrientation = 0.0f;
ResetStatics = false;
}
CVector TargetCoors = CameraTarget;
float StickX = CPad::GetPad(0)->GetRightStickX();
float StickY = CPad::GetPad(0)->GetRightStickY();
float StickAngle;
if(StickX != 0.0 || StickY != 0.0f) // BUG: game checks StickX twice
StickAngle = CGeneral::GetATanOfXY(StickX, StickY); // result unused?
else
FixOrientation = false;
CVector Dist = Source - TargetCoors;
Source.z = TargetCoors.z + 0.75f;
float Length = Dist.Magnitude2D();
if(Length > 2.5f){
Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
}else if(Length < 2.4f){
Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
}
Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
if(CPad::GetPad(0)->GetLeftShoulder1()){
FixedTargetOrientation = TargetOrientation;
Rotating = true;
}
if(FixOrientation){
Rotating = true;
FixedTargetOrientation = StickX/128.0f + Beta - PI;
}
if(Rotating){
Dist = Source - TargetCoors;
Length = Dist.Magnitude2D();
// inlined
WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
Source.x = TargetCoors.x + Length*Cos(Beta);
Source.y = TargetCoors.y + Length*Sin(Beta);
float DeltaBeta = FixedTargetOrientation+PI - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < 0.06f)
Rotating = false;
}
Front = TargetCoors - Source;
Front.Normalise();
CVector Front2 = Front;
Front2.Normalise(); // What?
// FIX: the meaning of this value must have changed somehow
Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
GetVectorsReadyForRW();
}
void
CCam::Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float)
{
static float AngleToBinned = 0.0f;
static float StartingAngleLastChange = 0.0f;
static float FixedTargetOrientation;
static float DeadZoneReachedOnePrevious;
static uint32 TimeOfLastChange;
uint32 Time;
bool DontBind = false; // BUG: left uninitialized
FOV = DefaultFOV; // missing in game
if(ResetStatics){
Rotating = false;
DeadZoneReachedOnePrevious = 0.0f;
FixedTargetOrientation = 0.0f;
ResetStatics = false;
DontBind = false;
}
CVector TargetCoors = CameraTarget;
CVector Dist = Source - TargetCoors;
Source.z = TargetCoors.z + 0.75f;
float Length = Dist.Magnitude2D();
if(Length > 2.5f){
Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
}else if(Length < 2.4f){
Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
}
Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
float StickX = CPad::GetPad(0)->GetLeftStickX();
float StickY = CPad::GetPad(0)->GetLeftStickY();
float StickAngle;
if(StickX != 0.0 || StickY != 0.0f){
StickAngle = CGeneral::GetATanOfXY(StickX, StickY);
while(StickAngle >= PI) StickAngle -= 2*PI;
while(StickAngle < -PI) StickAngle += 2*PI;
}else
StickAngle = 1000.0f;
if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){
DontBind = true;
Time = CTimer::GetTimeInMilliseconds();
}
if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){
if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){
FixedTargetOrientation = TargetOrientation;
Rotating = true;
TimeOfLastChange = CTimer::GetTimeInMilliseconds();
}
}
// These two together don't make much sense.
// Only prevents rotation for one frame
AngleToBinned = StickAngle;
if(DontBind)
TimeOfLastChange = Time;
if(Rotating){
Dist = Source - TargetCoors;
Length = Dist.Magnitude2D();
// inlined
WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
Source.x = TargetCoors.x + Length*Cos(Beta);
Source.y = TargetCoors.y + Length*Sin(Beta);
float DeltaBeta = FixedTargetOrientation+PI - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < 0.06f)
Rotating = false;
}
Front = TargetCoors - Source;
Front.Normalise();
CVector Front2 = Front;
Front2.Normalise(); // What?
// FIX: the meaning of this value must have changed somehow
Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
GetVectorsReadyForRW();
}
void
CCam::Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float)
{
static float AngleToBinned = 0.0f;
static float StartingAngleLastChange = 0.0f;
static float FixedTargetOrientation;
static float DeadZoneReachedOnePrevious;
static uint32 TimeOfLastChange;
uint32 Time;
bool DontBind = false;
FOV = DefaultFOV; // missing in game
if(ResetStatics){
Rotating = false;
DeadZoneReachedOnePrevious = 0.0f;
FixedTargetOrientation = 0.0f;
ResetStatics = false;
}
CVector TargetCoors = CameraTarget;
CVector Dist = Source - TargetCoors;
Source.z = TargetCoors.z + 0.75f;
float Length = Dist.Magnitude2D();
if(Length > 2.5f){
Source.x = TargetCoors.x + Dist.x/Length * 2.5f;
Source.y = TargetCoors.y + Dist.y/Length * 2.5f;
}else if(Length < 2.4f){
Source.x = TargetCoors.x + Dist.x/Length * 2.4f;
Source.y = TargetCoors.y + Dist.y/Length * 2.4f;
}
Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
float StickX = CPad::GetPad(0)->GetLeftStickX();
float StickY = CPad::GetPad(0)->GetLeftStickY();
float StickAngle;
if(StickX != 0.0 || StickY != 0.0f){
StickAngle = CGeneral::GetATanOfXY(StickX, StickY);
while(StickAngle >= PI) StickAngle -= 2*PI;
while(StickAngle < -PI) StickAngle += 2*PI;
}else
StickAngle = 1000.0f;
if(Abs(StickAngle-AngleToBinned) > DEGTORAD(15.0f)){
DontBind = true;
Time = CTimer::GetTimeInMilliseconds();
}
if(CTimer::GetTimeInMilliseconds()-TimeOfLastChange > 200){
if(Abs(HALFPI-StickAngle) > DEGTORAD(50.0f)){
FixedTargetOrientation = TargetOrientation;
Rotating = true;
TimeOfLastChange = CTimer::GetTimeInMilliseconds();
}
}
if(CPad::GetPad(0)->GetLeftShoulder1JustDown()){
FixedTargetOrientation = TargetOrientation;
Rotating = true;
TimeOfLastChange = CTimer::GetTimeInMilliseconds();
}
// These two together don't make much sense.
// Only prevents rotation for one frame
AngleToBinned = StickAngle;
if(DontBind)
TimeOfLastChange = Time;
if(Rotating){
Dist = Source - TargetCoors;
Length = Dist.Magnitude2D();
// inlined
WellBufferMe(FixedTargetOrientation+PI, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
Source.x = TargetCoors.x + Length*Cos(Beta);
Source.y = TargetCoors.y + Length*Sin(Beta);
float DeltaBeta = FixedTargetOrientation+PI - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < 0.06f)
Rotating = false;
}
Front = TargetCoors - Source;
Front.Normalise();
CVector Front2 = Front;
Front2.Normalise(); // What?
// FIX: the meaning of this value must have changed somehow
Source -= Front2 * TheCamera.m_fPedZoomValueSmooth*1.5f;
// Source += Front2 * TheCamera.m_fPedZoomValueSmooth;
GetVectorsReadyForRW();
}
#ifdef FREE_CAM
void
CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float)
{
FOV = DefaultFOV;
const float MinDist = 2.0f;
const float MaxDist = 2.0f + TheCamera.m_fPedZoomValueSmooth;
const float BaseOffset = 0.75f; // base height of camera above target
CVector TargetCoors = CameraTarget;
TargetCoors.z += m_fSyphonModeTargetZOffSet;
TargetCoors = DoAverageOnVector(TargetCoors);
TargetCoors.z += BaseOffset; // add offset so alpha evens out to 0
// TargetCoors.z += m_fRoadOffSet;
CVector Dist = Source - TargetCoors;
CVector ToCam;
bool Shooting = false;
if(((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
if(CPad::GetPad(0)->GetWeapon())
Shooting = true;
if(((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||
((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)
Shooting = false;
if(ResetStatics){
// Coming out of top down here probably
// so keep Beta, reset alpha and calculate vectors
Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);
Alpha = 0.0f;
Dist = MaxDist*CVector(Cos(Alpha) * Cos(Beta), Cos(Alpha) * Sin(Beta), Sin(Alpha));
Source = TargetCoors + Dist;
ResetStatics = false;
}
// Drag the camera along at the look-down offset
float CamDist = Dist.Magnitude();
if(CamDist == 0.0f)
Dist = CVector(1.0f, 1.0f, 0.0f);
else if(CamDist < MinDist)
Dist *= MinDist/CamDist;
else if(CamDist > MaxDist)
Dist *= MaxDist/CamDist;
CamDist = Dist.Magnitude();
// Beta = 0 is looking east, HALFPI is north, &c.
// Alpha positive is looking up
float GroundDist = Dist.Magnitude2D();
Beta = CGeneral::GetATanOfXY(-Dist.x, -Dist.y);
Alpha = CGeneral::GetATanOfXY(GroundDist, -Dist.z);
while(Beta >= PI) Beta -= 2.0f*PI;
while(Beta < -PI) Beta += 2.0f*PI;
while(Alpha >= PI) Alpha -= 2.0f*PI;
while(Alpha < -PI) Alpha += 2.0f*PI;
// Look around
bool UseMouse = false;
float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown;
2020-04-02 10:48:01 +00:00
/*
if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
UseMouse = true;
LookLeftRight = -2.5f*MouseX;
LookUpDown = 4.0f*MouseY;
2020-04-02 10:48:01 +00:00
}else
*/
{
LookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();
LookUpDown = -CPad::GetPad(0)->LookAroundUpDown();
}
float AlphaOffset, BetaOffset;
if(UseMouse){
BetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;
AlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;
}else{
2020-06-09 13:50:00 +00:00
BetaOffset = LookLeftRight * fStickSens * (1.0f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();
AlphaOffset = LookUpDown * fStickSens * (0.6f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();
}
// Stop centering once stick has been touched
if(BetaOffset)
Rotating = false;
Beta += BetaOffset;
Alpha += AlphaOffset;
while(Beta >= PI) Beta -= 2.0f*PI;
while(Beta < -PI) Beta += 2.0f*PI;
if(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);
if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
float BetaDiff = TargetOrientation+PI - Beta;
while(BetaDiff >= PI) BetaDiff -= 2.0f*PI;
while(BetaDiff < -PI) BetaDiff += 2.0f*PI;
float TargetAlpha = Alpha;
// 12deg to account for our little height offset. we're not working on the true alpha here
const float AlphaLimitUp = DEGTORAD(15.0f) + DEGTORAD(12.0f);
const float AlphaLimitDown = -DEGTORAD(15.0f) + DEGTORAD(12.0f);
if(Abs(BetaDiff) < DEGTORAD(25.0f) && ((CPed*)CamTargetEntity)->GetMoveSpeed().Magnitude2D() > 0.01f){
// Limit alpha when player is walking towards camera
if(TargetAlpha > AlphaLimitUp) TargetAlpha = AlphaLimitUp;
if(TargetAlpha < AlphaLimitDown) TargetAlpha = AlphaLimitDown;
}
WellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.2f, 0.1f, true);
if(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){
m_fTargetBeta = TargetOrientation;
Rotating = true;
}
if(Rotating){
WellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, 0.1f, 0.06f, true);
float DeltaBeta = m_fTargetBeta - Beta;
while(DeltaBeta >= PI) DeltaBeta -= 2*PI;
while(DeltaBeta < -PI) DeltaBeta += 2*PI;
if(Abs(DeltaBeta) < 0.06f)
Rotating = false;
}
2020-05-11 07:18:21 +00:00
if(TheCamera.m_bUseTransitionBeta)
Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
2020-05-11 07:18:41 +00:00
if(TheCamera.m_bUseTransitionBeta)
Beta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));
Front = CVector(Cos(Alpha) * Cos(Beta), Cos(Alpha) * Sin(Beta), Sin(Alpha));
Source = TargetCoors - Front*CamDist;
TargetCoors.z -= BaseOffset; // now get back to the real target coors again
m_cvecTargetCoorsForFudgeInter = TargetCoors;
Front = TargetCoors - Source;
Front.Normalise();
/*
* Handle collisions - taken from FollowPedWithMouse
*/
CEntity *entity;
CColPoint colPoint;
// Clip Source and fix near clip
CWorld::pIgnoreEntity = CamTargetEntity;
entity = nil;
if(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){
float PedColDist = (TargetCoors - colPoint.point).Magnitude();
float ColCamDist = CamDist - PedColDist;
2020-06-09 13:50:00 +00:00
if(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){
// Ped in the way but not clipping through
if(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){
PedColDist = (TargetCoors - colPoint.point).Magnitude();
Source = colPoint.point;
2020-04-02 10:48:01 +00:00
if(PedColDist < DEFAULT_NEAR + 0.3f)
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));
}else{
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR));
}
}else{
Source = colPoint.point;
2020-04-02 10:48:01 +00:00
if(PedColDist < DEFAULT_NEAR + 0.3f)
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));
}
}
CWorld::pIgnoreEntity = nil;
float ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);
2020-05-23 23:59:30 +00:00
float ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV;
float Near = RwCameraGetNearClipPlane(Scene.camera);
float radius = ViewPlaneWidth*Near;
entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
int i = 0;
while(entity){
CVector CamToCol = gaTempSphereColPoints[0].point - Source;
float frontDist = DotProduct(CamToCol, Front);
float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;
// Try to decrease near clip
2020-04-19 16:34:08 +00:00
dist = Max(Min(Near, dist), 0.1f);
if(dist < Near)
RwCameraSetNearClipPlane(Scene.camera, dist);
// Move forward a bit
if(dist == 0.1f)
Source += (TargetCoors - Source)*0.3f;
// Keep testing
2020-06-09 13:50:00 +00:00
Near = RwCameraGetNearClipPlane(Scene.camera);
radius = ViewPlaneWidth*Near;
entity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);
i++;
if(i > 5)
entity = nil;
}
GetVectorsReadyForRW();
}
// LCS cam hehe
void
CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float, float)
{
// Missing things on III CCam
static CVector m_aTargetHistoryPosOne;
static CVector m_aTargetHistoryPosTwo;
static CVector m_aTargetHistoryPosThree;
static int m_nCurrentHistoryPoints = 0;
static float lastBeta = -9999.0f;
static float lastAlpha = -9999.0f;
static float stepsLeftToChangeBetaByMouse;
static float dontCollideWithCars;
static bool alphaCorrected;
static float heightIncreaseMult;
if (!CamTargetEntity->IsVehicle())
return;
CVehicle* car = (CVehicle*)CamTargetEntity;
CVector TargetCoors = CameraTarget;
uint8 camSetArrPos = 0;
// We may need those later
2020-06-05 20:13:31 +00:00
bool isPlane = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE;
bool isHeli = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI;
bool isBike = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE || car->IsBike();
bool isCar = car->IsCar() && !isPlane && !isHeli && !isBike;
CPad* pad = CPad::GetPad(0);
// Next direction is non-existent in III
uint8 nextDirectionIsForward = !(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()) &&
DirectionWasLooking == LOOKING_FORWARD;
2020-05-05 11:48:35 +00:00
if (car->GetModelIndex() == MI_FIRETRUCK) {
camSetArrPos = 7;
2020-06-05 20:13:31 +00:00
} else if (car->GetModelIndex() == MI_RCBANDIT || car->GetModelIndex() == MI_RCBARON) {
camSetArrPos = 5;
2020-06-05 20:13:31 +00:00
} else if (car->GetModelIndex() == MI_RCGOBLIN || car->GetModelIndex() == MI_RCRAIDER) {
camSetArrPos = 6;
} else if (car->IsBoat()) {
camSetArrPos = 4;
} else if (isBike) {
camSetArrPos = 1;
} else if (isPlane) {
camSetArrPos = 3;
} else if (isHeli) {
camSetArrPos = 2;
}
// LCS one but index 1(firetruck) moved to last
float CARCAM_SET[][15] = {
{1.3f, 1.0f, 0.4f, 10.0f, 15.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.8f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // cars
{1.1f, 1.0f, 0.1f, 10.0f, 11.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.75f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // bike
{1.1f, 1.0f, 0.2f, 10.0f, 15.0f, 0.05f, 0.05f, 0.0f, 0.9f, 0.05f, 0.01f, 0.05f, 1.0f, DEGTORAD(10.0f), DEGTORAD(70.0f)}, // heli (SA values)
{1.1f, 3.5f, 0.2f, 10.0f, 25.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(89.0f), DEGTORAD(89.0f)}, // plane (SA values)
{0.9f, 1.0f, 0.1f, 10.0f, 15.0f, 0.5f, 1.0f, 0.0f, 0.9f, 0.05f, 0.005f, 0.05f, 1.0f, -0.2f, DEGTORAD(70.0f)}, // boat
{1.1f, 1.0f, 0.2f, 10.0f, 5.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // rc cars
{1.1f, 1.0f, 0.2f, 10.0f, 5.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(20.0f), DEGTORAD(70.0f)}, // rc heli/planes
{1.3f, 1.0f, 0.4f, 10.0f, 15.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.8f, -0.18f, DEGTORAD(40.0f)}, // firetruck...
};
// RC Heli/planes use same alpha values with heli/planes (LCS firetruck will fallback to 0)
uint8 alphaArrPos = (camSetArrPos > 4 ? (isPlane ? 3 : (isHeli ? 2 : 0)) : camSetArrPos);
float zoomModeAlphaOffset = 0.0f;
static float ZmOneAlphaOffsetLCS[] = { 0.12f, 0.08f, 0.15f, 0.08f, 0.08f };
static float ZmTwoAlphaOffsetLCS[] = { 0.1f, 0.08f, 0.3f, 0.08f, 0.08f };
static float ZmThreeAlphaOffsetLCS[] = { 0.065f, 0.05f, 0.15f, 0.06f, 0.08f };
if (isHeli && car->GetStatus() == STATUS_PLAYER_REMOTE)
zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];
else {
switch ((int)TheCamera.CarZoomIndicator) {
// near
2020-04-08 06:58:08 +00:00
case CAM_ZOOM_1:
zoomModeAlphaOffset = ZmOneAlphaOffsetLCS[alphaArrPos];
break;
// mid
2020-04-08 06:58:08 +00:00
case CAM_ZOOM_2:
zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];
break;
// far
2020-04-08 06:58:08 +00:00
case CAM_ZOOM_3:
zoomModeAlphaOffset = ZmThreeAlphaOffsetLCS[alphaArrPos];
break;
default:
break;
}
}
CColModel* carCol = (CColModel*)car->GetColModel();
float colMaxZ = carCol->boundingBox.max.z; // As opposed to LCS and SA, VC does this: carCol->boundingBox.max.z - carCol->boundingBox.min.z;
float approxCarLength = 2.0f * Abs(carCol->boundingBox.min.y); // SA taxi min.y = -2.95, max.z = 0.883502f
float newDistance = TheCamera.CarZoomValueSmooth + CARCAM_SET[camSetArrPos][1] + approxCarLength;
2020-06-05 20:13:31 +00:00
// Taken from VC CCam::Cam_On_A_String_Unobscured. If we don't this, we will end up seeing the world from the inside of RC Goblin/Raider.
// I couldn't find where SA does that. It's possible that they've increased the size of these veh.'s collision bounding box.
if (car->m_modelIndex == MI_RCRAIDER || car->m_modelIndex == MI_RCBANDIT) {
newDistance += 6.0f;
} else if (car->m_modelIndex == MI_RCBARON) {
newDistance += 9.5f;
}
float minDistForThisCar = approxCarLength * CARCAM_SET[camSetArrPos][3];
if (!isHeli || car->GetStatus() == STATUS_PLAYER_REMOTE) {
float radiusToStayOutside = colMaxZ * CARCAM_SET[camSetArrPos][0] - CARCAM_SET[camSetArrPos][2];
if (radiusToStayOutside > 0.0f) {
TargetCoors.z += radiusToStayOutside;
newDistance += radiusToStayOutside;
zoomModeAlphaOffset += 0.3f / newDistance * radiusToStayOutside;
}
} else {
// 0.6f = fTestShiftHeliCamTarget
2020-04-08 06:58:08 +00:00
TargetCoors += 0.6f * car->GetUp() * colMaxZ;
}
2020-06-05 20:13:31 +00:00
if (car->m_modelIndex == MI_RCGOBLIN)
zoomModeAlphaOffset += 0.178997f;
float minDistForVehType = CARCAM_SET[camSetArrPos][4];
2020-04-08 06:58:08 +00:00
if (TheCamera.CarZoomIndicator == CAM_ZOOM_1 && (camSetArrPos < 2 || camSetArrPos == 7)) {
minDistForVehType = minDistForVehType * 0.65f;
}
2020-04-19 16:34:08 +00:00
float nextDistance = Max(newDistance, minDistForVehType);
CA_MAX_DISTANCE = newDistance;
CA_MIN_DISTANCE = 3.5f;
if (ResetStatics) {
FOV = DefaultFOV;
2020-06-05 20:13:31 +00:00
// TODO(Miami): Remove that when cam is done!
// GTA 3 has this in veh. camera
if (TheCamera.m_bIdleOn)
TheCamera.m_uiTimeWeEnteredIdle = CTimer::GetTimeInMilliseconds();
} else {
if (isCar || isBike) {
// 0.4f: CAR_FOV_START_SPEED
if (DotProduct(car->GetForward(), car->m_vecMoveSpeed) > 0.4f)
FOV += (DotProduct(car->GetForward(), car->m_vecMoveSpeed) - 0.4f) * CTimer::GetTimeStep();
}
if (FOV > DefaultFOV)
// 0.98f: CAR_FOV_FADE_MULT
FOV = pow(0.98f, CTimer::GetTimeStep()) * (FOV - DefaultFOV) + DefaultFOV;
if (FOV <= DefaultFOV + 30.0f) {
if (FOV < DefaultFOV)
FOV = DefaultFOV;
} else
FOV = DefaultFOV + 30.0f;
}
// WORKAROUND: I still don't know how looking behind works (m_bCamDirectlyInFront is unused in III, they seem to use m_bUseTransitionBeta)
if (pad->GetLookBehindForCar())
if (DirectionWasLooking == LOOKING_FORWARD || !LookingBehind)
TheCamera.m_bCamDirectlyInFront = true;
// Taken from RotCamIfInFrontCar, because we don't call it anymore
if (!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))
if (DirectionWasLooking != LOOKING_FORWARD)
TheCamera.m_bCamDirectlyBehind = true;
// Called when we just entered the car, just started to look behind or returned back from looking left, right or behind
if (ResetStatics || TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront) {
ResetStatics = false;
Rotating = false;
m_bCollisionChecksOn = true;
2020-06-05 20:13:31 +00:00
// TODO(Miami): Uncomment that when cam is done!
// Garage exit cam is not working well in III...
2020-06-05 20:13:31 +00:00
// if (!TheCamera.m_bJustCameOutOfGarage)
// {
Alpha = 0.0f;
Beta = car->GetForward().Heading() - HALFPI;
if (TheCamera.m_bCamDirectlyInFront) {
Beta += PI;
}
// }
BetaSpeed = 0.0;
AlphaSpeed = 0.0;
Distance = 1000.0;
Front.x = -(cos(Beta) * cos(Alpha));
Front.y = -(sin(Beta) * cos(Alpha));
Front.z = sin(Alpha);
m_aTargetHistoryPosOne = TargetCoors - nextDistance * Front;
m_aTargetHistoryPosTwo = TargetCoors - newDistance * Front;
m_nCurrentHistoryPoints = 0;
2020-06-05 20:13:31 +00:00
if (!TheCamera.m_bJustCameOutOfGarage)
Alpha = -zoomModeAlphaOffset;
}
Front = TargetCoors - m_aTargetHistoryPosOne;
Front.Normalise();
// Code that makes cam rotate around the car
float camRightHeading = Front.Heading() - HALFPI;
if (camRightHeading < -PI)
camRightHeading = camRightHeading + TWOPI;
float velocityRightHeading;
if (car->m_vecMoveSpeed.Magnitude2D() <= 0.02f)
velocityRightHeading = camRightHeading;
else
velocityRightHeading = car->m_vecMoveSpeed.Heading() - HALFPI;
if (velocityRightHeading < camRightHeading - PI)
velocityRightHeading = velocityRightHeading + TWOPI;
else if (velocityRightHeading > camRightHeading + PI)
velocityRightHeading = velocityRightHeading - TWOPI;
float betaChangeMult1 = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][10];
float betaChangeLimit = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][11];
float betaChangeMult2 = (car->m_vecMoveSpeed - DotProduct(car->m_vecMoveSpeed, Front) * Front).Magnitude();
2020-04-19 16:34:08 +00:00
float betaChange = Min(1.0f, betaChangeMult1 * betaChangeMult2) * (velocityRightHeading - camRightHeading);
if (betaChange <= betaChangeLimit) {
if (betaChange < -betaChangeLimit)
betaChange = -betaChangeLimit;
} else {
betaChange = betaChangeLimit;
}
float targetBeta = camRightHeading + betaChange;
if (targetBeta < Beta - HALFPI)
targetBeta += TWOPI;
else if (targetBeta > Beta + PI)
targetBeta -= TWOPI;
float carPosChange = (TargetCoors - m_aTargetHistoryPosTwo).Magnitude();
if (carPosChange < newDistance && newDistance > minDistForThisCar) {
2020-04-19 16:34:08 +00:00
newDistance = Max(minDistForThisCar, carPosChange);
}
float maxAlphaAllowed = CARCAM_SET[camSetArrPos][13];
// Originally this is to prevent camera enter into car while we're stopping, but what about moving???
// This is also original LCS and SA bug, or some attempt to fix lag. We'll never know
// if (car->m_vecMoveSpeed.MagnitudeSqr() < sq(0.2f))
2020-06-05 20:13:31 +00:00
if (car->GetModelIndex() != MI_FIRETRUCK)
if (!isBike || ((CBike*)car)->m_nWheelsOnGround > 3)
if (!isHeli && (!isPlane || ((CAutomobile*)car)->m_nWheelsOnGround)) {
CVector left = CrossProduct(car->GetForward(), CVector(0.0f, 0.0f, 1.0f));
left.Normalise();
CVector up = CrossProduct(left, car->GetForward());
up.Normalise();
float lookingUp = DotProduct(up, Front);
if (lookingUp > 0.0f) {
float v88 = Asin(Abs(Sin(Beta - (car->GetForward().Heading() - HALFPI))));
float v200;
if (v88 <= Atan2(carCol->boundingBox.max.x, -carCol->boundingBox.min.y)) {
v200 = (1.5f - carCol->boundingBox.min.y) / Cos(v88);
} else {
float a6g = 1.2f + carCol->boundingBox.max.x;
2020-04-19 16:34:08 +00:00
v200 = a6g / Cos(Max(0.0f, HALFPI - v88));
}
maxAlphaAllowed = Cos(Beta - (car->GetForward().Heading() - HALFPI)) * Atan2(car->GetForward().z, car->GetForward().Magnitude2D())
+ Atan2(TargetCoors.z - car->GetPosition().z + car->GetHeightAboveRoad(), v200 * 1.2f);
if (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1 && Abs(DotProduct(car->m_vecTurnSpeed, car->GetForward())) < 0.05f) {
maxAlphaAllowed += Cos(Beta - (car->GetForward().Heading() - HALFPI) + HALFPI) * Atan2(car->GetRight().z, car->GetRight().Magnitude2D());
}
}
}
float targetAlpha = Asin(clamp(Front.z, -1.0f, 1.0f)) - zoomModeAlphaOffset;
if (targetAlpha <= maxAlphaAllowed) {
if (targetAlpha < -CARCAM_SET[camSetArrPos][14])
targetAlpha = -CARCAM_SET[camSetArrPos][14];
} else {
targetAlpha = maxAlphaAllowed;
}
float maxAlphaBlendAmount = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][6];
float targetAlphaBlendAmount = (1.0f - pow(CARCAM_SET[camSetArrPos][5], CTimer::GetTimeStep())) * (targetAlpha - Alpha);
if (targetAlphaBlendAmount <= maxAlphaBlendAmount) {
if (targetAlphaBlendAmount < -maxAlphaBlendAmount)
targetAlphaBlendAmount = -maxAlphaBlendAmount;
} else {
targetAlphaBlendAmount = maxAlphaBlendAmount;
}
// Using GetCarGun(LR/UD) will give us same unprocessed RightStick value as SA
float stickX = -(pad->GetCarGunLeftRight());
float stickY = pad->GetCarGunUpDown();
// In SA this checks for m_bUseMouse3rdPerson so num2/num8 do not move camera when Keyboard & Mouse controls are used.
if (CCamera::m_bUseMouse3rdPerson)
stickY = 0.0f;
float xMovement = Abs(stickX) * (FOV / 80.0f * 5.f / 70.f) * stickX * 0.007f * 0.007f;
float yMovement = Abs(stickY) * (FOV / 80.0f * 3.f / 70.f) * stickY * 0.007f * 0.007f;
bool correctAlpha = true;
// if (SA checks if we aren't in work car, why?) {
2020-05-07 09:33:20 +00:00
if (!isCar || car->GetModelIndex() != MI_VOODOO) {
correctAlpha = false;
}
else {
xMovement = 0.0f;
yMovement = 0.0f;
}
// } else
// yMovement = 0.0;
if (!nextDirectionIsForward) {
2020-04-08 06:58:08 +00:00
yMovement = 0.0f;
xMovement = 0.0f;
}
if (camSetArrPos == 0 || camSetArrPos == 7) {
// This is not working on cars as SA
// Because III/VC doesn't have any buttons tied to LeftStick if you're not in Classic Configuration, using Dodo or using GInput/Pad, so :shrug:
if (Abs(pad->GetSteeringUpDown()) > 120.0f) {
if (car->pDriver && car->pDriver->m_objective != OBJECTIVE_LEAVE_VEHICLE) {
yMovement += Abs(pad->GetSteeringUpDown()) * (FOV / 80.0f * 3.f / 70.f) * pad->GetSteeringUpDown() * 0.007f * 0.007f * 0.5;
}
}
}
if (yMovement > 0.0)
yMovement = yMovement * 0.5;
bool mouseChangesBeta = false;
// FIX: Disable mouse movement in drive-by, it's buggy. Original SA bug.
2020-04-02 10:48:01 +00:00
if (/*bFreeMouseCam &&*/ CCamera::m_bUseMouse3rdPerson && !pad->ArePlayerControlsDisabled() && nextDirectionIsForward) {
float mouseY = pad->GetMouseY() * 2.0f;
float mouseX = pad->GetMouseX() * -2.0f;
// If you want an ability to toggle free cam while steering with mouse, you can add an OR after DisableMouseSteering.
// There was a pad->NewState.m_bVehicleMouseLook in SA, which doesn't exists in III.
if ((mouseX != 0.0 || mouseY != 0.0) && (CVehicle::m_bDisableMouseSteering)) {
yMovement = mouseY * FOV / 80.0f * TheCamera.m_fMouseAccelHorzntl; // Same as SA, horizontal sensitivity.
BetaSpeed = 0.0;
AlphaSpeed = 0.0;
xMovement = mouseX * FOV / 80.0f * TheCamera.m_fMouseAccelHorzntl;
targetAlpha = Alpha;
stepsLeftToChangeBetaByMouse = 1.0f * 50.0f;
mouseChangesBeta = true;
} else if (stepsLeftToChangeBetaByMouse > 0.0f) {
// Finish rotation by decreasing speed when we stopped moving mouse
BetaSpeed = 0.0;
AlphaSpeed = 0.0;
yMovement = 0.0;
xMovement = 0.0;
targetAlpha = Alpha;
2020-04-19 16:34:08 +00:00
stepsLeftToChangeBetaByMouse = Max(0.0f, stepsLeftToChangeBetaByMouse - CTimer::GetTimeStep());
mouseChangesBeta = true;
}
}
if (correctAlpha) {
if (nPreviousMode != MODE_CAM_ON_A_STRING)
alphaCorrected = false;
if (!alphaCorrected && Abs(zoomModeAlphaOffset + Alpha) > 0.05f) {
yMovement = (-zoomModeAlphaOffset - Alpha) * 0.05f;
} else
alphaCorrected = true;
}
float alphaSpeedFromStickY = yMovement * CARCAM_SET[camSetArrPos][12];
float betaSpeedFromStickX = xMovement * CARCAM_SET[camSetArrPos][12];
float newAngleSpeedMaxBlendAmount = CARCAM_SET[camSetArrPos][9];
float angleChangeStep = pow(CARCAM_SET[camSetArrPos][8], CTimer::GetTimeStep());
2020-04-19 16:34:08 +00:00
float targetBetaWithStickBlendAmount = betaSpeedFromStickX + (targetBeta - Beta) / Max(CTimer::GetTimeStep(), 1.0f);
if (targetBetaWithStickBlendAmount < -newAngleSpeedMaxBlendAmount)
targetBetaWithStickBlendAmount = -newAngleSpeedMaxBlendAmount;
else if (targetBetaWithStickBlendAmount > newAngleSpeedMaxBlendAmount)
targetBetaWithStickBlendAmount = newAngleSpeedMaxBlendAmount;
float angleChangeStepLeft = 1.0f - angleChangeStep;
BetaSpeed = targetBetaWithStickBlendAmount * angleChangeStepLeft + angleChangeStep * BetaSpeed;
if (Abs(BetaSpeed) < 0.0001f)
BetaSpeed = 0.0f;
float betaChangePerFrame;
if (mouseChangesBeta)
betaChangePerFrame = betaSpeedFromStickX;
else
betaChangePerFrame = CTimer::GetTimeStep() * BetaSpeed;
Beta = betaChangePerFrame + Beta;
if (TheCamera.m_bJustCameOutOfGarage) {
float invHeading = Atan2(Front.y, Front.x);
if (invHeading < 0.0f)
invHeading += TWOPI;
Beta = invHeading + PI;
}
Beta = CGeneral::LimitRadianAngle(Beta);
if (Beta < 0.0f)
Beta += TWOPI;
if ((camSetArrPos <= 1 || camSetArrPos == 7) && targetAlpha < Alpha && carPosChange >= newDistance) {
2020-06-05 20:13:31 +00:00
if (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1 ||
isBike && ((CBike*)car)->m_nWheelsOnGround > 1)
alphaSpeedFromStickY += (targetAlpha - Alpha) * 0.075f;
}
AlphaSpeed = angleChangeStepLeft * alphaSpeedFromStickY + angleChangeStep * AlphaSpeed;
float maxAlphaSpeed = newAngleSpeedMaxBlendAmount;
if (alphaSpeedFromStickY > 0.0f)
maxAlphaSpeed = maxAlphaSpeed * 0.5;
if (AlphaSpeed <= maxAlphaSpeed) {
float minAlphaSpeed = -maxAlphaSpeed;
if (AlphaSpeed < minAlphaSpeed)
AlphaSpeed = minAlphaSpeed;
} else {
AlphaSpeed = maxAlphaSpeed;
}
if (Abs(AlphaSpeed) < 0.0001f)
AlphaSpeed = 0.0f;
float alphaWithSpeedAccounted;
if (mouseChangesBeta) {
alphaWithSpeedAccounted = alphaSpeedFromStickY + targetAlpha;
Alpha += alphaSpeedFromStickY;
} else {
alphaWithSpeedAccounted = CTimer::GetTimeStep() * AlphaSpeed + targetAlpha;
Alpha += targetAlphaBlendAmount;
}
if (Alpha <= maxAlphaAllowed) {
float minAlphaAllowed = -CARCAM_SET[camSetArrPos][14];
if (minAlphaAllowed > Alpha) {
Alpha = minAlphaAllowed;
AlphaSpeed = 0.0f;
}
} else {
Alpha = maxAlphaAllowed;
AlphaSpeed = 0.0f;
}
// Prevent unsignificant angle changes
if (Abs(lastAlpha - Alpha) < 0.0001f)
Alpha = lastAlpha;
lastAlpha = Alpha;
if (Abs(lastBeta - Beta) < 0.0001f)
Beta = lastBeta;
lastBeta = Beta;
Front.x = -(cos(Beta) * cos(Alpha));
Front.y = -(sin(Beta) * cos(Alpha));
Front.z = sin(Alpha);
GetVectorsReadyForRW();
TheCamera.m_bCamDirectlyBehind = false;
TheCamera.m_bCamDirectlyInFront = false;
Source = TargetCoors - newDistance * Front;
m_cvecTargetCoorsForFudgeInter = TargetCoors;
m_aTargetHistoryPosThree = m_aTargetHistoryPosOne;
float nextAlpha = alphaWithSpeedAccounted + zoomModeAlphaOffset;
float nextFrontX = -(cos(Beta) * cos(nextAlpha));
float nextFrontY = -(sin(Beta) * cos(nextAlpha));
float nextFrontZ = sin(nextAlpha);
m_aTargetHistoryPosOne.x = TargetCoors.x - nextFrontX * nextDistance;
m_aTargetHistoryPosOne.y = TargetCoors.y - nextFrontY * nextDistance;
m_aTargetHistoryPosOne.z = TargetCoors.z - nextFrontZ * nextDistance;
m_aTargetHistoryPosTwo.x = TargetCoors.x - nextFrontX * newDistance;
m_aTargetHistoryPosTwo.y = TargetCoors.y - nextFrontY * newDistance;
m_aTargetHistoryPosTwo.z = TargetCoors.z - nextFrontZ * newDistance;
// SA calls SetColVarsVehicle in here
if (nextDirectionIsForward) {
// This is new in LCS!
float timestepFactor = Pow(0.99f, CTimer::GetTimeStep());
dontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude());
// Move cam if on collision
CColPoint foundCol;
CEntity* foundEnt;
CWorld::pIgnoreEntity = CamTargetEntity;
if (CWorld::ProcessLineOfSight(TargetCoors, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, false, false, true, false)) {
float obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude();
float obstacleCamDist = newDistance - obstacleTargetDist;
if (!foundEnt->IsPed() || obstacleCamDist <= 1.0f) {
Source = foundCol.point;
if (obstacleTargetDist < 1.2f) {
2020-04-19 16:34:08 +00:00
RwCameraSetNearClipPlane(Scene.camera, Max(0.05f, obstacleTargetDist - 0.3f));
}
} else {
if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, false, false, true, false)) {
float lessClip = obstacleCamDist - 0.35f;
2020-04-02 10:48:01 +00:00
if (lessClip <= DEFAULT_NEAR)
RwCameraSetNearClipPlane(Scene.camera, lessClip);
else
2020-04-02 10:48:01 +00:00
RwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);
} else {
obstacleTargetDist = (TargetCoors - foundCol.point).Magnitude();
Source = foundCol.point;
if (obstacleTargetDist < 1.2f) {
float lessClip = obstacleTargetDist - 0.3f;
if (lessClip >= 0.05f)
RwCameraSetNearClipPlane(Scene.camera, lessClip);
else
RwCameraSetNearClipPlane(Scene.camera, 0.05f);
}
}
}
}
CWorld::pIgnoreEntity = nil;
float nearClip = RwCameraGetNearClipPlane(Scene.camera);
float radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f;
// If we're seeing blue hell due to camera intersects some surface, fix it.
// SA and LCS have this unrolled.
for (int i = 0;
i <= 5 && CWorld::TestSphereAgainstWorld((nearClip * Front) + Source, radius * nearClip, nil, true, true, false, true, false, false);
i++) {
CVector surfaceCamDist = gaTempSphereColPoints->point - Source;
CVector frontButInvertedIfTouchesSurface = DotProduct(surfaceCamDist, Front) * Front;
float newNearClip = (surfaceCamDist - frontButInvertedIfTouchesSurface).Magnitude() / radius;
if (newNearClip > nearClip)
newNearClip = nearClip;
if (newNearClip < 0.1f)
newNearClip = 0.1f;
if (nearClip > newNearClip)
RwCameraSetNearClipPlane(Scene.camera, newNearClip);
if (newNearClip == 0.1f)
Source += (TargetCoors - Source) * 0.3f;
nearClip = RwCameraGetNearClipPlane(Scene.camera);
radius = Tan(DEGTORAD(FOV * 0.5f)) * CDraw::GetAspectRatio() * 1.1f;
}
}
TheCamera.m_bCamDirectlyBehind = false;
TheCamera.m_bCamDirectlyInFront = false;
// ------- LCS specific part starts
if (camSetArrPos == 5 && Source.z < 1.0f) // RC Bandit and Baron
Source.z = 1.0f;
// CCam::FixSourceAboveWaterLevel
if (CameraTarget.z >= -2.0f) {
float level = -6000.0;
2020-06-05 20:13:31 +00:00
if (CWaterLevel::GetWaterLevelNoWaves(Source.x, Source.y, Source.z, &level)) {
2020-06-05 20:13:31 +00:00
if (Source.z < level)
Source.z = level;
}
}
Front = TargetCoors - Source;
// -------- LCS specific part ends
GetVectorsReadyForRW();
// SA
// gTargetCoordsForLookingBehind = TargetCoors;
// SA code from CAutomobile::TankControl/FireTruckControl.
2020-05-05 11:48:35 +00:00
if (car->GetModelIndex() == MI_RHINO || car->GetModelIndex() == MI_FIRETRUCK) {
float &carGunLR = ((CAutomobile*)car)->m_fCarGunLR;
CVector hi = Multiply3x3(Front, car->GetMatrix());
// III/VC's firetruck turret angle is reversed
2020-05-05 11:48:35 +00:00
float angleToFace = (car->GetModelIndex() == MI_FIRETRUCK ? -hi.Heading() : hi.Heading());
if (angleToFace <= carGunLR + PI) {
if (angleToFace < carGunLR - PI)
angleToFace = angleToFace + TWOPI;
} else {
angleToFace = angleToFace - TWOPI;
}
float neededTurn = angleToFace - carGunLR;
2020-05-05 11:48:35 +00:00
float turnPerFrame = CTimer::GetTimeStep() * (car->GetModelIndex() == MI_FIRETRUCK ? 0.05f : 0.015f);
if (neededTurn <= turnPerFrame) {
if (neededTurn < -turnPerFrame)
angleToFace = carGunLR - turnPerFrame;
} else {
angleToFace = turnPerFrame + carGunLR;
}
2020-05-05 11:48:35 +00:00
if (car->GetModelIndex() == MI_RHINO && carGunLR != angleToFace) {
DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_TANK_TURRET_ROTATE, Abs(angleToFace - carGunLR));
}
carGunLR = angleToFace;
if (carGunLR < -PI) {
carGunLR += TWOPI;
} else if (carGunLR > PI) {
carGunLR -= TWOPI;
}
// Because firetruk turret also has Y movement
2020-05-05 11:48:35 +00:00
if (car->GetModelIndex() == MI_FIRETRUCK) {
float &carGunUD = ((CAutomobile*)car)->m_fCarGunUD;
float alphaToFace = Atan2(hi.z, hi.Magnitude2D()) + DEGTORAD(15.0f);
float neededAlphaTurn = alphaToFace - carGunUD;
float alphaTurnPerFrame = CTimer::GetTimeStep() * 0.02f;
if (neededAlphaTurn > alphaTurnPerFrame) {
neededTurn = alphaTurnPerFrame;
carGunUD = neededTurn + carGunUD;
} else {
if (neededAlphaTurn >= -alphaTurnPerFrame) {
carGunUD = alphaToFace;
} else {
carGunUD = carGunUD - alphaTurnPerFrame;
}
}
float turretMinY = -DEGTORAD(20.0f);
float turretMaxY = DEGTORAD(20.0f);
if (turretMinY <= carGunUD) {
if (carGunUD > turretMaxY)
carGunUD = turretMaxY;
} else {
carGunUD = turretMinY;
}
}
}
}
#endif