Merge remote-tracking branch 'upstream/master' into carctrl_dev

This commit is contained in:
Nikolay Korolev 2019-10-08 23:57:58 +03:00
commit 9e5a5f2ab6
40 changed files with 878 additions and 147 deletions

View File

@ -162,7 +162,7 @@ void cMusicManager::DisplayRadioStationName()
CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_SCALE_X(640.0f));
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_Y(23.0f), pCurrentStation);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation);
if (gNumRetunePresses)
CFont::SetColor(CRGBA(102, 133, 143, 255));

View File

@ -3,3 +3,4 @@
#include "Cranes.h"
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }

View File

@ -7,4 +7,5 @@ class CCranes
{
public:
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*);
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*);
};

View File

@ -28,8 +28,8 @@ int8 &CDarkel::InterruptedWeapon = *(int8*)0x95CD60;
int8 &CDarkel::bStandardSoundAndMessages = *(int8*)0x95CDB6;
int8 &CDarkel::bNeedHeadShot = *(int8*)0x95CDCA;
int8 &CDarkel::bProperKillFrenzy = *(int8*)0x95CD98;
eKillFrenzyStatus &CDarkel::Status = *(eKillFrenzyStatus*)0x95CCB4;
uint16 (&CDarkel::RegisteredKills)[NUMDEFAULTMODELS] = *(uint16(*)[NUMDEFAULTMODELS]) * (uintptr*)0x6EDBE0;
uint16 &CDarkel::Status = *(uint16*)0x95CCB4;
uint16 (&CDarkel::RegisteredKills)[NUM_DEFAULT_MODELS] = *(uint16(*)[NUM_DEFAULT_MODELS]) * (uintptr*)0x6EDBE0;
int32 &CDarkel::ModelToKill = *(int32*)0x8F2C78;
int32 &CDarkel::ModelToKill2 = *(int32*)0x885B40;
int32 &CDarkel::ModelToKill3 = *(int32*)0x885B3C;
@ -185,7 +185,7 @@ CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype)
void
CDarkel::ResetModelsKilledByPlayer()
{
for (int i = 0; i < NUMDEFAULTMODELS; i++)
for (int i = 0; i < NUM_DEFAULT_MODELS; i++)
RegisteredKills[i] = 0;
}

View File

@ -1,10 +1,11 @@
#pragma once
#include "Weapon.h"
#include "ModelIndices.h"
class CVehicle;
class CPed;
enum eKillFrenzyStatus
enum
{
KILLFRENZY_NONE,
KILLFRENZY_ONGOING,
@ -25,8 +26,8 @@ private:
static int8 &bStandardSoundAndMessages;
static int8 &bNeedHeadShot;
static int8 &bProperKillFrenzy;
static eKillFrenzyStatus &Status;
static uint16 (&RegisteredKills)[NUMDEFAULTMODELS];
static uint16 &Status;
static uint16 (&RegisteredKills)[NUM_DEFAULT_MODELS];
static int32 &ModelToKill;
static int32 &ModelToKill2;
static int32 &ModelToKill3;

293
src/control/GameLogic.cpp Normal file
View File

@ -0,0 +1,293 @@
#include "common.h"
#include "patcher.h"
#include "GameLogic.h"
#include "Clock.h"
#include "Stats.h"
#include "Pickups.h"
#include "Timer.h"
#include "Streaming.h"
#include "CutsceneMgr.h"
#include "World.h"
#include "PlayerPed.h"
#include "Camera.h"
#include "Messages.h"
#include "CarCtrl.h"
#include "Restart.h"
#include "Pad.h"
#include "References.h"
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
uint8 CGameLogic::ActivePlayers; // 0x95CD5E
void
CGameLogic::InitAtStartOfGame()
{
ActivePlayers = 1;
}
void
CGameLogic::PassTime(uint32 time)
{
uint8 minutes, hours, days;
minutes = time + CClock::GetMinutes();
hours = CClock::GetHours();
for (; minutes >= 60; minutes -= 60)
hours++;
if (hours > 23) {
days = CStats::DaysPassed;
for (; hours >= 24; hours -= 24)
days++;
CStats::DaysPassed = days;
}
CClock::SetGameClock(hours, minutes);
CPickups::PassTime(time * 1000);
}
void
CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
{
CTimer::Stop();
CStreaming::FlushRequestList();
CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory();
CStreaming::LoadScene(pos);
CTimer::Update();
}
void
CGameLogic::Update()
{
CVector vecRestartPos;
float fRestartFloat;
if (CCutsceneMgr::ms_cutsceneProcessing) return;
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.KillPlayer();
}
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
pPlayerInfo.m_pPed->ClearAdrenaline();
pPlayerInfo.ArrestPlayer();
}
break;
case WBSTATE_WASTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = false;
CRestart::OverridePoliceStationLevel = false;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextDeath = true;
}
break;
case WBSTATE_BUSTED:
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney;
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
case 0:
case 1:
takeMoney = 100;
break;
case 2:
takeMoney = 200;
break;
case 3:
takeMoney = 400;
break;
case 4:
takeMoney = 600;
break;
case 5:
takeMoney = 900;
break;
case 6:
takeMoney = 1500;
break;
}
if (pPlayerInfo.m_bGetOutOfJailFree) {
pPlayerInfo.m_bGetOutOfJailFree = false;
} else {
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
pPlayerInfo.m_pPed->ClearWeapons();
}
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
}
else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = false;
CRestart::OverridePoliceStationLevel = false;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
} else CRestart::bFadeInAfterNextArrest = true;
}
break;
case WBSTATE_FAILED_CRITICAL_MISSION:
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
if (pPlayerInfo.m_pPed->bInVehicle) {
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
if (pVehicle != nil) {
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
pVehicle->pDriver = nil;
if (pVehicle->m_status != STATUS_WRECKED)
pVehicle->m_status = STATUS_ABANDONED;
} else
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
}
}
CEventList::Initialise();
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverridePoliceStationLevel = false;
CRestart::OverrideHospitalLevel = false;
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
CCarCtrl::CountDownToCarsAtStart = 2;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
}
break;
case 4:
return;
}
}
void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{
pPlayerPed->m_fHealth = 100.0f;
pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCount = 0;
pPlayerPed->bDoBloodyFootprints = false;
pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire)
pPlayerPed->m_pFire->Extinguish();
pPlayerPed->bInVehicle = false;
pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset();
pPlayerPed->RestartNonPartialAnims();
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList();
pos.z += 1.0f;
pPlayerPed->Teleport(pos);
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
pPlayerPed->RestoreHeadingRate();
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed);
}
STARTPATCHES
InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP);
InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP);
InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP);
InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP);
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
ENDPATCHES

