Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Nikolay Korolev 2020-03-31 23:54:39 +03:00
commit e2ed468018
24 changed files with 1705 additions and 536 deletions

BIN
gamefiles/JAPANESE.gxt Normal file

Binary file not shown.

BIN
gamefiles/fonts_j.txd Normal file

Binary file not shown.

BIN
gamefiles/fonts_r.txd Normal file

Binary file not shown.

BIN
gamefiles/russian.gxt Normal file

Binary file not shown.

View File

@ -23,12 +23,18 @@
#include "SceneEdit.h" #include "SceneEdit.h"
#include "Debug.h" #include "Debug.h"
#include "Camera.h" #include "Camera.h"
#include "DMAudio.h"
const float DefaultFOV = 70.0f; // beta: 80.0f const float DefaultFOV = 70.0f; // beta: 80.0f
bool PrintDebugCode = false; bool PrintDebugCode = false;
int16 &DebugCamMode = *(int16*)0x95CCF2; int16 &DebugCamMode = *(int16*)0x95CCF2;
bool bFreeCam = false;
#ifdef FREE_CAM
bool bFreePadCam = false;
bool bFreeMouseCam = false;
int nPreviousMode = -1;
#endif
void void
CCam::Init(void) CCam::Init(void)
@ -140,7 +146,7 @@ CCam::Process(void)
Process_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else else
#ifdef FREE_CAM #ifdef FREE_CAM
if(bFreeCam) if(bFreePadCam)
Process_FollowPed_Rotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_FollowPed_Rotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else else
#endif #endif
@ -180,6 +186,11 @@ CCam::Process(void)
Process_FlyBy(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_FlyBy(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break; break;
case MODE_CAM_ON_A_STRING: case MODE_CAM_ON_A_STRING:
#ifdef FREE_CAM
if(bFreeMouseCam || bFreePadCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
Process_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break; break;
case MODE_REACTION: case MODE_REACTION:
@ -192,6 +203,11 @@ CCam::Process(void)
Process_Chris_With_Binding_PlusRotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_Chris_With_Binding_PlusRotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break; break;
case MODE_BEHINDBOAT: case MODE_BEHINDBOAT:
#ifdef FREE_CAM
if (bFreeMouseCam || bFreePadCam)
Process_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
else
#endif
Process_BehindBoat(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar); Process_BehindBoat(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break; break;
case MODE_PLAYER_FALLEN_WATER: case MODE_PLAYER_FALLEN_WATER:
@ -244,6 +260,9 @@ CCam::Process(void)
Up = CVector(0.0f, 0.0f, 1.0f); Up = CVector(0.0f, 0.0f, 1.0f);
} }
#ifdef FREE_CAM
nPreviousMode = Mode;
#endif
CVector TargetToCam = Source - m_cvecTargetCoorsForFudgeInter; CVector TargetToCam = Source - m_cvecTargetCoorsForFudgeInter;
float DistOnGround = TargetToCam.Magnitude2D(); float DistOnGround = TargetToCam.Magnitude2D();
m_fTrueBeta = CGeneral::GetATanOfXY(TargetToCam.x, TargetToCam.y); m_fTrueBeta = CGeneral::GetATanOfXY(TargetToCam.x, TargetToCam.y);
@ -1530,7 +1549,12 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient
TargetCoors.z += fTranslateCamUp; TargetCoors.z += fTranslateCamUp;
TargetCoors = DoAverageOnVector(TargetCoors); TargetCoors = DoAverageOnVector(TargetCoors);
// SA code
#ifdef FREE_CAM
if((bFreeMouseCam && Alpha > 0.0f) || (!bFreeMouseCam && Alpha > fBaseDist))
#else
if(Alpha > fBaseDist) // comparing an angle against a distance? if(Alpha > fBaseDist) // comparing an angle against a distance?
#endif
CamDist = fBaseDist + Cos(min(Alpha*fFalloff, HALFPI))*fAngleDist; CamDist = fBaseDist + Cos(min(Alpha*fFalloff, HALFPI))*fAngleDist;
else else
CamDist = fBaseDist + Cos(Alpha)*fAngleDist; CamDist = fBaseDist + Cos(Alpha)*fAngleDist;
@ -4441,7 +4465,7 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
float MouseX = CPad::GetPad(0)->GetMouseX(); float MouseX = CPad::GetPad(0)->GetMouseX();
float MouseY = CPad::GetPad(0)->GetMouseY(); float MouseY = CPad::GetPad(0)->GetMouseY();
float LookLeftRight, LookUpDown; float LookLeftRight, LookUpDown;
if((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){ if(bFreeMouseCam && (MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){
UseMouse = true; UseMouse = true;
LookLeftRight = -2.5f*MouseX; LookLeftRight = -2.5f*MouseX;
LookUpDown = 4.0f*MouseY; LookUpDown = 4.0f*MouseY;
@ -4572,6 +4596,645 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient
GetVectorsReadyForRW(); 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
bool isPlane = car->m_modelIndex == MI_DODO;
bool isHeli = false;
bool isBike = false;
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;
if (car->m_modelIndex == MI_FIRETRUCK) {
camSetArrPos = 7;
} else if (car->m_modelIndex == MI_RCBANDIT) {
camSetArrPos = 5;
} 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->m_status == STATUS_PLAYER_REMOTE)
zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];
else {
switch ((int)TheCamera.CarZoomIndicator) {
// near
case 1:
zoomModeAlphaOffset = ZmOneAlphaOffsetLCS[alphaArrPos];
break;
// mid
case 2:
zoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];
break;
// far
case 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;
float minDistForThisCar = approxCarLength * CARCAM_SET[camSetArrPos][3];
if (!isHeli || car->m_status == 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
TargetCoors.x += 0.6f * car->GetUp().x * colMaxZ;
TargetCoors.y += 0.6f * car->GetUp().y * colMaxZ;
TargetCoors.z += 0.6f * car->GetUp().z * colMaxZ;
}
float minDistForVehType = CARCAM_SET[camSetArrPos][4];
if ((int)TheCamera.CarZoomIndicator == 1 && (camSetArrPos < 2 || camSetArrPos == 7)) {
minDistForVehType = minDistForVehType * 0.65f;
}
float nextDistance = max(newDistance, minDistForVehType);
CA_MAX_DISTANCE = newDistance;
CA_MIN_DISTANCE = 3.5f;
if (ResetStatics) {
FOV = DefaultFOV;
// 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;
// TheCamera.m_bResetOldMatrix = 1;
// Garage exit cam is not working well in III...
// if (!TheCamera.m_bJustCameOutOfGarage) // && !sthForScript)
// {
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;
if (!TheCamera.m_bJustCameOutOfGarage) // && !sthForScript)
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();
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) {
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))
if (car->m_modelIndex != MI_FIRETRUCK) {
// if (!isBike || GetMysteriousWheelRelatedThingBike(car) > 3)
// if (!isHeli && (!isPlane || car->GetWheelsOnGround())) {
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;
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?) {
if (!isCar || car->m_modelIndex != MI_YARDIE) {
correctAlpha = false;
}
else {
xMovement = 0.0f;
yMovement = 0.0f;
}
// } else
// yMovement = 0.0;
if (!nextDirectionIsForward) {
yMovement = 0.0;
xMovement = 0.0;
}
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.
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;
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());
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) {
if (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1)
// || isBike && GetMysteriousWheelRelatedThingBike(car) > 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, true, 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) {
RwCameraSetNearClipPlane(Scene.camera, max(0.05f, obstacleTargetDist - 0.3f));
}
} else {
if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false)) {
float lessClip = obstacleCamDist - 0.35f;
if (lessClip <= 0.9f)
RwCameraSetNearClipPlane(Scene.camera, lessClip);
else
RwCameraSetNearClipPlane(Scene.camera, 0.9f);
} 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;
// Obviously some specific place in LC
if (Source.x > 11.0f && Source.x < 91.0f) {
if (Source.y > -680.0f && Source.y < -600.0f && Source.z < 24.4f)
Source.z = 24.4f;
}
// CCam::FixSourceAboveWaterLevel
if (CameraTarget.z >= -2.0f) {
float level = -6000.0;
// +0.5f is needed for III
if (CWaterLevel::GetWaterLevelNoWaves(Source.x, Source.y, Source.z, &level)) {
if (Source.z < level + 0.5f)
Source.z = level + 0.5f;
}
}
Front = TargetCoors - Source;
// -------- LCS specific part ends
GetVectorsReadyForRW();
// SA
// gTargetCoordsForLookingBehind = TargetCoors;
// SA code from CAutomobile::TankControl/FireTruckControl.
if (car->m_modelIndex == MI_RHINO || car->m_modelIndex == MI_FIRETRUCK) {
float &carGunLR = ((CAutomobile*)car)->m_fCarGunLR;
CVector hi = Multiply3x3(Front, car->GetMatrix());
// III/VC's firetruck turret angle is reversed
float angleToFace = (car->m_modelIndex == 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;
float turnPerFrame = CTimer::GetTimeStep() * (car->m_modelIndex == MI_FIRETRUCK ? 0.05f : 0.015f);
if (neededTurn <= turnPerFrame) {
if (neededTurn < -turnPerFrame)
angleToFace = carGunLR - turnPerFrame;
} else {
angleToFace = turnPerFrame + carGunLR;
}
if (car->m_modelIndex == 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
if (car->m_modelIndex == 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 #endif
STARTPATCHES STARTPATCHES

View File

@ -224,6 +224,7 @@ struct CCam
// custom stuff // custom stuff
void Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FollowCar_SA(const CVector &CameraTarget, float TargetOrientation, float, float);
}; };
static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size"); static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error"); static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");

View File

@ -64,7 +64,6 @@ bool &CMenuManager::m_bShutDownFrontEndRequested = *(bool*)0x95CD6A;
int8 &CMenuManager::m_PrefsUseWideScreen = *(int8*)0x95CD23; int8 &CMenuManager::m_PrefsUseWideScreen = *(int8*)0x95CD23;
int8 &CMenuManager::m_PrefsRadioStation = *(int8*)0x95CDA4; int8 &CMenuManager::m_PrefsRadioStation = *(int8*)0x95CDA4;
int8 &CMenuManager::m_bDisableMouseSteering = *(int8*)0x60252C; // 1
int32 &CMenuManager::m_PrefsBrightness = *(int32*)0x5F2E50; // 256 int32 &CMenuManager::m_PrefsBrightness = *(int32*)0x5F2E50; // 256
float &CMenuManager::m_PrefsLOD = *(float*)0x8F42C4; float &CMenuManager::m_PrefsLOD = *(float*)0x8F42C4;
int8 &CMenuManager::m_bFrontEnd_ReloadObrTxtGxt = *(int8*)0x628CFC; int8 &CMenuManager::m_bFrontEnd_ReloadObrTxtGxt = *(int8*)0x628CFC;
@ -97,6 +96,11 @@ int32 &JoyButtonJustClicked = *(int32*)0x628D10;
bool &holdingScrollBar = *(bool*)0x628D59; bool &holdingScrollBar = *(bool*)0x628D59;
//int32 *pControlTemp = 0; //int32 *pControlTemp = 0;
#ifndef MASTER
bool CMenuManager::m_PrefsMarketing = false;
bool CMenuManager::m_PrefsDisableTutorials = false;
#endif // !MASTER
// 0x5F311C // 0x5F311C
const char* FrontendFilenames[][2] = { const char* FrontendFilenames[][2] = {
{"fe2_mainpanel_ul", "" }, {"fe2_mainpanel_ul", "" },
@ -968,7 +972,7 @@ void CMenuManager::Draw()
rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF"); rightText = TheText.Get(m_PrefsDMA ? "FEM_ON" : "FEM_OFF");
break; break;
case MENUACTION_MOUSESTEER: case MENUACTION_MOUSESTEER:
rightText = TheText.Get(m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON"); rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON");
break; break;
} }
@ -1727,6 +1731,17 @@ void CMenuManager::InitialiseChangedLanguageSettings()
CTimer::Update(); CTimer::Update();
CGame::frenchGame = false; CGame::frenchGame = false;
CGame::germanGame = false; CGame::germanGame = false;
#ifdef MORE_LANGUAGES
switch (CMenuManager::m_PrefsLanguage) {
case LANGUAGE_RUSSIAN:
CFont::ReloadFonts(FONT_LANGSET_RUSSIAN);
break;
default:
CFont::ReloadFonts(FONT_LANGSET_EFIGS);
break;
}
#endif
switch (CMenuManager::m_PrefsLanguage) { switch (CMenuManager::m_PrefsLanguage) {
case LANGUAGE_FRENCH: case LANGUAGE_FRENCH:
CGame::frenchGame = true; CGame::frenchGame = true;
@ -1734,6 +1749,11 @@ void CMenuManager::InitialiseChangedLanguageSettings()
case LANGUAGE_GERMAN: case LANGUAGE_GERMAN:
CGame::germanGame = true; CGame::germanGame = true;
break; break;
#ifdef MORE_LANGUAGES
case LANGUAGE_RUSSIAN:
CGame::russianGame = true;
break;
#endif
default: default:
break; break;
} }
@ -2935,6 +2955,14 @@ CMenuManager::ProcessButtonPresses(void)
CMenuManager::InitialiseChangedLanguageSettings(); CMenuManager::InitialiseChangedLanguageSettings();
SaveSettings(); SaveSettings();
break; break;
#ifdef MORE_LANGUAGES
case MENUACTION_LANG_RUS:
m_PrefsLanguage = LANGUAGE_RUSSIAN;
m_bFrontEnd_ReloadObrTxtGxt = true;
CMenuManager::InitialiseChangedLanguageSettings();
SaveSettings();
break;
#endif
case MENUACTION_POPULATESLOTS_CHANGEMENU: case MENUACTION_POPULATESLOTS_CHANGEMENU:
PcSaveHelper.PopulateSlotInfo(); PcSaveHelper.PopulateSlotInfo();
@ -3141,7 +3169,7 @@ CMenuManager::ProcessButtonPresses(void)
CMenuManager::m_ControlMethod = CONTROL_STANDART; CMenuManager::m_ControlMethod = CONTROL_STANDART;
MousePointerStateHelper.bInvertVertically = false; MousePointerStateHelper.bInvertVertically = false;
TheCamera.m_fMouseAccelHorzntl = 0.0025f; TheCamera.m_fMouseAccelHorzntl = 0.0025f;
m_bDisableMouseSteering = true; CVehicle::m_bDisableMouseSteering = true;
TheCamera.m_bHeadBob = false; TheCamera.m_bHeadBob = false;
SaveSettings(); SaveSettings();
} }
@ -3460,7 +3488,7 @@ void CMenuManager::ProcessOnOffMenuOptions()
SaveSettings(); SaveSettings();
break; break;
case MENUACTION_MOUSESTEER: case MENUACTION_MOUSESTEER:
m_bDisableMouseSteering = !m_bDisableMouseSteering; CVehicle::m_bDisableMouseSteering = !CVehicle::m_bDisableMouseSteering;
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0);
SaveSettings(); SaveSettings();
break; break;

View File

@ -51,6 +51,9 @@ enum eLanguages
LANGUAGE_GERMAN, LANGUAGE_GERMAN,
LANGUAGE_ITALIAN, LANGUAGE_ITALIAN,
LANGUAGE_SPANISH, LANGUAGE_SPANISH,
#ifdef MORE_LANGUAGES
LANGUAGE_RUSSIAN,
#endif
}; };
enum eFrontendSprites enum eFrontendSprites
@ -301,6 +304,9 @@ enum eMenuAction
MENUACTION_UNK108, MENUACTION_UNK108,
MENUACTION_UNK109, MENUACTION_UNK109,
MENUACTION_UNK110, MENUACTION_UNK110,
#ifdef MORE_LANGUAGES
MENUACTION_LANG_RUS,
#endif
}; };
enum eCheckHover enum eCheckHover
@ -473,7 +479,6 @@ public:
static int32 &m_ControlMethod; static int32 &m_ControlMethod;
static int8 &m_PrefsDMA; static int8 &m_PrefsDMA;
static int32 &m_PrefsLanguage; static int32 &m_PrefsLanguage;
static int8 &m_bDisableMouseSteering;
static int32 &m_PrefsBrightness; static int32 &m_PrefsBrightness;
static float &m_PrefsLOD; static float &m_PrefsLOD;
static int8 &m_bFrontEnd_ReloadObrTxtGxt; static int8 &m_bFrontEnd_ReloadObrTxtGxt;
@ -492,6 +497,12 @@ public:
static int32 &sthWithButtons; static int32 &sthWithButtons;
static int32 &sthWithButtons2; static int32 &sthWithButtons2;
#ifndef MASTER
static bool m_PrefsMarketing;
static bool m_PrefsDisableTutorials;
#endif // !MASTER
public: public:
static void BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2); static void BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2);
static void CentreMousePointer(); static void CentreMousePointer();