13
src/control/GameLogic.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
class CGameLogic
{
public:
static void InitAtStartOfGame();
static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos);
static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
static uint8 ActivePlayers;
};

View File

@ -71,6 +71,7 @@ bool CGarages::HasCarBeenCrushed(int32 handle)
WRAPPER void CGarages::TriggerMessage(const char *text, int16, uint16 time, int16) { EAXJMP(0x426B20); }
WRAPPER bool CGarages::IsPointWithinHideOutGarage(CVector&) { EAXJMP(0x428260); }
WRAPPER bool CGarages::IsPointWithinAnyGarage(CVector&) { EAXJMP(0x428320); }
WRAPPER void CGarages::PlayerArrestedOrDied() { EAXJMP(0x427F60); }
#if 0
WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }
@ -78,40 +79,40 @@ WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }
void CGarages::PrintMessages()
{
if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) {
CFont::SetScale(SCREEN_SCALE_X(1.2f / 2), SCREEN_SCALE_Y(1.5f / 2)); // BUG: game doesn't use macro here.
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); // BUG: game doesn't use macro here.
CFont::SetPropOn();
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f));
CFont::SetCentreOn();
CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, 255));
float y_offset = SCREEN_HEIGHT / 3; // THIS is PS2 calculation
// y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements
if (MessageNumberInString2 < 0) {
if (MessageNumberInString < 0) {
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString((SCREEN_WIDTH/ 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString));
CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f), TheText.Get(MessageIDString));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
}
else {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0f - 40.0f), gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f - 40.0f), gUString);
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
else {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f + 2.0f - 40.0f), gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(-84.0f - 40.0f), gUString);
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
}

View File

@ -27,4 +27,5 @@ public:
static bool HasCarBeenCrushed(int32);
static bool IsPointWithinHideOutGarage(CVector&);
static bool IsPointWithinAnyGarage(CVector&);
static void PlayerArrestedOrDied();
};

View File

@ -2,6 +2,13 @@
#include "patcher.h"
#include "Restart.h"
bool &CRestart::OverrideHospitalLevel = *(bool*)0x95CD4C;
bool &CRestart::OverridePoliceStationLevel = *(bool*)0x95CD50;
bool &CRestart::bFadeInAfterNextArrest = *(bool*)0x95CD69;
bool &CRestart::bFadeInAfterNextDeath = *(bool*)0x95CD9D;
WRAPPER void CRestart::AddHospitalRestartPoint(const CVector&, float) { EAXJMP(0x436100); }
WRAPPER void CRestart::AddPoliceRestartPoint(const CVector&, float) { EAXJMP(0x436150); }
WRAPPER void CRestart::OverrideNextRestart(const CVector&, float) { EAXJMP(0x4366C0); }
WRAPPER void CRestart::OverrideNextRestart(const CVector&, float) { EAXJMP(0x4366C0); }
WRAPPER void CRestart::FindClosestHospitalRestartPoint(const CVector &, CVector *, float *) { EAXJMP(0x4361A0); }
WRAPPER void CRestart::FindClosestPoliceRestartPoint(const CVector &, CVector *, float *) { EAXJMP(0x436450); }

View File

@ -6,4 +6,12 @@ public:
static void AddPoliceRestartPoint(const CVector&, float);
static void AddHospitalRestartPoint(const CVector&, float);
static void OverrideNextRestart(const CVector&, float);
static void FindClosestHospitalRestartPoint(const CVector &, CVector *, float *);
static void FindClosestPoliceRestartPoint(const CVector &, CVector *, float *);
static bool &OverrideHospitalLevel;
static bool &OverridePoliceStationLevel;
static bool &bFadeInAfterNextArrest;
static bool &bFadeInAfterNextDeath;
};

View File

@ -1349,6 +1349,14 @@ CCamera::TakeControlWithSpline(short nSwitch)
//FindPlayerPed(); // unused
};
void CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString()
{
m_bCamDirectlyInFront = true;
CPlayerPed *player = FindPlayerPed();
if (player)
m_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);
}
STARTPATCHES
InjectHook(0x42C760, (bool (CCamera::*)(const CVector &center, float radius, const CMatrix *mat))&CCamera::IsSphereVisible, PATCH_JUMP);
InjectHook(0x46FD00, &CCamera::SetFadeColour, PATCH_JUMP);
@ -1357,6 +1365,8 @@ STARTPATCHES
InjectHook(0x46FD80, &CCamera::SetMotionBlurAlpha, PATCH_JUMP);
InjectHook(0x46F940, &CCamera::RenderMotionBlur, PATCH_JUMP);
InjectHook(0x46FC90, &CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString, PATCH_JUMP);
InjectHook(0x456F40, WellBufferMe, PATCH_JUMP);
InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP);
InjectHook(0x457710, &CCam::DoAverageOnVector, PATCH_JUMP);

View File

@ -489,6 +489,7 @@ int m_iModeObbeCamIsInForCar;
void SetCamCutSceneOffSet(const CVector&);
void TakeControlWithSpline(short);
void RestoreWithJumpCut(void);
void SetCameraDirectlyInFrontForFollowPed_CamOnAString(void);
void dtor(void) { this->CCamera::~CCamera(); }
};

View File

@ -10,7 +10,6 @@ class CCutsceneHead;
class CCutsceneMgr
{
static bool &ms_running;
static bool &ms_cutsceneProcessing;
static CCutsceneObject *(&ms_pCutsceneObjects)[NUMCUTSCENEOBJECTS];
static int32 &ms_numCutsceneObjs;
@ -25,6 +24,7 @@ class CCutsceneMgr
public:
static CDirectory *&ms_pCutsceneDir;
static uint32 &ms_cutsceneLoadStatus;
static bool &ms_cutsceneProcessing;
static bool IsRunning(void) { return ms_running; }
static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }

View File

@ -997,7 +997,7 @@ void CMenuManager::DrawFrontEndNormal()
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
CRect mouse(0.0f, 0.0f, SCREEN_SCALE_X(75.0f), SCREEN_SCALE_X(75.0f));
CRect mouse(0.0f, 0.0f, SCREEN_SCALE_X(75.0f), SCREEN_SCALE_Y(75.0f));
mouse.Translate(m_nMousePosX, m_nMousePosY);
CRect shad = mouse;
shad.Translate(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(3.0f));