View File

@ -99,6 +99,9 @@ bool &CGame::germanGame = *(bool*)0x95CD1E;
bool &CGame::noProstitutes = *(bool*)0x95CDCF; bool &CGame::noProstitutes = *(bool*)0x95CDCF;
bool &CGame::playingIntro = *(bool*)0x95CDC2; bool &CGame::playingIntro = *(bool*)0x95CDC2;
char *CGame::aDatFile = (char*)0x773A48; char *CGame::aDatFile = (char*)0x773A48;
#ifdef MORE_LANGUAGES
bool CGame::russianGame = false;
#endif
int &gameTxdSlot = *(int*)0x628D88; int &gameTxdSlot = *(int*)0x628D88;

View File

@ -16,6 +16,9 @@ public:
static bool &nastyGame; static bool &nastyGame;
static bool &frenchGame; static bool &frenchGame;
static bool &germanGame; static bool &germanGame;
#ifdef MORE_LANGUAGES
static bool russianGame;
#endif
static bool &noProstitutes; static bool &noProstitutes;
static bool &playingIntro; static bool &playingIntro;
static char *aDatFile; //[32]; static char *aDatFile; //[32];

View File

@ -65,6 +65,9 @@ const CMenuScreen aScreens[] = {
MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE,
#ifdef MORE_LANGUAGES
MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE,
#endif
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
}, },