View File

@ -5,25 +5,32 @@
#include "Frontend.h"
#include "Vehicle.h"
#include "PlayerSkin.h"
#include "Darkel.h"
#include "Messages.h"
#include "Text.h"
#include "Stats.h"
WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); }
WRAPPER void CPlayerInfo::AwardMoneyForExplosion(CVehicle *vehicle) { EAXJMP(0x4A15F0); }
WRAPPER void CPlayerInfo::Process(void) { EAXJMP(0x49FD30); }
void CPlayerInfo::SetPlayerSkin(char *skin)
void
CPlayerInfo::SetPlayerSkin(char *skin)
{
strncpy(m_aSkinName, skin, 32);
LoadPlayerSkin();
}
CVector& CPlayerInfo::GetPos()
CVector&
CPlayerInfo::GetPos()
{
if (m_pPed->bInVehicle && m_pPed->m_pMyVehicle)
return m_pPed->m_pMyVehicle->GetPosition();
return m_pPed->GetPosition();
}
void CPlayerInfo::LoadPlayerSkin()
void
CPlayerInfo::LoadPlayerSkin()
{
DeletePlayerSkin();
@ -32,7 +39,8 @@ void CPlayerInfo::LoadPlayerSkin()
m_pSkinTexture = CPlayerSkin::GetSkinTexture(DEFAULT_SKIN_NAME);
}
void CPlayerInfo::DeletePlayerSkin()
void
CPlayerInfo::DeletePlayerSkin()
{
if (m_pSkinTexture) {
RwTextureDestroy(m_pSkinTexture);
@ -40,7 +48,33 @@ void CPlayerInfo::DeletePlayerSkin()
}
}
void
CPlayerInfo::KillPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_WASTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("DEAD"), 4000, 2);
CStats::TimesDied++;
}
void
CPlayerInfo::ArrestPlayer()
{
if (m_WBState != WBSTATE_PLAYING) return;
m_WBState = WBSTATE_BUSTED;
m_nWBTime = CTimer::GetTimeInMilliseconds();
CDarkel::ResetOnPlayerDeath();
CMessages::AddBigMessage(TheText.Get("BUSTED"), 5000, 2);
CStats::TimesArrested++;
}
STARTPATCHES
InjectHook(0x4A1700, &CPlayerInfo::LoadPlayerSkin, PATCH_JUMP);
InjectHook(0x4A1750, &CPlayerInfo::DeletePlayerSkin, PATCH_JUMP);
InjectHook(0x4A12E0, &CPlayerInfo::KillPlayer, PATCH_JUMP);
InjectHook(0x4A1330, &CPlayerInfo::ArrestPlayer, PATCH_JUMP);
ENDPATCHES

View File

@ -73,6 +73,8 @@ public:
void SetPlayerSkin(char* skin);
CVector& GetPos();
void Process(void);
void KillPlayer(void);
void ArrestPlayer(void);
};
static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error");

View File

@ -137,11 +137,15 @@ CPlayerSkin::RenderFrontendSkinEdit(void)
{
static float rotation = 0.0f;
RwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };
const RwV3d pos = { 1.35f, 0.35f, 7.725f };
RwV3d pos = { 1.35f, 0.35f, 7.725f };
const RwV3d axis1 = { 1.0f, 0.0f, 0.0f };
const RwV3d axis2 = { 0.0f, 0.0f, 1.0f };
static uint32 LastFlash = 0;
#ifdef ASPECT_RATIO_SCALE
pos.x = 1.35f * (SCREEN_ASPECT_RATIO / DEFAULT_ASPECT_RATIO);
#endif
RwFrame *frame = RpClumpGetFrame(gpPlayerClump);
if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {

View File

@ -9,6 +9,9 @@ int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64;
int32 *CStats::PedsKilledOfThisType = (int32*)0x880DBC;
int32 &CStats::TimesDied = *(int32*)0x8E2BDC;
int32 &CStats::TimesArrested = *(int32*)0x8E2BEC;
int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C;
void CStats::AnotherKillFrenzyPassed()
{

View File

@ -11,7 +11,11 @@ public:
static int32 &PeopleKilledByOthers;
static int32 &HelisDestroyed;
static int32 *PedsKilledOfThisType; //[NUM_PEDTYPES]
static int32 &TimesDied;
static int32 &TimesArrested;
static int32 &KillsSinceLastCheckpoint;
public:
static void AnotherKillFrenzyPassed();
static void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };
};

View File

@ -1021,7 +1021,7 @@ CStreaming::RemoveAllUnusedModels(void)
for(i = 0; i < MAXVEHICLESLOADED; i++)
RemoveLoadedVehicle();
for(i = NUMDEFAULTMODELS; i < MODELINFOSIZE; i++){
for(i = NUM_DEFAULT_MODELS; i < MODELINFOSIZE; i++){
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED &&
ms_aInfoForModel[i].m_flags & STREAMFLAGS_DONT_REMOVE &&
CModelInfo::GetModelInfo(i)->m_refCount == 0){
@ -2405,8 +2405,8 @@ CStreaming::MemoryCardSave(uint8 *buffer, uint32 *length)
{
int i;
*length = NUMDEFAULTMODELS;
for(i = 0; i < NUMDEFAULTMODELS; i++)
*length = NUM_DEFAULT_MODELS;
for(i = 0; i < NUM_DEFAULT_MODELS; i++)
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
buffer[i] = ms_aInfoForModel[i].m_flags;
else
@ -2418,7 +2418,7 @@ CStreaming::MemoryCardLoad(uint8 *buffer, uint32 length)
{
uint32 i;
assert(length == NUMDEFAULTMODELS);
assert(length == NUM_DEFAULT_MODELS);
for(i = 0; i < length; i++)
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
if(buffer[i] != 0xFF)

View File

@ -12,6 +12,8 @@
int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714; // 6
int32 &CWanted::nMaximumWantedLevel = *(int32*)0x5F7718; // 6400
WRAPPER void CWanted::Reset() { EAXJMP(0x4AD790) };
void
CWanted::Initialise()
{

View File

@ -76,6 +76,7 @@ public:
bool AddCrimeToQ(eCrimeType type, int32 id, const CVector &pos, bool reported, bool policeDoesntCare);
void ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesntCare);
void UpdateWantedLevel();
void Reset();
bool IsIgnored(void) { return m_bIgnoredByCops || m_bIgnoredByEveryone; }

View File

@ -41,6 +41,7 @@ bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA;
WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); }
WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); }
WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); }
WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8) { EAXJMP(0x4B4E70) };
void
CWorld::Initialise()

View File

@ -85,6 +85,7 @@ public:
}
}
static void ClearScanCodes(void);
static void ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8);
static bool CameraToIgnoreThisObject(CEntity *ent);

View File

@ -32,7 +32,6 @@ enum Config {
NUMDUMMIES = 2802, // 2368 on PS2
NUMAUDIOSCRIPTOBJECTS = 256,
NUMCUTSCENEOBJECTS = 50,
NUMDEFAULTMODELS = 200,
NUMTEMPOBJECTS = 30,
@ -84,7 +83,9 @@ enum Config {
NUM_PATH_NODES_IN_AUTOPILOT = 8,
NUM_ACCIDENTS = 20,
NUM_FIRES = 40
NUM_FIRES = 40,
NUMPEDROUTES = 200,
};
// We'll use this once we're ready to become independent of the game

View File

@ -199,7 +199,11 @@ Idle(void *arg)
Render2dStuff();
}else{
float viewWindow = DEFAULT_VIEWWINDOW;
#ifdef ASPECT_RATIO_SCALE
CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
#else
CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
#endif
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
@ -234,7 +238,11 @@ FrontendIdle(void)
return;
float viewWindow = DEFAULT_VIEWWINDOW;
#ifdef ASPECT_RATIO_SCALE
CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
#else
CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
#endif
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))

View File

@ -146,7 +146,7 @@ LetThemFollowYou(void) {
CPed *nearPed = player->m_nearPeds[i];
if (nearPed && !nearPed->IsPlayer()) {
nearPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, (void*)player);
nearPed->m_pedFormation = rand() & 7;
nearPed->m_pedFormation = (eFormation)(1 + (rand() & 7));
nearPed->bScriptObjectiveCompleted = false;
}
}
@ -349,7 +349,7 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil);
DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil);
DebugMenuAddCmd("Debug", "Make peds around you follow you", LetThemFollowYou);
DebugMenuAddCmd("Debug", "Make peds follow you in formation", LetThemFollowYou);
#ifndef MASTER
DebugMenuAddVarBool8("Debug", "Toggle unused fight feature", (int8*)&CPed::bUnusedFightThingOnPlayer, nil);
#endif

View File

@ -256,8 +256,8 @@ CMatrix &Invert(const CMatrix &src, CMatrix &dst);
CVector operator*(const CMatrix &mat, const CVector &vec);
CMatrix operator*(const CMatrix &m1, const CMatrix &m2);
CVector MultiplyInverse(const CMatrix &mat, const CVector &vec);
CVector Multiply3x3(const CMatrix &mat, const CVector &vec);
CVector Multiply3x3(const CVector &vec, const CMatrix &mat);
const CVector Multiply3x3(const CMatrix &mat, const CVector &vec);
const CVector Multiply3x3(const CVector &vec, const CMatrix &mat);
inline CMatrix
Invert(const CMatrix &matrix)

View File