View File

@ -214,6 +214,11 @@ void CTimer::EndUserPause(void)
m_UserPause = false; m_UserPause = false;
} }
uint32 CTimer::GetCyclesPerFrame()
{
return 20;
}
#if 1 #if 1
STARTPATCHES STARTPATCHES
InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP); InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP);

View File

@ -34,6 +34,7 @@ public:
static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }
static const float &GetTimeScale(void) { return ms_fTimeScale; } static const float &GetTimeScale(void) { return ms_fTimeScale; }
static void SetTimeScale(float ts) { ms_fTimeScale = ts; } static void SetTimeScale(float ts) { ms_fTimeScale = ts; }
static uint32 GetCyclesPerFrame();
static bool GetIsPaused() { return m_UserPause || m_CodePause; } static bool GetIsPaused() { return m_UserPause || m_CodePause; }
static bool GetIsUserPaused() { return m_UserPause; } static bool GetIsUserPaused() { return m_UserPause; }

View File

@ -171,10 +171,12 @@ enum Config {
# define NO_MOVIES // disable intro videos # define NO_MOVIES // disable intro videos
# define NO_CDCHECK # define NO_CDCHECK
# define CHATTYSPLASH // print what the game is loading # define CHATTYSPLASH // print what the game is loading
//# define TIMEBARS // print debug timers
#endif #endif
#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things
#define MORE_LANGUAGES // Add more translations to the game
// Pad // Pad
#define XINPUT #define XINPUT

View File

@ -51,6 +51,7 @@
#include "Script.h" #include "Script.h"
#include "Debug.h" #include "Debug.h"
#include "Console.h" #include "Console.h"
#include "timebars.h"
#define DEFAULT_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetFOV() * 0.5f))) #define DEFAULT_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetFOV() * 0.5f)))
@ -141,6 +142,11 @@ Idle(void *arg)
#endif #endif
CTimer::Update(); CTimer::Update();
#ifdef TIMEBARS
tbInit();
#endif
CSprite2d::InitPerFrame(); CSprite2d::InitPerFrame();
CFont::InitPerFrame(); CFont::InitPerFrame();
@ -155,16 +161,39 @@ Idle(void *arg)
FrontEndMenuManager.Process(); FrontEndMenuManager.Process();
} else { } else {
CPointLights::InitPerFrame(); CPointLights::InitPerFrame();
#ifdef TIMEBARS
tbStartTimer(0, "CGame::Process");
#endif
CGame::Process(); CGame::Process();
#ifdef TIMEBARS
tbEndTimer("CGame::Process");
tbStartTimer(0, "DMAudio.Service");
#endif
DMAudio.Service(); DMAudio.Service();
#ifdef TIMEBARS
tbEndTimer("DMAudio.Service");
#endif
} }
if (RsGlobal.quit) if (RsGlobal.quit)
return; return;
#else #else
CPointLights::InitPerFrame(); CPointLights::InitPerFrame();
#ifdef TIMEBARS
tbStartTimer(0, "CGame::Process");
#endif
CGame::Process(); CGame::Process();
#ifdef TIMEBARS
tbEndTimer("CGame::Process");
tbStartTimer(0, "DMAudio.Service");
#endif
DMAudio.Service(); DMAudio.Service();
#ifdef TIMEBARS
tbEndTimer("DMAudio.Service");
#endif
#endif #endif
if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){ if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
@ -191,9 +220,19 @@ Idle(void *arg)
pos.y = SCREEN_HEIGHT / 2.0f; pos.y = SCREEN_HEIGHT / 2.0f;
RsMouseSetPos(&pos); RsMouseSetPos(&pos);
} }
#endif
#ifdef TIMEBARS
tbStartTimer(0, "CnstrRenderList");
#endif #endif
CRenderer::ConstructRenderList(); CRenderer::ConstructRenderList();
#ifdef TIMEBARS
tbEndTimer("CnstrRenderList");
tbStartTimer(0, "PreRender");
#endif
CRenderer::PreRender(); CRenderer::PreRender();
#ifdef TIMEBARS
tbEndTimer("PreRender");
#endif
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){ if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255)) if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
@ -211,16 +250,31 @@ Idle(void *arg)
RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip()); RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());
RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart()); RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());
#ifdef TIMEBARS
tbStartTimer(0, "RenderScene");
#endif
RenderScene(); RenderScene();
#ifdef TIMEBARS
tbEndTimer("RenderScene");
#endif
RenderDebugShit(); RenderDebugShit();
RenderEffects(); RenderEffects();
#ifdef TIMEBARS
tbStartTimer(0, "RenderMotionBlur");
#endif
if((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) && if((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) &&
TheCamera.m_ScreenReductionPercentage > 0.0f) TheCamera.m_ScreenReductionPercentage > 0.0f)
TheCamera.SetMotionBlurAlpha(150); TheCamera.SetMotionBlurAlpha(150);
TheCamera.RenderMotionBlur(); TheCamera.RenderMotionBlur();
#ifdef TIMEBARS
tbEndTimer("RenderMotionBlur");
tbStartTimer(0, "Render2dStuff");
#endif
Render2dStuff(); Render2dStuff();
#ifdef TIMEBARS
tbEndTimer("Render2dStuff");
#endif
}else{ }else{
float viewWindow = DEFAULT_VIEWWINDOW; float viewWindow = DEFAULT_VIEWWINDOW;
#ifdef ASPECT_RATIO_SCALE #ifdef ASPECT_RATIO_SCALE
@ -237,11 +291,30 @@ Idle(void *arg)
#ifdef PS2_SAVE_DIALOG #ifdef PS2_SAVE_DIALOG
if (FrontEndMenuManager.m_bMenuActive) if (FrontEndMenuManager.m_bMenuActive)
DefinedState(); DefinedState();
#endif
#ifdef TIMEBARS
tbStartTimer(0, "RenderMenus");
#endif #endif
RenderMenus(); RenderMenus();
#ifdef TIMEBARS
tbEndTimer("RenderMenus");
tbStartTimer(0, "DoFade");
#endif
DoFade(); DoFade();
#ifdef TIMEBARS
tbEndTimer("DoFade");
tbStartTimer(0, "Render2dStuff-Fade");
#endif
Render2dStuffAfterFade(); Render2dStuffAfterFade();
#ifdef TIMEBARS
tbEndTimer("Render2dStuff-Fade");
#endif
CCredits::Render(); CCredits::Render();
#ifdef TIMEBARS
tbDisplay();
#endif
DoRWStuffEndOfFrame(); DoRWStuffEndOfFrame();
// if(g_SlowMode) // if(g_SlowMode)

View File

@ -373,8 +373,10 @@ DebugMenuPopulate(void)
extern bool PrintDebugCode; extern bool PrintDebugCode;
extern int16 &DebugCamMode; extern int16 &DebugCamMode;
#ifdef FREE_CAM #ifdef FREE_CAM
extern bool bFreeCam; extern bool bFreePadCam;
DebugMenuAddVarBool8("Cam", "Free Cam", (int8*)&bFreeCam, nil); extern bool bFreeMouseCam;
DebugMenuAddVarBool8("Cam", "Free Gamepad Cam", (int8*)&bFreePadCam, nil);
DebugMenuAddVarBool8("Cam", "Free Mouse Cam", (int8*)&bFreeMouseCam, nil);
#endif #endif
DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil); DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil);
DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil); DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil);