@ -136,7 +136,7 @@ MultiplyInverse(const CMatrix &mat, const CVector &vec)
mat.m_matrix.at.x * v.x + mat.m_matrix.at.y * v.y + mat.m_matrix.at.z * v.z);
}
CVector
const CVector
Multiply3x3(const CMatrix &mat, const CVector &vec)
{
return CVector(
@ -145,7 +145,7 @@ Multiply3x3(const CMatrix &mat, const CVector &vec)
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z);
}
CVector
const CVector
Multiply3x3(const CVector &vec, const CMatrix &mat)
{
return CVector(

View File

@ -1,3 +1,5 @@
#pragma once
#define MODELINDICES \
X("fire_hydrant", MI_FIRE_HYDRANT, 0x5F5A00) \
X("bagelstnd02", MI_BAGELSTAND2, 0x5F59FC) \
@ -352,6 +354,8 @@ enum
MI_AIRTRAIN_VLO = 198,
MI_LOPOLYGUY,
NUM_DEFAULT_MODELS
};
enum{

View File

@ -44,26 +44,23 @@
#include "WaterLevel.h"
#include "CarAI.h"
#include "Zones.h"
#include "Cranes.h"
#include "MusicManager.h"
WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); }
WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); }
WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); }
WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); }
WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); }
WRAPPER void CPed::SetRadioStation(void) { EAXJMP(0x4D7BC0); }
WRAPPER void CPed::ProcessBuoyancy(void) { EAXJMP(0x4C7FF0); }
WRAPPER void CPed::ServiceTalking(void) { EAXJMP(0x4E5870); }
WRAPPER void CPed::UpdatePosition(void) { EAXJMP(0x4C7A00); }
WRAPPER void CPed::WanderRange(void) { EAXJMP(0x4D26C0); }
WRAPPER void CPed::WanderPath(void) { EAXJMP(0x4D28D0); }
WRAPPER void CPed::SeekCar(void) { EAXJMP(0x4D3F90); }
WRAPPER void CPed::SeekBoatPosition(void) { EAXJMP(0x4E4C70); }
WRAPPER void CPed::UpdateFromLeader(void) { EAXJMP(0x4D8F30); }
WRAPPER int CPed::ScanForThreats(void) { EAXJMP(0x4C5FE0); }
WRAPPER void CPed::SetEnterCar(CVehicle*, uint32) { EAXJMP(0x4E0920); }
WRAPPER void CPed::SetEnterCar_AllClear(CVehicle*, uint32, uint32) { EAXJMP(0x4E0A40); }
WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); }
WRAPPER void CPed::SetExitCar(CVehicle*, uint32) { EAXJMP(0x4E1010); }
@ -391,7 +388,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_vecOffsetSeek.x = 0.0f;
m_vecOffsetSeek.y = 0.0f;
m_vecOffsetSeek.z = 0.0f;
m_pedFormation = 0;
m_pedFormation = FORMATION_UNDEFINED;
m_collidingThingTimer = 0;
m_nPedStateTimer = 0;
m_actionX = 0;
@ -440,7 +437,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_pLookTarget = nil;
m_fLookDirection = 0.0f;
m_pCurSurface = nil;
m_targetUnused = nil;
m_wanderRangeBounds = nil;
m_nPathNodes = 0;
m_nCurPathNode = 0;
m_nPathState = 0;
@ -2689,7 +2686,7 @@ CPed::SetObjective(eObjective newObj, void *entity)
case OBJECTIVE_FOLLOW_PED_IN_FORMATION:
m_pedInObjective = (CPed*)entity;
m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
m_pedFormation = 1;
m_pedFormation = FORMATION_REAR;
break;
case OBJECTIVE_LEAVE_VEHICLE:
#ifdef VC_PED_PORTS
@ -6325,8 +6322,14 @@ CPed::ExitCar(void)
void
CPed::Fall(void)
{
if (m_getUpTimer != -1 && CTimer::GetTimeInMilliseconds() > m_getUpTimer)
if (m_getUpTimer != -1 && CTimer::GetTimeInMilliseconds() > m_getUpTimer
#ifdef VC_PED_PORTS
&& bIsStanding
#endif
)
ClearFall();
// VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
}
void
@ -7612,28 +7615,28 @@ CPed::GetFormationPosition(void)
CVector formationOffset;
switch (m_pedFormation) {
case 1:
case FORMATION_REAR:
formationOffset = CVector(0.0f, -1.5f, 0.0f);
break;
case 2:
case FORMATION_REAR_LEFT:
formationOffset = CVector(-1.5f, -1.5f, 0.0f);
break;
case 3:
case FORMATION_REAR_RIGHT:
formationOffset = CVector(1.5f, -1.5f, 0.0f);
break;
case 4:
case FORMATION_FRONT_LEFT:
formationOffset = CVector(-1.5f, 1.5f, 0.0f);
break;
case 5:
case FORMATION_FRONT_RIGHT:
formationOffset = CVector(1.5f, 1.5f, 0.0f);
break;
case 6:
case FORMATION_LEFT:
formationOffset = CVector(-1.5f, 0.0f, 0.0f);
break;
case 7:
case FORMATION_RIGHT:
formationOffset = CVector(1.5f, 0.0f, 0.0f);
break;
case 8:
case FORMATION_FRONT:
formationOffset = CVector(0.0f, 1.5f, 0.0f);
break;
default:
@ -7769,7 +7772,7 @@ CPed::GetNextPointOnRoute(void)
int16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;
// Route is complete
if (nextPoint < 0 || nextPoint > 200 || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {
if (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {
switch (m_routeType) {
case PEDROUTE_STOP_WHEN_DONE:
@ -7790,7 +7793,7 @@ CPed::GetNextPointOnRoute(void)
return nextPoint;
}
// TODO: enum
// These categories are purely random, most of ped models have no correlation. So I don't think making an enum.
uint8
CPed::GetPedRadioCategory(uint32 modelIndex)
{
@ -10083,7 +10086,7 @@ CPed::ProcessControl(void)
if (IsPedInControl() && !bIsStanding && !m_pDamageEntity && CheckIfInTheAir()) {
SetInTheAir();
#ifdef VC_PED_PORTS
bKnockedUpIntoAir = true;
bKnockedUpIntoAir = false;
#endif
}
#ifdef VC_PED_PORTS
@ -10416,7 +10419,9 @@ CPed::ProcessControl(void)
ServiceTalking();
if (bInVehicle && !m_pMyVehicle)
bInVehicle = false;
#ifndef VC_PED_PORTS
m_pCurrentPhysSurface = nil;
#endif
} else {
if (bIsStanding && (!m_pCurrentPhysSurface || IsPlayer())
|| bIsInWater || !bUsesCollision) {
@ -11516,9 +11521,8 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
void
CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
{
CPed* ped = (CPed*)arg;
CVehicle* veh = ped->m_pMyVehicle;
CPed *ped = (CPed*)arg;
CTrain *veh = (CTrain*)ped->m_pMyVehicle;
if (!veh)
return;
@ -13538,18 +13542,19 @@ CPed::SetSeekBoatPosition(CVehicle *boat)
void
CPed::SetExitTrain(CVehicle* train)
{
if (m_nPedState != PED_EXIT_TRAIN && train->m_status == STATUS_TRAIN_NOT_MOVING && ((CTrain*)train)->Doors[0].IsFullyOpen()) {
/*
// Not used
CVector exitPos;
GetNearestTrainPedPosition(train, exitPos);
*/
m_nPedState = PED_EXIT_TRAIN;
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
bUsesCollision = false;
LineUpPedWithTrain();
}
if (m_nPedState == PED_EXIT_TRAIN || train->m_status != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
return;
/*
// Not used
CVector exitPos;
GetNearestTrainPedPosition(train, exitPos);
*/
m_nPedState = PED_EXIT_TRAIN;
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
bUsesCollision = false;
LineUpPedWithTrain();
}
#ifdef NEW_WALK_AROUND_ALGORITHM
@ -14386,6 +14391,246 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
return ourCollidedSpheres;
}
void
CPed::SetFormation(eFormation type)
{
// FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7.
// To not change the behaviour, range in here tweaked by 1 with the use of enum.
switch (m_pedFormation) {
case FORMATION_REAR:
case FORMATION_REAR_LEFT:
case FORMATION_REAR_RIGHT:
case FORMATION_FRONT_LEFT:
case FORMATION_FRONT_RIGHT:
case FORMATION_LEFT:
case FORMATION_RIGHT:
case FORMATION_FRONT:
break;
default:
Error("Unknown formation type, PedAI.cpp");
break;
}
m_pedFormation = type;
}
void
CPed::SetFollowRoute(int16 currentPoint, int16 routeType)
{
m_routeLastPoint = currentPoint;
m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
m_routePointsPassed = 0;
m_routeType = routeType;
m_routePointsBeingPassed = 1;
m_objective = OBJECTIVE_FOLLOW_ROUTE;
m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());
}
// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
void
CPed::WanderRange(void)
{
bool arrived = Seek();
if (arrived) {
Idle();
if (((m_randomSeed % 256) + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {
int xDiff = Abs(m_wanderRangeBounds[1].x - m_wanderRangeBounds[0].x);
int yDiff = Abs(m_wanderRangeBounds[1].y - m_wanderRangeBounds[0].y);
CVector newCoords(
(CGeneral::GetRandomNumber() % xDiff) + m_wanderRangeBounds[0].x,
(CGeneral::GetRandomNumber() % yDiff) + m_wanderRangeBounds[0].y,
GetPosition().z);
SetSeek(newCoords, 2.5f);
}
}
}
bool
CPed::WillChat(CPed *stranger)
{
if (m_pNextPathNode && m_pLastPathNode) {
if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {
return false;
}
}
if (m_nSurfaceTouched == SURFACE_TARMAC)
return false;
if (this == stranger)
return false;
if (m_nPedType == stranger->m_nPedType)
return true;
if (m_nPedType == PEDTYPE_CRIMINAL)
return false;
if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)
return false;
return true;
}
void
CPed::SetEnterTrain(CVehicle *train, uint32 unused)
{
if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
return;
/*
// Not used
CVector enterPos;
GetNearestTrainPedPosition(train, enterPos);
*/
m_fRotationCur = train->GetForward().Heading() - HALFPI;
m_pMyVehicle = train;
m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
m_nPedState = PED_ENTER_TRAIN;
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
bUsesCollision = false;
LineUpPedWithTrain();
if (IsPlayer()) {
if (((CPlayerPed*)this)->m_bAdrenalineActive)
((CPlayerPed*)this)->ClearAdrenaline();
}
}
void
CPed::SetDuck(uint32 time)
{
if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
return;
if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) {
CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f);
bIsDucking = true;
m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
}
} else {
CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
bIsDucking = true;
m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
}
}
}
void
CPed::SeekBoatPosition(void)
{
if (m_carInObjective && !m_carInObjective->pDriver) {
CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();
CVector enterOffset;
if (boatModel->m_vehicleType == VEHICLE_TYPE_BOAT)
enterOffset = boatModel->m_positions[BOAT_POS_FRONTSEAT];
else
enterOffset = boatModel->m_positions[CAR_POS_FRONTSEAT];
enterOffset.x = 0.0f;
CMatrix boatMat(m_carInObjective->GetMatrix());
SetMoveState(PEDMOVE_WALK);
m_vecSeekPos = boatMat * enterOffset;
if (Seek()) {
// We arrived to the boat
m_vehEnterType = 0;
SetEnterCar(m_carInObjective, 0);
}
} else
RestorePreviousState();
}
void
CPed::SetEnterCar(CVehicle *car, uint32 unused)
{
if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
RestorePreviousState();
RestorePreviousObjective();
} else {
uint8 doorFlag;
eDoors door;
switch (m_vehEnterType) {
case CAR_DOOR_RF:
doorFlag = CAR_DOOR_FLAG_RF;
door = DOOR_FRONT_RIGHT;
break;
case CAR_DOOR_RR:
doorFlag = CAR_DOOR_FLAG_RR;
door = DOOR_REAR_RIGHT;
break;
case CAR_DOOR_LF:
doorFlag = CAR_DOOR_FLAG_LF;
door = DOOR_FRONT_LEFT;
break;
case CAR_DOOR_LR:
doorFlag = CAR_DOOR_FLAG_LR;
door = DOOR_REAR_LEFT;
break;
default:
doorFlag = CAR_DOOR_FLAG_UNKNOWN;
break;
}
if (!IsPedInControl() || m_fHealth <= 0.0f
|| doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
|| car->m_veh_flagC10 || m_pVehicleAnim
|| doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
SetMoveState(PEDMOVE_STILL);
else
SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
}
}
void
CPed::SetRadioStation(void)
{
uint8 radiosPerRadioCategories[10][4] = {
{JAH_RADIO, RISE_FM, GAME_FM, MSX_FM},
{HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
{RISE_FM, GAME_FM, MSX_FM, FLASHBACK},
{HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM},
{HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK},
{JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK},
{HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK},
{HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK},
{HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
{CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM}
};
uint8 orderInCat;
if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)
return;
uint8 category = GetPedRadioCategory(m_modelIndex);
if (DMAudio.IsMP3RadioChannelAvailable()) {
if (CGeneral::GetRandomNumber() & 15) {
for (orderInCat = 0; orderInCat < 4; orderInCat++) {
if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
break;
}
} else {
m_pMyVehicle->m_nRadioStation = USERTRACK;
}
} else {
for (orderInCat = 0; orderInCat < 4; orderInCat++) {
if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
break;
}
}
if (orderInCat == 4) {
if (DMAudio.IsMP3RadioChannelAvailable()) {
if (CGeneral::GetRandomNumber() & 15)
m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
else
m_pMyVehicle->m_nRadioStation = USERTRACK;
} else {
m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
}
}
}
class CPed_ : public CPed
{
public:
@ -14589,4 +14834,10 @@ STARTPATCHES
InjectHook(0x4D6A00, &CPed::PossiblyFindBetterPosToSeekCar, PATCH_JUMP);
InjectHook(0x4D94E0, &CPed::ProcessObjective, PATCH_JUMP);
InjectHook(0x4CCEB0, &CPed::SetDirectionToWalkAroundObject, PATCH_JUMP);
InjectHook(0x4DF3E0, &CPed::SetFormation, PATCH_JUMP);
InjectHook(0x4C7340, &CPed::WillChat, PATCH_JUMP);
InjectHook(0x4E32D0, &CPed::SetEnterTrain, PATCH_JUMP);
InjectHook(0x4E4920, &CPed::SetDuck, PATCH_JUMP);
InjectHook(0x4E0920, &CPed::SetEnterCar, PATCH_JUMP);
InjectHook(0x4D7BC0, &CPed::SetRadioStation, PATCH_JUMP);
ENDPATCHES

View File

@ -24,6 +24,19 @@ struct CPedAudioData
int m_nMaxRandomDelayTime;
};
enum eFormation
{
FORMATION_UNDEFINED,
FORMATION_REAR,
FORMATION_REAR_LEFT,
FORMATION_REAR_RIGHT,
FORMATION_FRONT_LEFT,
FORMATION_FRONT_RIGHT,
FORMATION_LEFT,
FORMATION_RIGHT,
FORMATION_FRONT
};
enum FightState : int8 {
FIGHTSTATE_MOVE_FINISHED = -2,
FIGHTSTATE_JUST_ATTACKED,
@ -360,7 +373,7 @@ public:
CVehicle *m_carInObjective;
CVector m_nextRoutePointPos;
CPed *m_leader;
uint32 m_pedFormation;
eFormation m_pedFormation;
uint32 m_fearFlags;
CEntity *m_threatEntity;
CVector2D m_eventOrThreat;
@ -398,7 +411,7 @@ public:
int16 m_routeLastPoint;
uint16 m_routeStartPoint;
int16 m_routePointsPassed;
int16 m_routeType;
int16 m_routeType; // See PedRouteType
int16 m_routePointsBeingPassed;
uint16 field_2D2;
CVector2D m_moved;
@ -434,7 +447,7 @@ public:
uint8 m_stateUnused;
uint8 pad_351[3];
uint32 m_timerUnused;
CEntity *m_targetUnused;
CVector2D *m_wanderRangeBounds; // array with 2 CVector2D (actually unused CRange2D class) - unused
CWeapon m_weapons[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS];
eWeaponType m_storedWeapon;
uint8 m_currentWeapon; // eWeaponType
@ -542,7 +555,6 @@ public:
void SetObjective(eObjective, int16, int16);
void ClearChat(void);
void InformMyGangOfAttack(CEntity*);
void SetFollowRoute(int16, int16);
void ReactToAttack(CEntity*);
void SetDuck(uint32);
void RegisterThreatWithGangPeds(CEntity*);
@ -647,11 +659,9 @@ public:
void ServiceTalking(void);
void SetJump(void);
void UpdatePosition(void);
void WanderRange(void);
void WanderPath(void);
void ReactToPointGun(CEntity*);
void SeekCar(void);
void SeekBoatPosition(void);
bool PositionPedOutOfCollision(void);
bool RunToReportCrime(eCrimeType);
bool PlacePedOnDryLand(void);
@ -661,6 +671,10 @@ public:
void SetEnterCar(CVehicle*, uint32);
bool WarpPedToNearEntityOffScreen(CEntity*);
void SetExitCar(CVehicle*, uint32);
void SetFormation(eFormation);
bool WillChat(CPed*);
void SetEnterTrain(CVehicle*, uint32);
void SetEnterCar_AllClear(CVehicle*, uint32, uint32);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@ -733,6 +747,9 @@ public:
void SetSeekCar(CVehicle*, uint32);
void SetSeekBoatPosition(CVehicle*);
void SetExitTrain(CVehicle*);
void WanderRange(void);
void SetFollowRoute(int16, int16);
void SeekBoatPosition(void);
#ifdef VC_PED_PORTS
bool CanPedJumpThis(CEntity*, CVector*);
#else

View File

@ -3,5 +3,27 @@
#include "main.h"
#include "PedRoutes.h"
WRAPPER int16 CRouteNode::GetRouteThisPointIsOn(int16) { EAXJMP(0x4EE7A0); }
WRAPPER CVector CRouteNode::GetPointPosition(int16) { EAXJMP(0x4EE780); }
CRouteNode (&gaRoutes)[NUMPEDROUTES] = *(CRouteNode(*)[NUMPEDROUTES]) * (uintptr*)0x62E090;
int16
CRouteNode::GetRouteThisPointIsOn(int16 point)
{
return gaRoutes[point].m_route;
}
// Actually GetFirstPointOfRoute
int16
CRouteNode::GetRouteStart(int16 route)
{
for (int i = 0; i < NUMPEDROUTES; i++) {
if (route == gaRoutes[i].m_route)
return i;
}
return -1;
}
CVector
CRouteNode::GetPointPosition(int16 point)
{
return gaRoutes[point].m_pos;
}

View File

@ -3,6 +3,10 @@
class CRouteNode
{
public:
int16 m_route;
CVector m_pos;
static int16 GetRouteThisPointIsOn(int16);
static CVector GetPointPosition(int16);
static int16 GetRouteStart(int16);
};

View File

@ -4,6 +4,7 @@
#include "Camera.h"
#include "WeaponEffects.h"
#include "ModelIndices.h"
#include "World.h"
CPlayerPed::~CPlayerPed()
{
@ -103,6 +104,15 @@ CPlayerPed::ClearAdrenaline(void)
}
}
CPlayerInfo *
CPlayerPed::GetPlayerInfoForThisPlayerPed()
{
if (CWorld::Players[0].m_pPed == this)
return &CWorld::Players[0];
return nil;
}
class CPlayerPed_ : public CPlayerPed
{
public:
@ -115,4 +125,5 @@ STARTPATCHES
InjectHook(0x4EFB30, &CPlayerPed_::dtor, PATCH_JUMP);
InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP);
InjectHook(0x4F3700, &CPlayerPed::AnnoyPlayerPed, PATCH_JUMP);
InjectHook(0x4F36C0, &CPlayerPed::GetPlayerInfoForThisPlayerPed, PATCH_JUMP);
ENDPATCHES

View File

@ -53,6 +53,7 @@ public:
void SetMoveAnim(void);
void ProcessControl(void);
void ClearAdrenaline(void);
class CPlayerInfo *GetPlayerInfoForThisPlayerPed();
static void SetupPlayerPed(int32);
static void DeactivatePlayerPed(int32);

View File

@ -227,7 +227,6 @@ CCoronas::UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, flo
static RwIm2DVertex vertexbufferX[2];
// TODO? not sure streaks look quite right...
void
CCoronas::Render(void)
{
@ -394,12 +393,15 @@ CCoronas::Render(void)
if(!aCoronas[i].hasValue[j] || !aCoronas[i].hasValue[j+1])
continue;
int mod1 = (float)(6 - j) / 6 * 128;
int mod2 = (float)(6 - (j+1)) / 6 * 128;
RwIm2DVertexSetScreenX(&vertexbufferX[0], aCoronas[i].prevX[j]);
RwIm2DVertexSetScreenY(&vertexbufferX[0], aCoronas[i].prevY[j]);
RwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j], aCoronas[i].prevGreen[j], aCoronas[i].prevBlue[j], 255);
RwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j] * mod1 / 256, aCoronas[i].prevGreen[j] * mod1 / 256, aCoronas[i].prevBlue[j] * mod1 / 256, 255);
RwIm2DVertexSetScreenX(&vertexbufferX[1], aCoronas[i].prevX[j+1]);
RwIm2DVertexSetScreenY(&vertexbufferX[1], aCoronas[i].prevY[j+1]);
RwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1], aCoronas[i].prevGreen[j+1], aCoronas[i].prevBlue[j+1], 255);
RwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1] * mod2 / 256, aCoronas[i].prevGreen[j+1] * mod2 / 256, aCoronas[i].prevBlue[j+1] * mod2 / 256, 255);
// BUG: game doesn't do this
RwIm2DVertexSetScreenZ(&vertexbufferX[0], RwIm2DGetNearScreenZ());