121
src/core/timebars.cpp Normal file
View File

@ -0,0 +1,121 @@
#ifndef MASTER
#include "common.h"
#include "Font.h"
#include "Frontend.h"
#include "Timer.h"
#include "Text.h"
#define MAX_TIMERS (50)
#define MAX_MS_COLLECTED (40)
// enables frame time output
#define FRAMETIME
struct sTimeBar
{
char name[20];
float startTime;
float endTime;
int32 unk;
};
struct
{
sTimeBar Timers[MAX_TIMERS];
uint32 count;
} TimerBar;
float MaxTimes[MAX_TIMERS];
float MaxFrameTime;
uint32 curMS;
uint32 msCollected[MAX_MS_COLLECTED];
#ifdef FRAMETIME
float FrameInitTime;
#endif
void tbInit()
{
TimerBar.count = 0;
uint32 i = CTimer::GetFrameCounter() & 0x7F;
if (i == 0) {
do
MaxTimes[i++] = 0.0f;
while (i != MAX_TIMERS);
#ifdef FRAMETIME
MaxFrameTime = 0.0f;
#endif
}
#ifdef FRAMETIME
FrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
}
void tbStartTimer(int32 unk, char *name)
{
strcpy(TimerBar.Timers[TimerBar.count].name, name);
TimerBar.Timers[TimerBar.count].unk = unk;
TimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
TimerBar.count++;
}
void tbEndTimer(char* name)
{
uint32 n = 1500;
for (uint32 i = 0; i < TimerBar.count; i++) {
if (strcmp(name, TimerBar.Timers[i].name) == 0)
n = i;
}
assert(n != 1500);
TimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
}
float Diag_GetFPS()
{
return 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);
}
void tbDisplay()
{
char temp[200];
wchar wtemp[200];
#ifdef FRAMETIME
float FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();
#endif
msCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();
CFont::SetBackgroundOff();
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
CFont::SetScale(0.48f, 1.12f);
CFont::SetCentreOff();
CFont::SetJustifyOff();
CFont::SetWrapx(640.0f);
CFont::SetRightJustifyOff();
CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK);
sprintf(temp, "FPS: %.2f", Diag_GetFPS());
AsciiToUnicode(temp, wtemp);
CFont::SetColor(CRGBA(255, 255, 255, 255));
if (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);
#ifndef FINAL
// Timers output (my own implementation)
for (uint32 i = 0; i < TimerBar.count; i++) {
MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);
sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);
}
#ifdef FRAMETIME
MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime);
sprintf(temp, "Frame Time: %.2f", MaxFrameTime);
AsciiToUnicode(temp, wtemp);
CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);
#endif // FRAMETIME
#endif // !FINAL
}
}
#endif // !MASTER

6
src/core/timebars.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
void tbInit();
void tbStartTimer(int32, char*);
void tbEndTimer(char*);
void tbDisplay();

View File

@ -59,6 +59,10 @@
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
#ifdef FREE_CAM
extern bool bFreeMouseCam;
#endif
CPed *gapTempPedList[50]; CPed *gapTempPedList[50];
uint16 gnNumTempPedList; uint16 gnNumTempPedList;
@ -807,6 +811,10 @@ CPed::IsPedInControl(void)
bool bool
CPed::CanStrafeOrMouseControl(void) CPed::CanStrafeOrMouseControl(void)
{ {
#ifdef FREE_CAM
if (bFreeMouseCam)
return false;
#endif
return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY || return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||
m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP; m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP;
} }
@ -6984,7 +6992,11 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
#endif #endif
) { ) {
#ifdef FREE_CAM
if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !bFreeMouseCam) {
#else
if (TheCamera.Cams[0].Using3rdPersonMouseCam()) { if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
#endif
float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur); float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);
ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle); ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);
ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle); ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);

View File

@ -18,6 +18,10 @@
#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f #define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f
#ifdef FREE_CAM
extern bool bFreeMouseCam;
#endif
CPlayerPed::~CPlayerPed() CPlayerPed::~CPlayerPed()
{ {
delete m_pWanted; delete m_pWanted;
@ -688,7 +692,14 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed)
float padMove = CVector2D(leftRight, upDown).Magnitude(); float padMove = CVector2D(leftRight, upDown).Magnitude();
float padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE; float padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE;
if (padMoveInGameUnit > 0.0f) { if (padMoveInGameUnit > 0.0f) {
#ifdef FREE_CAM
if (!bFreeMouseCam)
m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation); m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
else
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;
#else
m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);
#endif
m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed); m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed);
} else { } else {
m_fMoveSpeed = 0.0f; m_fMoveSpeed = 0.0f;
@ -981,6 +992,12 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
if (padUsed->TargetJustDown()) { if (padUsed->TargetJustDown()) {
SetStoredState(); SetStoredState();
m_nPedState = PED_SNIPER_MODE; m_nPedState = PED_SNIPER_MODE;
#ifdef FREE_CAM
if (bFreeMouseCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) {
m_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
SetHeading(m_fRotationCur);
}
#endif
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) if (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)
TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0); TheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0);
else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE) else if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE)
@ -1000,6 +1017,11 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) { if (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) {
if (m_nSelectedWepSlot == m_currentWeapon) { if (m_nSelectedWepSlot == m_currentWeapon) {
if (m_pPointGunAt) { if (m_pPointGunAt) {
#ifdef FREE_CAM
if (bFreeMouseCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE && m_fMoveSpeed < 1.0f)
StartFightAttack(padUsed->GetWeapon());
else
#endif
SetAttack(m_pPointGunAt); SetAttack(m_pPointGunAt);
} else if (m_currentWeapon != WEAPONTYPE_UNARMED) { } else if (m_currentWeapon != WEAPONTYPE_UNARMED) {
if (m_nPedState == PED_ATTACK) { if (m_nPedState == PED_ATTACK) {
@ -1027,11 +1049,65 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
bIsAttacking = false; bIsAttacking = false;
} }
} }
#ifdef FREE_CAM
// Rotate player/arm when shooting. We don't have auto-rotation anymore
if (CCamera::m_bUseMouse3rdPerson && bFreeMouseCam &&
m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
// Weapons except throwable and melee ones
if (weaponInfo->m_bCanAim || weaponInfo->m_b1stPerson || weaponInfo->m_bExpands) {
if ((padUsed->GetTarget() && weaponInfo->m_bCanAimWithArm) || padUsed->GetWeapon()) {
float limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation);
// On this one we can rotate arm.
if (weaponInfo->m_bCanAimWithArm) {
if (!padUsed->GetWeapon()) { // making this State != ATTACK still stops it after attack. Re-start it immediately!
SetPointGunAt(nil);
bIsPointingGunAt = false; // to not stop after attack
}
SetLookFlag(limitedCam, true);
SetAimFlag(limitedCam);
#ifdef VC_PED_PORTS
SetLookTimer(INT_MAX); // removing this makes head move for real, but I experinced some bugs.
#endif
} else {
m_fRotationDest = limitedCam;
m_headingRate = 50.0f;
// Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)
if (weaponInfo->m_bCanAim && padUsed->WeaponJustDown()) {
m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
float limitedRotDest = m_fRotationDest;
if (m_fRotationCur - PI > m_fRotationDest) {
limitedRotDest += 2 * PI;
} else if (PI + m_fRotationCur < m_fRotationDest) {
limitedRotDest -= 2 * PI;
}
m_fRotationCur += (limitedRotDest - m_fRotationCur) / 2;
}
}
} else if (weaponInfo->m_bCanAimWithArm)
ClearPointGunAt();
else
RestoreHeadingRate();
}
}
#endif
if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) { if (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {
if (m_pPointGunAt) { if (m_pPointGunAt) {
// what?? // what??
if (!m_pPointGunAt if (!m_pPointGunAt
|| CCamera::m_bUseMouse3rdPerson || m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) { #ifdef FREE_CAM
|| (!bFreeMouseCam && CCamera::m_bUseMouse3rdPerson)
#else
|| CCamera::m_bUseMouse3rdPerson
#endif
|| m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->bInVehicle) {
ClearWeaponTarget(); ClearWeaponTarget();
return; return;
} }
@ -1047,7 +1123,12 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed)
} }
TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0); TheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0);
TheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition()); TheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition());
} else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) { }
#ifdef FREE_CAM
else if ((bFreeMouseCam && weaponInfo->m_eWeaponFire == WEAPON_FIRE_MELEE) || (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson)) {
#else
else if (weaponInfo->m_bCanAim && !CCamera::m_bUseMouse3rdPerson) {
#endif
if (padUsed->TargetJustDown()) if (padUsed->TargetJustDown())
FindWeaponLockOnTarget(); FindWeaponLockOnTarget();
} }