View File

@ -107,14 +107,9 @@ WRAPPER void CHud::Draw(void) { EAXJMP(0x5052A0); }
#else
void CHud::Draw()
{
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSMIRROR);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
// disable hud via second controller
if (CPad::GetPad(1)->GetStartJustDown())
m_Wants_To_Draw_Hud = !m_Wants_To_Draw_Hud;
if (CReplay::IsPlayingBack())
return;
@ -134,7 +129,7 @@ void CHud::Draw()
/*
Draw Crosshairs
*/
if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == 40) {
if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_FIRSTPERSONPEDONPC_40) {
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed) {
int32 State = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_nPedState;
if (State != PED_ENTER_CAR && State != PED_CARJACK) {
@ -272,19 +267,6 @@ void CHud::Draw()
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint);
/*
DrawClock
*/
sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes());
AsciiToUnicode(sTemp, sPrint);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f - 2.0f), SCREEN_SCALE_Y(22.0f + 2.0f), sPrint);
CFont::SetColor(CRGBA(194, 165, 120, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint);
/*
DrawAmmo
*/
@ -519,19 +501,19 @@ void CHud::Draw()
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f - 1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f - 1.0f), m_ZoneToPrint);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint);
CFont::SetColor(CRGBA(152, 154, 82, fZoneAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint);
}
}
}
else {
/*else {
m_pLastZoneName = nil;
m_ZoneState = 0;
m_ZoneFadeTimer = 0;
m_ZoneNameTimer = 0;
}
}*/
/*
DrawVehicleName
@ -615,7 +597,7 @@ void CHud::Draw()
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f - 1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f - 1.0f), m_pVehicleNameToPrint);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint);
CFont::SetColor(CRGBA(194, 165, 120, fVehicleAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint);
@ -629,27 +611,41 @@ void CHud::Draw()
m_VehicleNameTimer = 0;
}
/*
DrawClock
*/
CFont::SetJustifyOff();
CFont::SetCentreOff();
CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::SetBackGroundOnlyTextOff();
CFont::SetPropOff();
CFont::SetFontStyle(FONT_HEADING);
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0);
sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes());
AsciiToUnicode(sTemp, sPrint);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), sPrint);
CFont::SetColor(CRGBA(194, 165, 120, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint);
/*
DrawOnScreenTimer
*/
wchar sTimer[16];
CFont::SetPropOn();
CFont::SetBackgroundOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetAlignment(ALIGN_RIGHT);
CFont::SetRightJustifyWrap(-SCREEN_WIDTH);
CFont::SetFontStyle(FONT_HEADING);
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed)
TimerOnLastFrame = 0;
if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed)
CounterOnLastFrame = 0;
float AlignToHUD = SCREEN_SCALE_X(-12.0f);
if (CUserDisplay::OnscnTimer.m_bProcessed == 1) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed == 1) {
if (CUserDisplay::OnscnTimer.m_bProcessed) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) {
if (!TimerOnLastFrame)
TimerFlashTimer = 1;
@ -662,22 +658,32 @@ void CHud::Draw()
if (CTimer::GetFrameCounter() & 4 || !TimerFlashTimer) {
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer);
CFont::SetPropOn();
CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetFontStyle(FONT_HEADING);
CFont::SetPropOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(25.0f) + AlignToHUD, SCREEN_SCALE_Y(112.0f), sTimer);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer);
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::SetColor(CRGBA(186, 101, 50, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + AlignToHUD, SCREEN_SCALE_Y(110.0f), sTimer);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f), SCREEN_SCALE_Y(110.0f), sTimer);
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) {
CFont::SetPropOn();
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(105.0f) + AlignToHUD, SCREEN_SCALE_Y(112.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText));
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(80.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText));
CFont::SetColor(CRGBA(186, 101, 50, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(107.0f) + AlignToHUD, SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText));
}
}
}
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed == 1) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) {
if (!CounterOnLastFrame)
CounterFlashTimer = 1;
@ -690,25 +696,38 @@ void CHud::Draw()
if (CTimer::GetFrameCounter() & 4 || !CounterFlashTimer) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_nType) {
CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(73.0f) + AlignToHUD, SCREEN_SCALE_Y(140.0f), SCREEN_SCALE_FROM_RIGHT(23.0f) + AlignToHUD, SCREEN_SCALE_Y(151.0f)), CRGBA(0, 106, 164, 80));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(73.0f) + AlignToHUD, SCREEN_SCALE_Y(140.0f), SCREEN_SCALE_FROM_RIGHT((-atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer) * 0.5f) + 73.0f) + AlignToHUD, SCREEN_SCALE_Y(151.0f)), CRGBA(0, 106, 164, 255));
}
else {
CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_FROM_RIGHT(27.0f) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 80));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_X(atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer)) / 2 + SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 255));
} else {
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer, sTimer);
CFont::SetPropOn();
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(25.0f) + AlignToHUD, SCREEN_SCALE_Y(134.0f), sTimer);
CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::SetCentreOff();
CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetFontStyle(FONT_HEADING);
CFont::SetColor(CRGBA(244, 20, 20, 255));
CFont::SetWrapx(SCREEN_SCALE_X(640.0f));
CFont::SetPropOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 106, 164, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + AlignToHUD, SCREEN_SCALE_Y(132.0f), sTimer);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), sTimer);
CFont::SetColor(CRGBA(0, 106, 164, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f), SCREEN_SCALE_Y(132.0f), sTimer);
}
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) {
CFont::SetPropOn();
CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(86.0f) + AlignToHUD, SCREEN_SCALE_Y(134.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
CFont::SetColor(CRGBA(0, 106, 164, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(88.0f) + AlignToHUD, SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText));
}
}
}
@ -1113,10 +1132,10 @@ void CHud::DrawAfterFade()
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::SetFontStyle(FONT_BANK);
CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[3]);
CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]);
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]);
CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]);
}
// Oddjob result

View File

@ -1933,13 +1933,15 @@ CAutomobile::Render(void)
CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));
CVector rearWheelFwd = GetForward();
for(i = 0; i < 4; i++){
contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
contactSpeeds[i] = GetSpeed(contactPoints[i]);
if(i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
else
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
m_aWheelRotation[i] += m_aWheelSpeed[i];
if (m_aWheelTimer[i] > 0.0f) {
contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
contactSpeeds[i] = GetSpeed(contactPoints[i]);
if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
else
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
m_aWheelRotation[i] += m_aWheelSpeed[i];
}
}
// Rear right wheel