View File

@ -8,7 +8,15 @@ CFontDetails &CFont::Details = *(CFontDetails*)0x8F317C;
int16 &CFont::NewLine = *(int16*)0x95CC94; int16 &CFont::NewLine = *(int16*)0x95CC94;
CSprite2d *CFont::Sprite = (CSprite2d*)0x95CC04; CSprite2d *CFont::Sprite = (CSprite2d*)0x95CC04;
#ifdef MORE_LANGUAGES
uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS;
int32 CFont::Slot = -1;
int16 CFont::Size[2][3][193] = {
{
#else
int16 CFont::Size[3][193] = { int16 CFont::Size[3][193] = {
#endif
{ {
13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31, 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31,
23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26, 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26,
@ -56,6 +64,56 @@ int16 CFont::Size[3][193] = {
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19 19
} }
#ifdef MORE_LANGUAGES
},
{
{ 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17,
13, 31, 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10,
35, 26, 26, 26, 26, 30, 26, 24, 23, 24, 22, 21, 24,
26, 10, 20, 26, 22, 29, 26, 25, 23, 25, 24, 24, 22,
25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37, 35, 21,
22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21,
21, 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 13,
33, 13, 13, 13, 24, 22, 22, 19, 26, 21, 30, 20, 23,
23, 21, 24, 26, 23, 22, 23, 21, 22, 20, 20, 26, 25,
24, 22, 31, 32, 23, 30, 22, 22, 32, 23, 19, 18, 18,
15, 22, 19, 27, 19, 20, 20, 18, 22, 24, 20, 19, 19,
20, 19, 16, 19, 28, 20, 20, 18, 26, 27, 19, 26, 18,
19, 27, 19, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 18, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 20 },
{ 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11,
17, 13, 33, 28, 14, 22, 21, 24, 23, 23, 21, 23, 22,
10, 35, 13, 35, 13, 33, 5, 25, 22, 23, 24, 21, 21, 24,
24, 9, 20, 24, 21, 27, 25, 25, 22, 25, 23, 20, 23, 23,
23, 31, 23, 23, 23, 37, 33, 37, 35, 37, 35, 21, 19,
19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21, 20,
22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33,
33, 35, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 16, },
{ 15, 14, 16, 25, 19,
26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, 19, 18, 19,
19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35,
15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29,
19, 20, 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19,
33, 31, 39, 37, 39, 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23,
21, 21, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35,
35, 35, 35, 37, 19, 19, 19, 19, 19, 19, 29, 19, 19,
19, 20, 22, 31, 19, 19, 19, 19, 19, 29, 19, 29, 19,
21, 19, 30, 31, 21, 29, 19, 19, 29, 19, 21, 23, 32,
21, 21, 30, 31, 22, 21, 32, 33, 23, 32, 21, 21, 32,
21, 19, 19, 30, 31, 22, 22, 21, 32, 33, 23, 32, 21,
21, 32, 21, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 11, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19 },
}
#endif
}; };
uint16 foreign_table[128] = { uint16 foreign_table[128] = {
@ -75,7 +133,21 @@ CFont::Initialise(void)
int slot; int slot;
slot = CTxdStore::AddTxdSlot("fonts"); slot = CTxdStore::AddTxdSlot("fonts");
#ifdef MORE_LANGUAGES
Slot = slot;
switch (LanguageSet)
{
case FONT_LANGSET_EFIGS:
default:
CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD"); CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
break;
case FONT_LANGSET_RUSSIAN:
CTxdStore::LoadTxd(slot, "MODELS/FONTS_R.TXD");
break;
}
#else
CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD");
#endif
CTxdStore::AddRef(slot); CTxdStore::AddRef(slot);
CTxdStore::PushCurrentTxd(); CTxdStore::PushCurrentTxd();
CTxdStore::SetCurrentTxd(slot); CTxdStore::SetCurrentTxd(slot);
@ -101,13 +173,48 @@ CFont::Initialise(void)
CTxdStore::PopCurrentTxd(); CTxdStore::PopCurrentTxd();
} }
#ifdef MORE_LANGUAGES
void
CFont::ReloadFonts(uint8 set)
{
if (Slot != -1 && LanguageSet != set) {
Sprite[0].Delete();
Sprite[1].Delete();
Sprite[2].Delete();
CTxdStore::PushCurrentTxd();
CTxdStore::RemoveTxd(Slot);
switch (set)
{
case FONT_LANGSET_EFIGS:
default:
CTxdStore::LoadTxd(Slot, "MODELS/FONTS.TXD");
break;
case FONT_LANGSET_RUSSIAN:
CTxdStore::LoadTxd(Slot, "MODELS/FONTS_R.TXD");
break;
}
CTxdStore::SetCurrentTxd(Slot);
Sprite[0].SetTexture("font2", "font2_mask");
Sprite[1].SetTexture("pager", "pager_mask");
Sprite[2].SetTexture("font1", "font1_mask");
CTxdStore::PopCurrentTxd();
}
LanguageSet = set;
}
#endif
void void
CFont::Shutdown(void) CFont::Shutdown(void)
{ {
Sprite[0].Delete(); Sprite[0].Delete();
Sprite[1].Delete(); Sprite[1].Delete();
Sprite[2].Delete(); Sprite[2].Delete();
#ifdef MORE_LANGUAGES
CTxdStore::RemoveTxdSlot(Slot);
Slot = -1;
#else
CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("fonts")); CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("fonts"));
#endif
} }
void void
@ -382,19 +489,33 @@ CFont::PrintString(float x, float y, uint16 *start, uint16 *end, float spwidth)
float float
CFont::GetCharacterWidth(uint16 c) CFont::GetCharacterWidth(uint16 c)
{ {
#ifdef MORE_LANGUAGES
if (Details.proportional)
return Size[LanguageSet][Details.style][c];
else
return Size[LanguageSet][Details.style][192];
#else
if (Details.proportional) if (Details.proportional)
return Size[Details.style][c]; return Size[Details.style][c];
else else
return Size[Details.style][192]; return Size[Details.style][192];
#endif // MORE_LANGUAGES
} }
float float
CFont::GetCharacterSize(uint16 c) CFont::GetCharacterSize(uint16 c)
{ {
#ifdef MORE_LANGUAGES
if(Details.proportional)
return Size[LanguageSet][Details.style][c] * Details.scaleX;
else
return Size[LanguageSet][Details.style][192] * Details.scaleX;
#else
if (Details.proportional) if (Details.proportional)
return Size[Details.style][c] * Details.scaleX; return Size[Details.style][c] * Details.scaleX;
else else
return Size[Details.style][192] * Details.scaleX; return Size[Details.style][192] * Details.scaleX;
#endif // MORE_LANGUAGES
} }
float float

View File

@ -39,9 +39,23 @@ enum {
ALIGN_RIGHT, ALIGN_RIGHT,
}; };
#ifdef MORE_LANGUAGES
enum
{
FONT_LANGSET_EFIGS,
FONT_LANGSET_RUSSIAN
};
#endif
class CFont class CFont
{ {
#ifdef MORE_LANGUAGES
static int16 Size[2][3][193];
static uint8 LanguageSet;
static int32 Slot;
#else
static int16 Size[3][193]; static int16 Size[3][193];
#endif
static int16 &NewLine; static int16 &NewLine;
static CSprite2d *Sprite; //[3] static CSprite2d *Sprite; //[3]
public: public:
@ -136,4 +150,6 @@ public:
if(Details.alphaFade < 255.0f) if(Details.alphaFade < 255.0f)
Details.dropColor.a *= Details.alphaFade/255.0f; Details.dropColor.a *= Details.alphaFade/255.0f;
} }
static void ReloadFonts(uint8 set);
}; };

View File

@ -43,6 +43,11 @@ CText::Load(void)
case LANGUAGE_SPANISH: case LANGUAGE_SPANISH:
sprintf(filename, "SPANISH.GXT"); sprintf(filename, "SPANISH.GXT");
break; break;
#ifdef MORE_LANGUAGES
case LANGUAGE_RUSSIAN:
sprintf(filename, "RUSSIAN.GXT");
break;
#endif
} }
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb"); length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");

View File

@ -2339,10 +2339,17 @@ CAutomobile::FireTruckControl(void)
if(this == FindPlayerVehicle()){ if(this == FindPlayerVehicle()){
if(!CPad::GetPad(0)->GetWeapon()) if(!CPad::GetPad(0)->GetWeapon())
return; return;
#ifdef FREE_CAM
extern bool bFreeMouseCam;
if (!bFreeMouseCam)
#endif
{
m_fCarGunLR += CPad::GetPad(0)->GetCarGunLeftRight() * 0.00025f * CTimer::GetTimeStep(); m_fCarGunLR += CPad::GetPad(0)->GetCarGunLeftRight() * 0.00025f * CTimer::GetTimeStep();
m_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown() * 0.0001f * CTimer::GetTimeStep(); m_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown() * 0.0001f * CTimer::GetTimeStep();
}
m_fCarGunUD = clamp(m_fCarGunUD, 0.05f, 0.3f); m_fCarGunUD = clamp(m_fCarGunUD, 0.05f, 0.3f);
CVector cannonPos(0.0f, 1.5f, 1.9f); CVector cannonPos(0.0f, 1.5f, 1.9f);
cannonPos = GetMatrix() * cannonPos; cannonPos = GetMatrix() * cannonPos;
CVector cannonDir( CVector cannonDir(
@ -2408,7 +2415,12 @@ CAutomobile::TankControl(void)
// Rotate turret // Rotate turret
float prevAngle = m_fCarGunLR; float prevAngle = m_fCarGunLR;
#ifdef FREE_CAM
extern bool bFreeMouseCam;
if(!bFreeMouseCam)
#endif
m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep(); m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();
if(m_fCarGunLR < 0.0f) if(m_fCarGunLR < 0.0f)
m_fCarGunLR += TWOPI; m_fCarGunLR += TWOPI;
if(m_fCarGunLR > TWOPI) if(m_fCarGunLR > TWOPI)