Merge branch 'miami' of https://github.com/GTAmodding/re3 into miami

This commit is contained in:
eray orçunus 2020-05-19 17:46:18 +03:00
commit 99574ebfc6
46 changed files with 1814 additions and 578 deletions

View File

@ -104,7 +104,7 @@ strcmpIgnoringDigits(const char *s1, const char *s2)
c2 = toupper(c2); c2 = toupper(c2);
#endif #endif
if(c1 != c2) if(c1 && c2 && c1 != c2)
return false; return false;
} }
} }

View File

@ -926,7 +926,7 @@ const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_
{ "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs }, { "grenade", "grenade", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs },
{ "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs }, { "flame", "flame", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs },
{ "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs }, { "medic", "medic", MI_COP, awc(aMedicAnimations), aMedicAnimDescs },
{ "sunbathe", "sunbathe", MI_COP, awc(aSunbatheAnimations), aSunbatheAnimDescs }, { "sunbathe", "sunbathe", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs }, // NB: not using awc here!
{ "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs }, { "playidles", "playidles", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs },
{ "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs }, { "riot", "riot", MI_COP, awc(aRiotAnimations), aRiotAnimDescs },
{ "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs }, { "strip", "strip", MI_COP, awc(aStripAnimations), aStripAnimDescs },

View File

@ -358,7 +358,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle); pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);
pVehicle->SetStatus(STATUS_PHYSICS); pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nCarMission = pVehicle->AutoPilot.m_nCarMission =
pVehicle->GetVehicleAppearance() == VEHICLE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel(); pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel();
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
}else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){ }else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){
@ -432,7 +432,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->bIsLawEnforcer) { if (pVehicle->bIsLawEnforcer) {
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||
pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) { pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {
if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)
pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY; pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;
} }
} }
@ -489,16 +489,16 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) { if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) {
if (!FindPlayerVehicle() || if (!FindPlayerVehicle() ||
FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_CAR || FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) { FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
if (pVehicle->GetVehicleAppearance() == VEHICLE_BOAT) { if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
} }
} }
else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BOAT) { else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
if (pVehicle->GetVehicleAppearance() == VEHICLE_CAR || if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
pVehicle->GetVehicleAppearance() == VEHICLE_BIKE) { pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
} }

View File

@ -655,10 +655,10 @@ CCarCtrl::GenerateOneRandomCar()
} }
int nMadDrivers; int nMadDrivers;
switch (pVehicle->GetVehicleAppearance()) { switch (pVehicle->GetVehicleAppearance()) {
case VEHICLE_BIKE: case VEHICLE_APPEARANCE_BIKE:
nMadDrivers = 30; nMadDrivers = 30;
break; break;
case VEHICLE_BOAT: case VEHICLE_APPEARANCE_BOAT:
nMadDrivers = 40; nMadDrivers = 40;
break; break;
default: default:

View File

@ -960,7 +960,7 @@ void CGarage::Update()
if (m_pDoor1) { if (m_pDoor1) {
if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) && if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) &&
CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) { CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) {
if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_PLANE) { if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE) {
CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage. CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds(); CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
} }

View File

@ -172,12 +172,12 @@ CPickup::GiveUsAPickUpObject(int32 handle)
} }
bool bool
CPickup::CanBePickedUp(CPlayerPed *player) CPickup::CanBePickedUp(CPlayerPed *player, int playerId)
{ {
assert(m_pObject != nil); assert(m_pObject != nil);
bool cannotBePickedUp = bool cannotBePickedUp =
(m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f) (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.5f)
|| (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.5f)
|| (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0) || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
|| (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame)); || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
return !cannotBePickedUp; return !cannotBePickedUp;
@ -233,7 +233,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
} }
// if we didn't then we've got nothing to do // if we didn't then we've got nothing to do
if (isPickupTouched && CanBePickedUp(player)) { if (isPickupTouched && CanBePickedUp(player, playerId)) {
CPad::GetPad(0)->StartShake(120, 100); CPad::GetPad(0)->StartShake(120, 100);
switch (m_eType) switch (m_eType)
{ {
@ -497,14 +497,14 @@ CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
return true; return true;
} else if (modelIndex == MI_PICKUP_BODYARMOUR) { } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
player->m_fArmour = 100.0f; player->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
return true; return true;
} else if (modelIndex == MI_PICKUP_INFO) { } else if (modelIndex == MI_PICKUP_INFO) {
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
return true; return true;
} else if (modelIndex == MI_PICKUP_HEALTH) { } else if (modelIndex == MI_PICKUP_HEALTH) {
player->m_fHealth = 100.0f; player->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
return true; return true;
} else if (modelIndex == MI_PICKUP_BONUS) { } else if (modelIndex == MI_PICKUP_BONUS) {

View File

@ -46,7 +46,7 @@ public:
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private: private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player); inline bool CanBePickedUp(CPlayerPed *player, int playerId);
void RemoveKeepType(); void RemoveKeepType();
void Remove(); void Remove();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -221,19 +221,17 @@ enum {
}; };
enum { enum {
SIZE_MAIN_SCRIPT = 128 * 1024, SIZE_MAIN_SCRIPT = 225512,
SIZE_MISSION_SCRIPT = 32 * 1024, SIZE_MISSION_SCRIPT = 35000,
SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT
}; };
enum { enum {
MAX_NUM_SCRIPTS = 128, MAX_NUM_SCRIPTS = 128,
MAX_NUM_CONTACTS = 16,
MAX_NUM_INTRO_TEXT_LINES = 2, MAX_NUM_INTRO_TEXT_LINES = 2,
MAX_NUM_INTRO_RECTANGLES = 16, MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16, MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16, MAX_NUM_SCRIPT_SPHERES = 16,
MAX_NUM_COLLECTIVES = 32,
MAX_NUM_USED_OBJECTS = 200, MAX_NUM_USED_OBJECTS = 200,
MAX_NUM_MISSION_SCRIPTS = 120, MAX_NUM_MISSION_SCRIPTS = 120,
MAX_NUM_BUILDING_SWAPS = 25, MAX_NUM_BUILDING_SWAPS = 25,
@ -245,13 +243,10 @@ class CTheScripts
{ {
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE]; static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS]; static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS];
static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES]; static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES];
static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS]; static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];
static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@ -275,14 +270,17 @@ class CTheScripts
static uint32 LargestMissionScriptSize; static uint32 LargestMissionScriptSize;
static uint32 MainScriptSize; static uint32 MainScriptSize;
static uint8 FailCurrentMission; static uint8 FailCurrentMission;
static uint8 CountdownToMakePlayerUnsafe;
static uint8 DelayMakingPlayerUnsafeThisTime;
static uint16 NumScriptDebugLines; static uint16 NumScriptDebugLines;
static uint16 NumberOfIntroRectanglesThisFrame; static uint16 NumberOfIntroRectanglesThisFrame;
static uint16 NumberOfIntroTextLinesThisFrame; static uint16 NumberOfIntroTextLinesThisFrame;
static uint8 UseTextCommands; static uint8 UseTextCommands;
static uint16 CommandsExecuted; static uint16 CommandsExecuted;
static uint16 ScriptsUpdated; static uint16 ScriptsUpdated;
static uint8 RiotIntensity;
static uint32 LastMissionPassedTime;
static uint16 NumberOfExclusiveMissionScripts;
static bool bPlayerIsInTheStatium;
static bool bPlayerHasMetDebbieHarry;
public: public:
static void Init(); static void Init();
@ -306,9 +304,6 @@ public:
static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; } static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }
static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; }
static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; }
static int32 Read4BytesFromScript(uint32* pIp) { static int32 Read4BytesFromScript(uint32* pIp) {
int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp]; int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 4; *pIp += 4;
@ -371,6 +366,7 @@ private:
static int32 AddScriptSphere(int32 id, CVector pos, float radius); static int32 AddScriptSphere(int32 id, CVector pos, float radius);
static int32 GetNewUniqueScriptSphereIndex(int32 index); static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index); static void RemoveScriptSphere(int32 index);
static void RemoveScriptTextureDictionary();
friend class CRunningScript; friend class CRunningScript;
friend class CHud; friend class CHud;
@ -414,6 +410,7 @@ class CRunningScript
uint32 m_anStack[MAX_STACK_DEPTH]; uint32 m_anStack[MAX_STACK_DEPTH];
uint16 m_nStackPointer; uint16 m_nStackPointer;
int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS]; int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];
bool m_bIsActive;
bool m_bCondResult; bool m_bCondResult;
bool m_bIsMissionScript; bool m_bIsMissionScript;
bool m_bSkipWakeTime; bool m_bSkipWakeTime;
@ -507,4 +504,6 @@ private:
return false; return false;
} }
} }
static bool ThisIsAValidRandomCop(int32 mi, bool cop, bool swat, bool fbi, bool army, bool miami);
}; };

View File

@ -61,6 +61,8 @@ enum
CCamera TheCamera; CCamera TheCamera;
bool CCamera::m_bUseMouse3rdPerson = true; bool CCamera::m_bUseMouse3rdPerson = true;
bool bDidWeProcessAnyCinemaCam; bool bDidWeProcessAnyCinemaCam;
float CCamera::m_f3rdPersonCHairMultX;
float CCamera::m_f3rdPersonCHairMultY;
#ifdef IMPROVED_CAMERA #ifdef IMPROVED_CAMERA
#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) #define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)

View File

@ -472,8 +472,8 @@ public:
// not static yet // not static yet
float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
float m_f3rdPersonCHairMultX; static float m_f3rdPersonCHairMultX;
float m_f3rdPersonCHairMultY; static float m_f3rdPersonCHairMultY;
CCam Cams[3]; CCam Cams[3];

View File

@ -1,4 +1,5 @@
#include "common.h" #include "common.h"
#include <ctype.h>
#include "main.h" #include "main.h"
#include "Quaternion.h" #include "Quaternion.h"
@ -26,6 +27,9 @@
#include "FileLoader.h" #include "FileLoader.h"
#include "Streaming.h" #include "Streaming.h"
#include "ColStore.h" #include "ColStore.h"
#include "Occlusion.h"
//--MIAMI: file done
char CFileLoader::ms_line[256]; char CFileLoader::ms_line[256];
@ -159,7 +163,6 @@ struct ColHeader
uint32 size; uint32 size;
}; };
//--MIAMI: done
void void
CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot)
{ {
@ -196,7 +199,6 @@ CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot)
} }
//--MIAMI: done
bool bool
CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot) CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot)
{ {
@ -298,13 +300,15 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numLines = *(int16*)buf; model.numLines = *(int16*)buf;
buf += 4; buf += 4;
if(model.numLines > 0){ if(model.numLines > 0){
model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine)); //model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));
for(i = 0; i < model.numLines; i++){ for(i = 0; i < model.numLines; i++){
model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12)); //model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));
buf += 24; buf += 24;
} }
}else }else
model.lines = nil; model.lines = nil;
model.numLines = 0;
model.lines = nil;
model.numBoxes = *(int16*)buf; model.numBoxes = *(int16*)buf;
buf += 4; buf += 4;
@ -323,10 +327,12 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector)); model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector));
for(i = 0; i < numVertices; i++){ for(i = 0; i < numVertices; i++){
model.vertices[i] = *(CVector*)buf; model.vertices[i] = *(CVector*)buf;
#if 0
if(Abs(model.vertices[i].x) >= 256.0f || if(Abs(model.vertices[i].x) >= 256.0f ||
Abs(model.vertices[i].y) >= 256.0f || Abs(model.vertices[i].y) >= 256.0f ||
Abs(model.vertices[i].z) >= 256.0f) Abs(model.vertices[i].z) >= 256.0f)
printf("%s:Collision volume too big\n", modelname); printf("%s:Collision volume too big\n", modelname);
#endif
buf += 12; buf += 12;
} }
}else }else
@ -349,7 +355,7 @@ GetNameAndLOD(char *nodename, char *name, int *n)
{ {
char *underscore = nil; char *underscore = nil;
for(char *s = nodename; *s != '\0'; s++){ for(char *s = nodename; *s != '\0'; s++){
if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L')) if(s[0] == '_' && (s[1] == 'l' || s[1] == 'L') && isdigit(s[2]))
underscore = s; underscore = s;
} }
if(underscore){ if(underscore){
@ -1093,7 +1099,7 @@ CFileLoader::LoadScene(const char *filename)
LoadCullZone(line); LoadCullZone(line);
break; break;
case OCCL: case OCCL:
// TODO(MIAMI): occlusion LoadOcclusionVolume(line);
break; break;
case PICK: case PICK:
// unused // unused
@ -1187,7 +1193,9 @@ CFileLoader::LoadObjectInstance(const char *line)
CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect()); CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect());
}else }else
entity->bUsesCollision = false; entity->bUsesCollision = false;
// TODO(MIAMI): set some flag here if col min is below 6
if(entity->GetPosition().z + col->boundingBox.min.z < 6.0f)
entity->bUnderwater = true;
}else{ }else{
entity = new CDummyObject; entity = new CDummyObject;
entity->SetModelIndexNoCreate(id); entity->SetModelIndexNoCreate(id);
@ -1241,6 +1249,21 @@ CFileLoader::LoadPickup(const char *line)
sscanf(line, "%d %f %f %f", &id, &x, &y, &z); sscanf(line, "%d %f %f %f", &id, &x, &y, &z);
} }
void
CFileLoader::LoadOcclusionVolume(const char *line)
{
float x, y, z;
float width, length, height;
float angle;
sscanf(line, "%f %f %f %f %f %f %f",
&x, &y, &z,
&width, &length, &height,
&angle);
COcclusion::AddOne(x, y, z, width, length, z + height/2.0f, angle);
}
//--MIAMI: unused //--MIAMI: unused
void void
CFileLoader::ReloadPaths(const char *filename) CFileLoader::ReloadPaths(const char *filename)

View File

@ -39,6 +39,7 @@ public:
static void LoadZone(const char *line); static void LoadZone(const char *line);
static void LoadCullZone(const char *line); static void LoadCullZone(const char *line);
static void LoadPickup(const char *line); static void LoadPickup(const char *line);
static void LoadOcclusionVolume(const char *line);
static void ReloadPaths(const char *filename); static void ReloadPaths(const char *filename);
static void ReloadObjectTypes(const char *filename); static void ReloadObjectTypes(const char *filename);

View File

@ -37,6 +37,18 @@
#include "Messages.h" #include "Messages.h"
#include "FileLoader.h" #include "FileLoader.h"
// Similar story to Hud.cpp:
// Game has colors inlined in code.
// For easier modification we collect them here:
CRGBA LABEL_COLOR(255, 150, 225, 255);
CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255);
CRGBA MENUOPTION_COLOR(255, 150, 225, 255);
CRGBA SELECTEDMENUOPTION_COLOR(255, 150, 225, 255);
CRGBA HEADER_COLOR(255, 150, 255, 255);
CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255);
CRGBA SLIDERON_COLOR(97, 194, 247, 255);
CRGBA SLIDEROFF_COLOR(27, 89, 130, 255);
#define TIDY_UP_PBP // ProcessButtonPresses #define TIDY_UP_PBP // ProcessButtonPresses
#define MAX_VISIBLE_LIST_ROW 30 #define MAX_VISIBLE_LIST_ROW 30
#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result #define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result
@ -149,53 +161,7 @@ bool CMenuManager::m_PrefsMarketing = false;
bool CMenuManager::m_PrefsDisableTutorials = false; bool CMenuManager::m_PrefsDisableTutorials = false;
#endif // !MASTER #endif // !MASTER
// 0x5F311C /*
const char* FrontendFilenames[][2] = {
{"fe2_mainpanel_ul", "" },
{"fe2_mainpanel_ur", "" },
{"fe2_mainpanel_dl", "" },
{"fe2_mainpanel_dr", "" },
{"fe2_mainpanel_dr2", "" },
{"fe2_tabactive", "" },
{"fe_iconbrief", "" },
{"fe_iconstats", "" },
{"fe_iconcontrols", "" },
{"fe_iconsave", "" },
{"fe_iconaudio", "" },
{"fe_icondisplay", "" },
{"fe_iconlanguage", "" },
{"fe_controller", "" },
{"fe_controllersh", "" },
{"fe_arrows1", "" },
{"fe_arrows2", "" },
{"fe_arrows3", "" },
{"fe_arrows4", "" },
{"fe_radio1", "" },
{"fe_radio2", "" },
{"fe_radio3", "" },
{"fe_radio4", "" },
{"fe_radio5", "" },
{"fe_radio6", "" },
{"fe_radio7", "" },
{"fe_radio8", "" },
{"fe_radio9", "" },
};
#ifdef MENU_MAP
const char* MapFilenames[][2] = {
{"mapMid01", "mapMid01A"},
{"mapMid02", "mapMid02A"},
{"mapMid03", "mapMid03A"},
{"mapBot01", "mapBot01A"},
{"mapBot02", "mapBot02A"},
{"mapBot03", "mapBot03A"},
{"mapTop01", "mapTop01A"},
{"mapTop02", "mapTop02A"},
{"mapTop03", "mapTop03A"},
};
CSprite2d CMenuManager::m_aMapSprites[NUM_MAP_SPRITES];
#endif
// 0x5F3344 // 0x5F3344
const char* MenuFilenames[][2] = { const char* MenuFilenames[][2] = {
{"connection24", ""}, {"connection24", ""},
@ -219,6 +185,37 @@ const char* MenuFilenames[][2] = {
{"gta3logo256", "gta3logo256m"}, {"gta3logo256", "gta3logo256m"},
{ nil, nil } { nil, nil }
}; };
*/
// 0x68C144
const char* FrontendFilenames[][2] = {
{"background", ""},
{"vc_logo", "vc_logom"},
{"mouse", "mousea"},
{"mapTop01", "mapTop01A"},
{"mapTop02", "mapTop02A"},
{"mapTop03", "mapTop03A"},
{"mapMid01", "mapMid01A"},
{"mapMid02", "mapMid02A"},
{"mapMid03", "mapMid03A"},
{"mapBot01", "mapBot01A"},
{"mapBot02", "mapBot02A"},
{"mapBot03", "mapBot03A"},
{"wildstyle", "wildstyleA"},
{"flash", "flashA"},
{"kchat", "kchatA"},
{"fever", "feverA"},
{"vrock", "vrockA"},
{"vcpr", "vcprA"},
{"espantoso", "espantosoA"},
{"emotion", "emotionA"},
{"wave103", "wave103A"},
{"mp3", "mp3A"},
{"downOff", "buttonA"},
{"downOn", "buttonA"},
{"upOff", "buttonA"},
{"upOn", "buttonA"}
};
#ifdef ASPECT_RATIO_SCALE #ifdef ASPECT_RATIO_SCALE
// All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X. // All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X.
@ -284,7 +281,7 @@ ScaleAndCenterX(float x)
#endif #endif
#define PREPARE_MENU_HEADER \ #define PREPARE_MENU_HEADER \
CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); \
CFont::SetRightJustifyOn(); \ CFont::SetRightJustifyOn(); \
CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
@ -306,9 +303,10 @@ ScaleAndCenterX(float x)
m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ m_nHoverOption = HOVEROPTION_NOT_HOVERING; \
} while(0) } while(0)
// TODO: this is COMPLETELY different in VC
#define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ #define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \
do { \ do { \
sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(255, 255, 255, 100)); \
if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \
m_nHoverOption = hoverOpt; \ m_nHoverOption = hoverOpt; \
} while (0) } while (0)
@ -651,15 +649,15 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR
int lastActiveBarX = 0; int lastActiveBarX = 0;
float curBarX = 0.0f; float curBarX = 0.0f;
float spacing = SCREEN_SCALE_X(10.0f); float spacing = SCREEN_SCALE_X(4.0f); // TODO: find actual numbers used in the game
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
curBarX = i * rectSize/16.0f + x; curBarX = i * rectSize/32.0f + x;
if (i / 16.0f + 1 / 32.0f < progress) { if (i / 16.0f + 1 / 32.0f < progress) {
color = CRGBA(255, 217, 106, FadeIn(255)); color = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255));
lastActiveBarX = curBarX; lastActiveBarX = curBarX;
} else } else
color = CRGBA(185, 120, 0, FadeIn(255)); color = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255));
maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); maxBarHeight = Max(mostLeftBarSize, mostRightBarSize);
@ -700,8 +698,10 @@ CMenuManager::Draw()
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetJustifyOn(); CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn(); CFont::SetBackGroundOnlyTextOn();
#ifdef GTA3_1_1_PATCH
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); // no V1.1 text in vc obv
#if 0 //def GTA3_1_1_PATCH
CFont::SetColor(CRGBA(255, 150, 225, FadeIn(255)));
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f));
@ -711,6 +711,7 @@ CMenuManager::Draw()
AsciiToUnicode(gString, gUString); AsciiToUnicode(gString, gUString);
CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString);
#endif #endif
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
@ -736,9 +737,13 @@ CMenuManager::Draw()
if(!m_bRenderGameInMenu) if(!m_bRenderGameInMenu)
#endif #endif
if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') {
PREPARE_MENU_HEADER PREPARE_MENU_HEADER
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
PREPARE_MENU_HEADER
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
// Weird place to put that. // Weird place to put that.
nextYToUse += 24.0f + 10.0f; nextYToUse += 24.0f + 10.0f;
@ -747,7 +752,7 @@ CMenuManager::Draw()
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y)); CFont::SetScale(MENU_X(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_X), MENU_Y(MENUACTION_SCALE_MULT * MENU_TEXT_SIZE_Y));
CFont::SetRightJustifyOff(); CFont::SetRightJustifyOff();
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); CFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));
// Label // Label
wchar *str; wchar *str;
@ -845,7 +850,7 @@ CMenuManager::Draw()
break; break;
case MENUPAGE_START_MENU: case MENUPAGE_START_MENU:
columnWidth = 320; columnWidth = 320;
headerHeight = 140; headerHeight = 110;
lineHeight = 24; lineHeight = 24;
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE)); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = BIGTEXT_X_SCALE), MENU_Y(MENU_TEXT_SIZE_Y = BIGTEXT_Y_SCALE));
@ -898,7 +903,7 @@ CMenuManager::Draw()
} }
float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider float usableLineHeight = lineHeight * 0.9f; // also height of biggest bar in slider
float smallestSliderBar = lineHeight * 0.1f; float smallestSliderBar = lineHeight * 0.25f; // TODO: find actual number
bool foundTheHoveringItem = false; bool foundTheHoveringItem = false;
wchar unicodeTemp[64]; wchar unicodeTemp[64];
char asciiTemp[32]; char asciiTemp[32];
@ -1226,7 +1231,7 @@ CMenuManager::Draw()
// We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background // We keep stretching, because we also stretch background image and we want that bar to be aligned with borders of background
CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY), CSprite2d::DrawRect(CRect(StretchX(10.0f), MENU_Y(bitAboveNextItemY),
SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)), SCREEN_STRETCH_FROM_RIGHT(11.0f), MENU_Y(usableLineHeight + nextItemY)),
CRGBA(100, 200, 50, FadeIn(50))); CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));
} }
CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90))); CFont::SetColor(CRGBA(0, 0, 0, FadeIn(90)));
@ -1245,14 +1250,14 @@ CMenuManager::Draw()
if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES") if(!strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FED_RES")
&& !m_bGameNotLoaded && textLayer == 1) { && !m_bGameNotLoaded && textLayer == 1) {
CFont::SetColor(CRGBA(155, 117, 6, FadeIn(255))); CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));
} }
CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText); CFont::PrintString(MENU_X_RIGHT_ALIGNED(columnWidth - textLayer), itemY, rightText);
} }
if (i == m_nCurrOption && itemsAreSelectable){ if (i == m_nCurrOption && itemsAreSelectable){
CFont::SetColor(CRGBA(255, 217, 106, FadeIn(255))); CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));
} else { } else {
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); CFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255)));
} }
} }
@ -1321,18 +1326,18 @@ CMenuManager::Draw()
// Radio icons // Radio icons
if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) {
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO1], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WILDSTYLE], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO2], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FLASH], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO5], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_KCHAT], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO7], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_FEVER], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO8], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VROCK], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO3], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_VCPR], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO4], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_ESPANTOSO], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO6], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_EMOTION], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7);
ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_WAVE], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8);
if (DMAudio.IsMP3RadioChannelAvailable()) if (DMAudio.IsMP3RadioChannelAvailable())
ProcessRadioIcon(m_aMenuSprites[MENUSPRITE_MP3LOGO], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); ProcessRadioIcon(m_aFrontEndSprites[MENUSPRITE_MP3], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9);
nextYToUse += 70.0f; nextYToUse += 70.0f;
} }
@ -1813,11 +1818,21 @@ CMenuManager::DrawControllerSetupScreen()
switch (m_ControlMethod) { switch (m_ControlMethod) {
case CONTROL_STANDARD: case CONTROL_STANDARD:
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f),
TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
PREPARE_MENU_HEADER
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y),
TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));
break; break;
case CONTROL_CLASSIC: case CONTROL_CLASSIC:
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f),
TheText.Get("FET_CTI"));
PREPARE_MENU_HEADER
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y),
TheText.Get("FET_CTI")); TheText.Get("FET_CTI"));
break; break;
default: default:
@ -2079,13 +2094,13 @@ CMenuManager::DrawFrontEndSaveZone()
mouse.Translate(m_nMousePosX, m_nMousePosY); mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){ if(field_518 == 4){
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{ }else{
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
} }
} }
} }
@ -2273,13 +2288,13 @@ CMenuManager::DrawFrontEndNormal()
mouse.Translate(m_nMousePosX, m_nMousePosY); mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){ if(field_518 == 4){
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{ }else{
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
} }
} }
} }
@ -2293,65 +2308,24 @@ CMenuManager::DrawFrontEndNormal()
LoadSplash(nil); LoadSplash(nil);
eMenuSprites previousSprite; eMenuSprites previousSprite = MENUSPRITE_BACKGROUND;
if (m_nMenuFadeAlpha < 255) { if (m_nMenuFadeAlpha < 255) {
switch (m_nPrevScreen) {
case MENUPAGE_STATS:
case MENUPAGE_START_MENU:
case MENUPAGE_PAUSE_MENU:
previousSprite = MENUSPRITE_MAINMENU;
break;
case MENUPAGE_NEW_GAME:
case MENUPAGE_CHOOSE_LOAD_SLOT:
case MENUPAGE_CHOOSE_DELETE_SLOT:
case MENUPAGE_NEW_GAME_RELOAD:
case MENUPAGE_LOAD_SLOT_CONFIRM:
case MENUPAGE_DELETE_SLOT_CONFIRM:
case MENUPAGE_EXIT:
previousSprite = MENUSPRITE_SINGLEPLAYER;
break;
case MENUPAGE_MULTIPLAYER_MAIN:
previousSprite = MENUSPRITE_MULTIPLAYER;
break;
case MENUPAGE_MULTIPLAYER_MAP:
case MENUPAGE_MULTIPLAYER_FIND_GAME:
case MENUPAGE_SKIN_SELECT:
case MENUPAGE_KEYBOARD_CONTROLS:
case MENUPAGE_MOUSE_CONTROLS:
previousSprite = MENUSPRITE_FINDGAME;
break;
case MENUPAGE_MULTIPLAYER_CONNECTION:
case MENUPAGE_MULTIPLAYER_MODE:
previousSprite = MENUSPRITE_CONNECTION;
break;
case MENUPAGE_MULTIPLAYER_CREATE:
previousSprite = MENUSPRITE_HOSTGAME;
break;
case MENUPAGE_SKIN_SELECT_OLD:
case MENUPAGE_OPTIONS:
previousSprite = MENUSPRITE_PLAYERSET;
break;
default:
previousSprite = MENUSPRITE_MAINMENU;
break;
}
if (m_nPrevScreen == m_nCurrScreen) if (m_nPrevScreen == m_nCurrScreen)
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha)); CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255 - m_nMenuFadeAlpha));
else else
m_aMenuSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha)); m_aFrontEndSprites[previousSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255 - m_nMenuFadeAlpha));
} }
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
eMenuSprites currentSprite = MENUSPRITE_MAINMENU; // actually uninitialized eMenuSprites currentSprite = MENUSPRITE_BACKGROUND; // actually uninitialized
switch (m_nCurrScreen) { switch (m_nCurrScreen) {
case MENUPAGE_STATS: case MENUPAGE_STATS:
case MENUPAGE_START_MENU: case MENUPAGE_START_MENU:
case MENUPAGE_PAUSE_MENU: case MENUPAGE_PAUSE_MENU:
currentSprite = MENUSPRITE_MAINMENU;
break;
case MENUPAGE_NEW_GAME: case MENUPAGE_NEW_GAME:
case MENUPAGE_CHOOSE_LOAD_SLOT: case MENUPAGE_CHOOSE_LOAD_SLOT:
case MENUPAGE_CHOOSE_DELETE_SLOT: case MENUPAGE_CHOOSE_DELETE_SLOT:
@ -2359,28 +2333,18 @@ CMenuManager::DrawFrontEndNormal()
case MENUPAGE_LOAD_SLOT_CONFIRM: case MENUPAGE_LOAD_SLOT_CONFIRM:
case MENUPAGE_DELETE_SLOT_CONFIRM: case MENUPAGE_DELETE_SLOT_CONFIRM:
case MENUPAGE_EXIT: case MENUPAGE_EXIT:
currentSprite = MENUSPRITE_SINGLEPLAYER;
break;
case MENUPAGE_MULTIPLAYER_MAIN: case MENUPAGE_MULTIPLAYER_MAIN:
currentSprite = MENUSPRITE_MULTIPLAYER;
break;
case MENUPAGE_MULTIPLAYER_MAP: case MENUPAGE_MULTIPLAYER_MAP:
case MENUPAGE_MULTIPLAYER_FIND_GAME: case MENUPAGE_MULTIPLAYER_FIND_GAME:
case MENUPAGE_SKIN_SELECT: case MENUPAGE_SKIN_SELECT:
case MENUPAGE_KEYBOARD_CONTROLS: case MENUPAGE_KEYBOARD_CONTROLS:
case MENUPAGE_MOUSE_CONTROLS: case MENUPAGE_MOUSE_CONTROLS:
currentSprite = MENUSPRITE_FINDGAME;
break;
case MENUPAGE_MULTIPLAYER_CONNECTION: case MENUPAGE_MULTIPLAYER_CONNECTION:
case MENUPAGE_MULTIPLAYER_MODE: case MENUPAGE_MULTIPLAYER_MODE:
currentSprite = MENUSPRITE_CONNECTION;
break;
case MENUPAGE_MULTIPLAYER_CREATE: case MENUPAGE_MULTIPLAYER_CREATE:
currentSprite = MENUSPRITE_HOSTGAME;
break;
case MENUPAGE_SKIN_SELECT_OLD: case MENUPAGE_SKIN_SELECT_OLD:
case MENUPAGE_OPTIONS: case MENUPAGE_OPTIONS:
currentSprite = MENUSPRITE_PLAYERSET; currentSprite = MENUSPRITE_BACKGROUND;
break; break;
} }
@ -2404,13 +2368,13 @@ CMenuManager::DrawFrontEndNormal()
#endif #endif
if (m_nMenuFadeAlpha > 255){ if (m_nMenuFadeAlpha > 255){
m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
} else { } else {
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha));
} }
} else { } else {
m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
// TODO: what is this? waiting mouse? // TODO: what is this? waiting mouse?
if(field_518 == 4){ if(field_518 == 4){
if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 || if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 ||
@ -2422,15 +2386,20 @@ CMenuManager::DrawFrontEndNormal()
} }
} }
m_aFrontEndSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
// GTA LOGO // GTA LOGO
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
/*
if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) { if (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_PAUSE_MENU) {
if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
m_aMenuSprites[MENUSPRITE_GTA3LOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255))); m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(205.0f), MENU_Y(70.0f), MENU_X_LEFT_ALIGNED(435.0f), MENU_Y(180.0f)), CRGBA(255, 255, 255, FadeIn(255)));
else else
m_aMenuSprites[MENUSPRITE_GTALOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255))); m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X_LEFT_ALIGNED(225.0f), MENU_Y(40.0f), MENU_X_LEFT_ALIGNED(415.0f), MENU_Y(210.0f)), CRGBA(255, 255, 255, FadeIn(255)));
} }
*/
m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_SCALE_X(27.0f), MENU_Y(8.0f), SCREEN_SCALE_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255)));
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
@ -2457,19 +2426,19 @@ CMenuManager::DrawFrontEndNormal()
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
CRect mouse(0.0f, 0.0f, MENU_X(75.0f), MENU_Y(75.0f)); CRect mouse(0.0f, 0.0f, MENU_X(40.0f), MENU_Y(40.0f));
CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(85.0f), MENU_Y(78.0f)); CRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(55.0f), MENU_Y(43.0f));
mouse.Translate(m_nMousePosX, m_nMousePosY); mouse.Translate(m_nMousePosX, m_nMousePosY);
shad.Translate(m_nMousePosX, m_nMousePosY); shad.Translate(m_nMousePosX, m_nMousePosY);
if(field_518 == 4){ if(field_518 == 4){
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSET].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
}else{ }else{
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
m_aMenuSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));
} }
} }
} }
@ -2711,21 +2680,21 @@ CMenuManager::DrawPlayerSetupScreen()
// 2 - leaves gap between button and scrollbar // 2 - leaves gap between button and scrollbar
if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) { if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) {
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#else #else
m_aMenuSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP), m_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), MENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#endif #endif
} else { } else {
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#else #else
m_aMenuSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP), m_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)), MENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#endif #endif
@ -2733,21 +2702,21 @@ CMenuManager::DrawPlayerSetupScreen()
if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) { if (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) {
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#else #else
m_aMenuSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f), m_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f),
MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), MENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#endif #endif
} else { } else {
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1), m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)), MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#else #else
m_aMenuSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f), m_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f),
MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)), MENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),
CRGBA(255, 255, 255, FadeIn(255))); CRGBA(255, 255, 255, FadeIn(255)));
#endif #endif
@ -3021,51 +2990,59 @@ CMenuManager::LoadAllTextures()
CStreaming::ImGonnaUseStreamingMemory(); CStreaming::ImGonnaUseStreamingMemory();
CGame::TidyUpMemory(false, true); CGame::TidyUpMemory(false, true);
CTxdStore::PushCurrentTxd(); CTxdStore::PushCurrentTxd();
int frontendTxdSlot = CTxdStore::FindTxdSlot("frontend"); int frontendTxdSlot1 = CTxdStore::FindTxdSlot("frontend1");
if(frontendTxdSlot == -1) if(frontendTxdSlot1 == -1)
frontendTxdSlot = CTxdStore::AddTxdSlot("frontend"); frontendTxdSlot1 = CTxdStore::AddTxdSlot("frontend1");
printf("LOAD frontend\n"); printf("LOAD frontend1\n");
CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD"); CTxdStore::LoadTxd(frontendTxdSlot1, "MODELS/FRONTEN1.TXD");
CTxdStore::AddRef(frontendTxdSlot); CTxdStore::AddRef(frontendTxdSlot1);
CTxdStore::SetCurrentTxd(frontendTxdSlot); CTxdStore::SetCurrentTxd(frontendTxdSlot1);
#ifndef GTA3_1_1_PATCH
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); i++) { for (int i = 0; i < 3; i++) {
m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]); m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);
m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
} }
int menuTxdSlot = CTxdStore::FindTxdSlot("menu"); CTxdStore::PopCurrentTxd();
CStreaming::IHaveUsedStreamingMemory();
if (menuTxdSlot == -1)
menuTxdSlot = CTxdStore::AddTxdSlot("menu");
printf("LOAD sprite\n"); // if ( !*(_BYTE *)(v1 + 124) )
CTxdStore::LoadTxd(menuTxdSlot, "MODELS/MENU.TXD");
CTxdStore::AddRef(menuTxdSlot);
CTxdStore::SetCurrentTxd(menuTxdSlot);
for (int i = 0; i < ARRAY_SIZE(MenuFilenames); i++) { CStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile
m_aMenuSprites[i].SetTexture(MenuFilenames[i][0], MenuFilenames[i][1]); CStreaming::ImGonnaUseStreamingMemory();
m_aMenuSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); CTxdStore::PushCurrentTxd();
int frontendTxdSlot2 = CTxdStore::FindTxdSlot("frontend2");
if (frontendTxdSlot2 == -1)
frontendTxdSlot2 = CTxdStore::AddTxdSlot("frontend2");
printf("LOAD frontend2\n");
CTxdStore::LoadTxd(frontendTxdSlot2, "MODELS/FRONTEN2.TXD");
CTxdStore::AddRef(frontendTxdSlot2);
CTxdStore::SetCurrentTxd(frontendTxdSlot2);
for (int i = 3; i < NUM_MENU_SPRITES; i++) {
m_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);
m_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
} }
#ifdef MENU_MAP
CTxdStore::PopCurrentTxd();
CStreaming::IHaveUsedStreamingMemory();
#if 0 //MENU_MAP
for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) { for (int i = 0; i < ARRAY_SIZE(MapFilenames); i++) {
m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]); m_aMapSprites[i].SetTexture(MapFilenames[i][0], MapFilenames[i][1]);
m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER); m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
} }
#endif #endif
#ifdef GTA3_1_1_PATCH
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
m_bSpritesLoaded = true; m_bSpritesLoaded = true;
CTxdStore::PopCurrentTxd(); CTimer::Update();
} }
void void
@ -5147,18 +5124,16 @@ CMenuManager::UnloadTextures()
for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i) for (int i = 0; i < ARRAY_SIZE(FrontendFilenames); ++i)
m_aFrontEndSprites[i].Delete(); m_aFrontEndSprites[i].Delete();
int frontend = CTxdStore::FindTxdSlot("frontend"); int frontend = CTxdStore::FindTxdSlot("frontend1");
CTxdStore::RemoveTxd(frontend); CTxdStore::RemoveTxd(frontend);
printf("REMOVE menu textures\n"); int frontend2 = CTxdStore::FindTxdSlot("frontend2");
for (int i = 0; i < ARRAY_SIZE(MenuFilenames); ++i) CTxdStore::RemoveTxd(frontend2);
m_aMenuSprites[i].Delete();
#ifdef MENU_MAP #ifdef false //MENU_MAP
for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i) for (int i = 0; i < ARRAY_SIZE(MapFilenames); ++i)
m_aMapSprites[i].Delete(); m_aMapSprites[i].Delete();
#endif #endif
int menu = CTxdStore::FindTxdSlot("menu");
CTxdStore::RemoveTxd(menu);
m_bSpritesLoaded = false; m_bSpritesLoaded = false;
} }
@ -5197,6 +5172,9 @@ CMenuManager::PrintController(void)
// FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?) // FIX: Originally this function doesn't have StretchX/Y, everything had constant pixel size (due to screen was abandoned early?)
// Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X) // Also texts and their alignment were very bad, so I tried to make them readable (commented out the original code, and marked the ones I added with X)
// sorry!
/*
m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255)); m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(240.0f), MENU_Y(180.0f), CRGBA(0, 0, 0, 255));
m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255));
if (m_DisplayControllerOnFoot) { if (m_DisplayControllerOnFoot) {
@ -5210,6 +5188,7 @@ CMenuManager::PrintController(void)
else else
m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255)); m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(160.0f), MENU_Y(160.0f), MENU_X(235.2f), MENU_Y(175.2f), CRGBA(255, 255, 255, 255));
} }
*/
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // X
@ -5468,47 +5447,47 @@ CMenuManager::PrintMap(void)
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
m_aMapSprites[MAPTOP1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize, m_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - fMapSize,
fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX - halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
m_aMapSprites[MAPTOP2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize, m_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - fMapSize,
fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + halfTile, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) { if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - fMapSize) {
m_aMapSprites[MAPTOP3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize, m_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - fMapSize,
fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + fMapSize, fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) { if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
m_aMapSprites[MAPMID1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile, m_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY - halfTile,
fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX - halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
m_aMapSprites[MAPMID2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile, m_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY - halfTile,
fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + halfTile, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) { if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY - halfTile) {
m_aMapSprites[MAPMID3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile, m_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY - halfTile,
fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + fMapSize, fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) { if (SCREEN_WIDTH >= fMapCenterX - fMapSize || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
m_aMapSprites[MAPBOT1].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile, m_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(fMapCenterX - fMapSize, fMapCenterY + halfTile,
fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX - halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { if (SCREEN_WIDTH >= fMapCenterX - halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
m_aMapSprites[MAPBOT2].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile, m_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(fMapCenterX - halfTile, fMapCenterY + halfTile,
fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + halfTile, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
} }
if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) { if (SCREEN_WIDTH >= fMapCenterX + halfTile || SCREEN_HEIGHT >= fMapCenterY + halfTile) {
m_aMapSprites[MAPBOT3].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile, m_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(fMapCenterX + halfTile, fMapCenterY + halfTile,
fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255))); fMapCenterX + fMapSize, fMapCenterY + fMapSize), CRGBA(255, 255, 255, FadeIn(255)));
} }

View File

@ -7,8 +7,8 @@
#define MENUHEADER_POS_Y 75.0f #define MENUHEADER_POS_Y 75.0f
#define MENUHEADER_HEIGHT 1.3f #define MENUHEADER_HEIGHT 1.3f
#else #else
#define MENUHEADER_POS_X 35.0f #define MENUHEADER_POS_X 10.0f
#define MENUHEADER_POS_Y 93.0f #define MENUHEADER_POS_Y 10.0f
#define MENUHEADER_HEIGHT 1.6f #define MENUHEADER_HEIGHT 1.6f
#endif #endif
#define MENUHEADER_WIDTH 0.84f #define MENUHEADER_WIDTH 0.84f
@ -20,7 +20,7 @@
#define MENURADIO_ICON_SCALE 60.0f #define MENURADIO_ICON_SCALE 60.0f
#define MENUSLIDER_X 256.0f #define MENUSLIDER_X 128.0f
#define MENUSLIDER_UNK 256.0f #define MENUSLIDER_UNK 256.0f
#define BIGTEXT_X_SCALE 0.75f #define BIGTEXT_X_SCALE 0.75f
@ -95,6 +95,7 @@ enum eLanguages
#endif #endif
}; };
/*
enum eFrontendSprites enum eFrontendSprites
{ {
FE2_MAINPANEL_UL, FE2_MAINPANEL_UL,
@ -128,29 +129,36 @@ enum eFrontendSprites
NUM_FE_SPRITES NUM_FE_SPRITES
}; };
*/
enum eMenuSprites enum eMenuSprites
{ {
MENUSPRITE_CONNECTION, MENUSPRITE_BACKGROUND,
MENUSPRITE_FINDGAME, MENUSPRITE_VCLOGO,
MENUSPRITE_HOSTGAME,
MENUSPRITE_MAINMENU,
MENUSPRITE_PLAYERSET,
MENUSPRITE_SINGLEPLAYER,
MENUSPRITE_MULTIPLAYER,
MENUSPRITE_DMALOGO,
MENUSPRITE_GTALOGO,
MENUSPRITE_RSTARLOGO,
MENUSPRITE_GAMESPY,
MENUSPRITE_MOUSE, MENUSPRITE_MOUSE,
MENUSPRITE_MOUSET, MENUSPRITE_MAPTOP01,
MENUSPRITE_MP3LOGO, MENUSPRITE_MAPTOP02,
MENUSPRITE_MAPTOP03,
MENUSPRITE_MAPMID01,
MENUSPRITE_MAPMID02,
MENUSPRITE_MAPMID03,
MENUSPRITE_MAPBOT01,
MENUSPRITE_MAPBOT02,
MENUSPRITE_MAPBOT03,
MENUSPRITE_WILDSTYLE,
MENUSPRITE_FLASH,
MENUSPRITE_KCHAT,
MENUSPRITE_FEVER,
MENUSPRITE_VROCK,
MENUSPRITE_VCPR,
MENUSPRITE_ESPANTOSO,
MENUSPRITE_EMOTION,
MENUSPRITE_WAVE,
MENUSPRITE_MP3,
MENUSPRITE_DOWNOFF, MENUSPRITE_DOWNOFF,
MENUSPRITE_DOWNON, MENUSPRITE_DOWNON,
MENUSPRITE_UPOFF, MENUSPRITE_UPOFF,
MENUSPRITE_UPON, MENUSPRITE_UPON,
MENUSPRITE_GTA3LOGO,
MENUSPRITE_UNUSED,
NUM_MENU_SPRITES NUM_MENU_SPRITES
}; };
@ -509,8 +517,9 @@ public:
char field_455; char field_455;
bool m_bStartWaitingForKeyBind; bool m_bStartWaitingForKeyBind;
bool m_bSpritesLoaded; bool m_bSpritesLoaded;
CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES]; //CSprite2d m_aFrontEndSprites[NUM_FE_SPRITES];
CSprite2d m_aMenuSprites[NUM_MENU_SPRITES]; //CSprite2d m_aMenuSprites[NUM_MENU_SPRITES];
CSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES];
int32 field_518; int32 field_518;
int32 m_nMenuFadeAlpha; int32 m_nMenuFadeAlpha;
bool m_bPressedPgUpOnList; bool m_bPressedPgUpOnList;

View File

@ -84,6 +84,7 @@
#include "World.h" #include "World.h"
#include "ZoneCull.h" #include "ZoneCull.h"
#include "Zones.h" #include "Zones.h"
#include "Occlusion.h"
#include "debugmenu.h" #include "debugmenu.h"
@ -272,6 +273,7 @@ bool CGame::Initialise(const char* datFile)
ThePaths.AllocatePathFindInfoMem(4500); ThePaths.AllocatePathFindInfoMem(4500);
CWeather::Init(); CWeather::Init();
CCullZones::Init(); CCullZones::Init();
COcclusion::Init();
CCollision::Init(); CCollision::Init();
CTheZones::Init(); CTheZones::Init();
CUserDisplay::Init(); CUserDisplay::Init();

View File

@ -100,7 +100,7 @@ void WeaponCheat()
void HealthCheat() void HealthCheat()
{ {
CHud::SetHelpMessage(TheText.Get("CHEAT3"), true); CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
FindPlayerPed()->m_fHealth = 100.0f; FindPlayerPed()->m_fHealth = CWorld::Players[0].m_nMaxHealth;
if (FindPlayerVehicle()) { if (FindPlayerVehicle()) {
FindPlayerVehicle()->m_fHealth = 1000.0f; FindPlayerVehicle()->m_fHealth = 1000.0f;
if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR) if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR)
@ -224,7 +224,7 @@ void MoneyCheat()
void ArmourCheat() void ArmourCheat()
{ {
CHud::SetHelpMessage(TheText.Get("CHEAT4"), true); CHud::SetHelpMessage(TheText.Get("CHEAT4"), true);
FindPlayerPed()->m_fArmour = 100.0f; FindPlayerPed()->m_fArmour = CWorld::Players[0].m_nMaxArmour;
} }
void WantedLevelUpCheat() void WantedLevelUpCheat()

View File

@ -140,6 +140,7 @@ CPlayerInfo::Clear(void)
m_nUpsideDownCounter = 0; m_nUpsideDownCounter = 0;
m_bInfiniteSprint = false; m_bInfiniteSprint = false;
m_bFastReload = false; m_bFastReload = false;
m_nMaxHealth = m_nMaxArmour = 100;
m_bGetOutOfJailFree = false; m_bGetOutOfJailFree = false;
m_bGetOutOfHospitalFree = false; m_bGetOutOfHospitalFree = false;
m_bDriveByAllowed = true; m_bDriveByAllowed = true;
@ -172,7 +173,6 @@ void
CPlayerInfo::MakePlayerSafe(bool toggle) CPlayerInfo::MakePlayerSafe(bool toggle)
{ {
if (toggle) { if (toggle) {
CTheScripts::ResetCountdownToMakePlayerUnsafe();
m_pPed->m_pWanted->m_bIgnoredByEveryone = true; m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CWorld::StopAllLawEnforcersInTheirTracks(); CWorld::StopAllLawEnforcersInTheirTracks();
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20; CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
@ -193,7 +193,8 @@ CPlayerInfo::MakePlayerSafe(bool toggle)
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
CReplay::DisableReplays(); CReplay::DisableReplays();
} else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { }
else {
m_pPed->m_pWanted->m_bIgnoredByEveryone = false; m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20; CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false; m_pPed->bBulletProof = false;

View File

@ -52,6 +52,9 @@ public:
int32 field_272; int32 field_272;
bool m_bInfiniteSprint; bool m_bInfiniteSprint;
bool m_bFastReload; bool m_bFastReload;
bool m_bFireproof;
uint8 m_nMaxHealth;
uint8 m_nMaxArmour;
bool m_bGetOutOfJailFree; bool m_bGetOutOfJailFree;
bool m_bGetOutOfHospitalFree; bool m_bGetOutOfHospitalFree;
bool m_bDriveByAllowed; bool m_bDriveByAllowed;

View File

@ -61,6 +61,7 @@ int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];
int32 CStats::Sprayings; int32 CStats::Sprayings;
float CStats::AutoPaintingBudget; float CStats::AutoPaintingBudget;
int32 CStats::NoMoreHurricanes; int32 CStats::NoMoreHurricanes;
float CStats::FashionBudget;
void CStats::Init() void CStats::Init()
{ {
@ -257,6 +258,11 @@ float CStats::GetPercentageProgress()
return Min(percentCompleted, 100.0f); return Min(percentCompleted, 100.0f);
} }
void CStats::MoneySpentOnFashion(int32 money)
{
FashionBudget += money;
}
void CStats::SaveStats(uint8 *buf, uint32 *size) void CStats::SaveStats(uint8 *buf, uint32 *size)
{ {
CheckPointReachedSuccessfully(); CheckPointReachedSuccessfully();

View File

@ -65,6 +65,7 @@ public:
static int32 Sprayings; static int32 Sprayings;
static float AutoPaintingBudget; static float AutoPaintingBudget;
static int32 NoMoreHurricanes; static int32 NoMoreHurricanes;
static float FashionBudget;
public: public:
static void Init(void); static void Init(void);
@ -91,4 +92,6 @@ public:
static void SaveStats(uint8 *buf, uint32 *size); static void SaveStats(uint8 *buf, uint32 *size);
static void LoadStats(uint8 *buf, uint32 size); static void LoadStats(uint8 *buf, uint32 size);
static float GetPercentageProgress(); static float GetPercentageProgress();
static void MoneySpentOnFashion(int32);
}; };

View File

@ -66,7 +66,7 @@ enum Config {
// Cull zones // Cull zones
NUMATTRIBZONES = 704, NUMATTRIBZONES = 704,
NUMHANDLINGS = 106, NUMOCCLUSIONVOLUMES = 350,
PATHNODESIZE = 4500, PATHNODESIZE = 4500,
@ -194,7 +194,7 @@ enum Config {
#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 //#define MORE_LANGUAGES // Add more translations to the game
#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch)
#define USE_TXD_CDIMAGE // generate and load textures from txd.img #define USE_TXD_CDIMAGE // generate and load textures from txd.img
#define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number

View File

@ -20,3 +20,25 @@ CBuilding::ReplaceWithNewModel(int32 id)
if(m_level == LEVEL_NONE || m_level == CGame::currLevel) if(m_level == LEVEL_NONE || m_level == CGame::currLevel)
CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE);
} }
bool
IsBuildingPointerValid(CBuilding* pBuilding)
{
if (!pBuilding)
return false;
if (pBuilding->GetIsATreadable()) {
int index = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding);
#ifdef FIX_BUGS
return index >= 0 && index < CPools::GetTreadablePool()->GetSize();
#else
return index >= 0 && index <= CPools::GetTreadablePool()->GetSize();
#endif
} else {
int index = CPools::GetBuildingPool()->GetJustIndex(pBuilding);
#ifdef FIX_BUGS
return index >= 0 && index < CPools::GetBuildingPool()->GetSize();
#else
return index >= 0 && index <= CPools::GetBuildingPool()->GetSize();
#endif
}
}

View File

@ -16,3 +16,5 @@ public:
virtual bool GetIsATreadable(void) { return false; } virtual bool GetIsATreadable(void) { return false; }
}; };
bool IsBuildingPointerValid(CBuilding*);

View File

@ -50,3 +50,18 @@ CDummy::Remove(void)
m_entryInfoList.DeleteNode(node); m_entryInfoList.DeleteNode(node);
} }
} }
bool
IsDummyPointerValid(CDummy* pDummy)
{
if (!pDummy)
return false;
int index = CPools::GetDummyPool()->GetJustIndex(pDummy);
#ifdef FIX_BUGS
if (index < 0 || index >= CPools::GetDummyPool()->GetSize())
#else
if (index < 0 || index > CPools::GetDummyPool()->GetSize())
#endif
return false;
return pDummy->m_entryInfoList.first;
}

View File

@ -15,3 +15,5 @@ public:
static void *operator new(size_t); static void *operator new(size_t);
static void operator delete(void*, size_t); static void operator delete(void*, size_t);
}; };
bool IsDummyPointerValid(CDummy* pDummy);

View File

@ -28,6 +28,8 @@
#include "Bones.h" #include "Bones.h"
#include "Debug.h" #include "Debug.h"
#include "Renderer.h" #include "Renderer.h"
#include "Ped.h"
#include "Dummy.h"
int gBuildings; int gBuildings;
@ -1028,3 +1030,18 @@ CEntity::LoadEntityFlags(uint8*& buf)
} }
#endif #endif
bool IsEntityPointerValid(CEntity* pEntity)
{
if (!pEntity)
return false;
switch (pEntity->GetType()) {
case ENTITY_TYPE_NOTHING: return false;
case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);
case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);
case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);
case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);
case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);
}
return false;
}

View File

@ -180,3 +180,5 @@ public:
static void AddSteamsFromGround(CPtrList& list); static void AddSteamsFromGround(CPtrList& list);
}; };
bool IsEntityPointerValid(CEntity*);

View File

@ -160,7 +160,9 @@
X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \ X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \
X("files", MI_FILES, 0x5F5BC4) \ X("files", MI_FILES, 0x5F5BC4) \
X("property_locked", MI_PICKUP_PROPERTY, 0x0) \ X("property_locked", MI_PICKUP_PROPERTY, 0x0) \
X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) X("property_fsale", MI_PICKUP_PROPERTY_FORSALE, 0x0) \
X("clothesp", MI_PICKUP_CLOTHES, 0x0) \
X("bigdollar", MI_PICKUP_REVENUE, 0x0)
#define X(name, var, addr) extern int16 var; #define X(name, var, addr) extern int16 var;
MODELINDICES MODELINDICES

View File

@ -396,3 +396,18 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius)
} }
} }
} }
bool
IsObjectPointerValid(CObject* pObject)
{
if (!pObject)
return false;
int index = CPools::GetObjectPool()->GetJustIndex(pObject);
#ifdef FIX_BUGS
if (index < 0 || index >= CPools::GetObjectPool()->GetSize())
#else
if (index < 0 || index > CPools::GetObjectPool()->GetSize())
#endif
return false;
return pObject->bIsBIGBuilding || pObject->m_entryInfoList.first;
}

View File

@ -113,3 +113,5 @@ public:
static void DeleteAllTempObjects(); static void DeleteAllTempObjects();
static void DeleteAllTempObjectsInArea(CVector point, float fRadius); static void DeleteAllTempObjectsInArea(CVector point, float fRadius);
}; };
bool IsObjectPointerValid(CObject* pObject);

View File

@ -325,7 +325,7 @@ CCivilianPed::ProcessControl(void)
CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10); CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10);
} }
m_pMyVehicle->pDriver->m_fHealth = Min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth); m_pMyVehicle->pDriver->m_fHealth = Min(CWorld::Players[0].m_nMaxHealth + 25.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);
if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250) if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250)
CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
} else { } else {
@ -336,7 +336,7 @@ CCivilianPed::ProcessControl(void)
} else { } else {
bWanderPathAfterExitingCar = true; bWanderPathAfterExitingCar = true;
CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
m_pMyVehicle->pDriver->m_fHealth = 125.0f; m_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f;
SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
} }
} else { } else {

View File

@ -513,6 +513,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_fAirResistance = 0.4f / m_fMass; m_fAirResistance = 0.4f / m_fMass;
m_fElasticity = 0.05f; m_fElasticity = 0.05f;
m_ceaseAttackTimer = 0;
bIsStanding = false; bIsStanding = false;
bWasStanding = false; bWasStanding = false;
bIsAttacking = false; bIsAttacking = false;
@ -18604,4 +18606,29 @@ bool
CPed::CanBeDamagedByThisGangMember(CPed* who) CPed::CanBeDamagedByThisGangMember(CPed* who)
{ {
return m_gangFlags & (1 << (uint8)(who->m_nPedType - PEDTYPE_GANG1)); return m_gangFlags & (1 << (uint8)(who->m_nPedType - PEDTYPE_GANG1));
}
bool
IsPedPointerValid_NotInWorld(CPed* pPed)
{
if (!pPed)
return false;
int index = CPools::GetPedPool()->GetJustIndex(pPed);
#ifdef FIX_BUGS
if (index < 0 || index >= NUMPEDS)
#else
if (index < 0 || index > NUMPEDS)
#endif
return false;
return true;
}
bool
IsPedPointerValid(CPed* pPed)
{
if (!IsPedPointerValid_NotInWorld(pPed))
return false;
if (pPed->bInVehicle && pPed->m_pMyVehicle)
return IsEntityPointerValid(pPed->m_pMyVehicle);
return pPed->m_entryInfoList.first || pPed == FindPlayerPed();
} }

View File

@ -220,7 +220,7 @@ enum eObjective : uint32 {
OBJECTIVE_LEAVE_CAR_AND_DIE, OBJECTIVE_LEAVE_CAR_AND_DIE,
OBJECTIVE_USE_SEAT_ATTRACTOR, OBJECTIVE_USE_SEAT_ATTRACTOR,
OBJECTIVE_USE_ATM_ATTRACTOR, OBJECTIVE_USE_ATM_ATTRACTOR,
OBJECTIVE_FLEE_CAR, // is it 41? OBJECTIVE_FLEE_CAR,
OBJ_42, OBJ_42,
OBJECTIVE_USE_STOP_ATTRACTOR, OBJECTIVE_USE_STOP_ATTRACTOR,
OBJECTIVE_USE_PIZZA_ATTRACTOR, OBJECTIVE_USE_PIZZA_ATTRACTOR,
@ -563,7 +563,7 @@ public:
uint32 m_duckAndCoverTimer; uint32 m_duckAndCoverTimer;
uint32 m_bloodyFootprintCountOrDeathTime; // Death time when bDoBloodyFootprints is false. Weird decision uint32 m_bloodyFootprintCountOrDeathTime; // Death time when bDoBloodyFootprints is false. Weird decision
uint32 m_shotTime; uint32 m_shotTime;
uint32 m_shotTimeAdd; uint32 m_ceaseAttackTimer;
uint8 m_panicCounter; uint8 m_panicCounter;
bool m_deadBleeding; bool m_deadBleeding;
int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't
@ -1026,3 +1026,6 @@ void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg);
#ifndef PED_SKIN #ifndef PED_SKIN
VALIDATE_SIZE(CPed, 0x53C); VALIDATE_SIZE(CPed, 0x53C);
#endif #endif
bool IsPedPointerValid(CPed*);
bool IsPedPointerValid_NotInWorld(CPed*);

View File

@ -64,6 +64,13 @@ CClouds::Update(void)
float s = Sin(TheCamera.Orientation - 0.85f); float s = Sin(TheCamera.Orientation - 0.85f);
CloudRotation += CWeather::Wind*s*0.001f; CloudRotation += CWeather::Wind*s*0.001f;
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f; IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f;
#ifdef FIX_BUGS
CloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix();
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f;
#else
CloudRotation += CWeather::Wind*s*0.001f;
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f;
#endif
} }
void void

View File

@ -593,15 +593,20 @@ void CHud::Draw()
else else
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f)); CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f));
CFont::SetSlant(0.15f);
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f); CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff(); CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha)); CFont::SetColor(CRGBA(0, 0, 0, fZoneAlpha));
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::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f) + SCREEN_SCALE_Y(1.0f), m_ZoneToPrint);
CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(30.0f), m_ZoneToPrint); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint);
CFont::SetSlant(0.f);
} }
} }
} }
@ -687,15 +692,20 @@ void CHud::Draw()
else else
CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f)); CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f));
CFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f));
CFont::SetSlant(0.15f);
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f); CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff(); CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha)); CFont::SetColor(CRGBA(0, 0, 0, fVehicleAlpha));
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::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f) + SCREEN_SCALE_X(1.0f), SCREEN_SCALE_FROM_BOTTOM(105.f) + SCREEN_SCALE_Y(1.0f), m_pVehicleNameToPrint);
CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha)); CFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(55.0f), m_pVehicleNameToPrint); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint);
CFont::SetSlant(0.f);
} }
} }
} }

View File

@ -2,6 +2,42 @@
#include "Occlusion.h" #include "Occlusion.h"
int32 COcclusion::NumOccludersOnMap;
int16 COcclusion::FarAwayList;
int16 COcclusion::NearbyList;
int16 COcclusion::ListWalkThroughFA;
int16 COcclusion::PreviousListWalkThroughFA;
COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES];
void
COcclusion::Init(void)
{
NumOccludersOnMap = 0;
FarAwayList = -1;
NearbyList = -1;
ListWalkThroughFA = -1;
PreviousListWalkThroughFA = -1;
}
void
COcclusion::AddOne(float x, float y, float z, float width, float length, float height, float angle)
{
if(NumOccludersOnMap >= NUMOCCLUSIONVOLUMES)
return;
aOccluders[NumOccludersOnMap].x = x;
aOccluders[NumOccludersOnMap].y = y;
aOccluders[NumOccludersOnMap].z = z;
aOccluders[NumOccludersOnMap].width = width;
aOccluders[NumOccludersOnMap].length = length;
aOccluders[NumOccludersOnMap].height = height;
while(angle < 0.0f) angle += 360.0f;
while(angle > 360.0f) angle -= 360.0f;
aOccluders[NumOccludersOnMap].angle = angle * UINT16_MAX/360.0f;
aOccluders[NumOccludersOnMap].listIndex = FarAwayList;
FarAwayList = NumOccludersOnMap++;
}
void void
COcclusion::ProcessBeforeRendering(void) COcclusion::ProcessBeforeRendering(void)
{ {

View File

@ -1,7 +1,26 @@
#pragma once #pragma once
class COccluder
{
public:
int16 width, length, height;
int16 x, y, z;
uint16 angle;
int16 listIndex;
};
class COcclusion class COcclusion
{ {
public: public:
static int32 NumOccludersOnMap;
static int16 FarAwayList;
static int16 NearbyList;
static int16 ListWalkThroughFA;
static int16 PreviousListWalkThroughFA;
static COccluder aOccluders[NUMOCCLUSIONVOLUMES];
static void Init(void);
static void AddOne(float x, float y, float z, float width, float length, float height, float angle);
static void ProcessBeforeRendering(void); static void ProcessBeforeRendering(void);
}; };

View File

@ -7,27 +7,36 @@
#include "Frontend.h" #include "Frontend.h"
#include "Messages.h" #include "Messages.h"
#include "Text.h" #include "Text.h"
#include "Timer.h"
static wchar WideErrorString[25]; static wchar WideErrorString[25];
CText TheText; CText TheText;
//--MIAMI: DONE
CText::CText(void) CText::CText(void)
{ {
encoding = 'e'; encoding = 'e';
bHasMissionTextOffsets = false;
bIsMissionTextLoaded = false;
memset(szMissionTableName, 0, sizeof(szMissionTableName));
memset(WideErrorString, 0, sizeof(WideErrorString)); memset(WideErrorString, 0, sizeof(WideErrorString));
} }
//--MIAMI: DONE
void void
CText::Load(void) CText::Load(void)
{ {
uint8 *filedata; char filename[32];
char filename[32], type[4]; uint32 offset;
int length; int file;
int offset, sectlen; bool tkey_loaded = false, tdat_loaded = false;
ChunkHeader m_ChunkHeader;
bIsMissionTextLoaded = false;
bHasMissionTextOffsets = false;
Unload(); Unload();
filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT"); CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){ switch(CMenuManager::m_PrefsLanguage){
@ -59,49 +68,64 @@ CText::Load(void)
#endif #endif
} }
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb"); file = CFileMgr::OpenFile(filename, "rb");
CFileMgr::SetDir("");
offset = 0; offset = 0;
while(offset < length){ while (!tkey_loaded || !tdat_loaded) {
type[0] = filedata[offset++]; ReadChunkHeader(&m_ChunkHeader, file, &offset);
type[1] = filedata[offset++]; if (m_ChunkHeader.size != 0) {
type[2] = filedata[offset++]; if (strncmp(m_ChunkHeader.magic, "TABL", 4) == 0) {
type[3] = filedata[offset++]; MissionTextOffsets.Load(m_ChunkHeader.size, file, &offset, 0x58000);
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 | bHasMissionTextOffsets = true;
(int)filedata[offset+1]<<8 | (int)filedata[offset+0]; } else if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
offset += 4; this->keyArray.Load(m_ChunkHeader.size, file, &offset);
if(sectlen != 0){ tkey_loaded = true;
if(strncmp(type, "TKEY", 4) == 0) } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
keyArray.Load(sectlen, filedata, &offset); this->data.Load(m_ChunkHeader.size, file, &offset);
else if(strncmp(type, "TDAT", 4) == 0) tdat_loaded = true;
data.Load(sectlen, filedata, &offset); } else {
else CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
offset += sectlen; offset += m_ChunkHeader.size;
}
} }
} }
keyArray.Update(data.chars); keyArray.Update(data.chars);
CFileMgr::CloseFile(file);
delete[] filedata; CFileMgr::SetDir("");
} }
//--MIAMI: DONE
void void
CText::Unload(void) CText::Unload(void)
{ {
CMessages::ClearAllMessagesDisplayedByGame(); CMessages::ClearAllMessagesDisplayedByGame();
data.Unload();
keyArray.Unload(); keyArray.Unload();
data.Unload();
mission_keyArray.Unload();
mission_data.Unload();
bIsMissionTextLoaded = false;
memset(szMissionTableName, 0, sizeof(szMissionTableName));
} }
//--MIAMI: DONE
wchar* wchar*
CText::Get(const char *key) CText::Get(const char *key)
{ {
uint8 result = false;
#ifdef FIX_BUGS #ifdef FIX_BUGS
return keyArray.Search(key, data.chars); wchar *outstr = keyArray.Search(key, data.chars, &result);
#else #else
return keyArray.Search(key); wchar *outstr = keyArray.Search(key, &result);
#endif #endif
if (!result && bHasMissionTextOffsets && bIsMissionTextLoaded)
#ifdef FIX_BUGS
outstr = mission_keyArray.Search(key, mission_data.chars, &result);
#else
outstr = mission_keyArray.Search(key, &result);
#endif
return outstr;
} }
wchar UpperCaseTable[128] = { wchar UpperCaseTable[128] = {
@ -134,6 +158,7 @@ wchar FrenchUpperCaseTable[128] = {
253, 254, 255 253, 254, 255
}; };
//--MIAMI: TODO (check tables)
wchar wchar
CText::GetUpperCase(wchar c) CText::GetUpperCase(wchar c)
{ {
@ -165,6 +190,7 @@ CText::GetUpperCase(wchar c)
return c; return c;
} }
//--MIAMI: DONE
void void
CText::UpperCase(wchar *s) CText::UpperCase(wchar *s)
{ {
@ -174,21 +200,131 @@ CText::UpperCase(wchar *s)
} }
} }
//--MIAMI: DONE
void void
CKeyArray::Load(uint32 length, uint8 *data, int *offset) CText::GetNameOfLoadedMissionText(char *outName)
{ {
uint32 i; strcpy(outName, szMissionTableName);
uint8 *rawbytes; }
//--MIAMI: DONE
void
CText::ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *offset)
{
// original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded
CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader));
*offset += sizeof(ChunkHeader);
}
//--MIAMI: DONE
void
CText::LoadMissionText(char *MissionTableName)
{
char filename[32];
mission_keyArray.Unload();
mission_data.Unload();
bool search_result = false;
int missionTableId = 0;
for (missionTableId = 0; missionTableId < MissionTextOffsets.size; missionTableId++) {
if (strncmp(MissionTextOffsets.data[missionTableId].szMissionName, MissionTableName, strlen(MissionTextOffsets.data[missionTableId].szMissionName)) == 0) {
search_result = true;
break;
}
}
if (!search_result) {
printf("CText::LoadMissionText - couldn't find %s", MissionTableName);
return;
}
CFileMgr::SetDir("TEXT");
switch (CMenuManager::m_PrefsLanguage) {
case LANGUAGE_AMERICAN:
sprintf(filename, "AMERICAN.GXT");
break;
case LANGUAGE_FRENCH:
sprintf(filename, "FRENCH.GXT");
break;
case LANGUAGE_GERMAN:
sprintf(filename, "GERMAN.GXT");
break;
case LANGUAGE_ITALIAN:
sprintf(filename, "ITALIAN.GXT");
break;
case LANGUAGE_SPANISH:
sprintf(filename, "SPANISH.GXT");
break;
#ifdef MORE_LANGUAGES
case LANGUAGE_POLISH:
sprintf(filename, "POLISH.GXT");
break;
case LANGUAGE_RUSSIAN:
sprintf(filename, "RUSSIAN.GXT");
break;
case LANGUAGE_JAPANESE:
sprintf(filename, "JAPANESE.GXT");
break;
#endif
}
CTimer::Suspend();
int file = CFileMgr::OpenFile(filename, "rb");
CFileMgr::Seek(file, MissionTextOffsets.data[missionTableId].offset, SEEK_SET);
char TableCheck[8];
CFileMgr::Read(file, TableCheck, 8);
if (strncmp(TableCheck, MissionTableName, 8) != 0)
printf("CText::LoadMissionText - expected to find %s in the text file", MissionTableName);
bool tkey_loaded = false, tdat_loaded = false;
ChunkHeader m_ChunkHeader;
while (!tkey_loaded || !tdat_loaded) {
uint32 bytes_read = 0;
ReadChunkHeader(&m_ChunkHeader, file, &bytes_read);
if (m_ChunkHeader.size != 0) {
if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
uint32 bytes_read = 0;
mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read);
tkey_loaded = true;
} else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
uint32 bytes_read = 0;
mission_data.Load(m_ChunkHeader.size, file, &bytes_read);
tdat_loaded = true;
} else
CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
}
}
mission_keyArray.Update(mission_data.chars);
CFileMgr::CloseFile(file);
CTimer::Resume();
CFileMgr::SetDir("");
strcpy(szMissionTableName, MissionTableName);
bIsMissionTextLoaded = true;
}
//--MIAMI: DONE
void
CKeyArray::Load(uint32 length, int file, uint32 *offset)
{
char *rawbytes;
numEntries = length / sizeof(CKeyEntry); numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries]; entries = new CKeyEntry[numEntries];
rawbytes = (uint8*)entries; rawbytes = (char*)entries;
for(i = 0; i < length; i++) #if DUMB
rawbytes[i] = data[(*offset)++]; for (uint32 i = 0; i < length; i++)
CFileMgr::Read(file, &rawbytes[i], 1);
#else
CFileMgr::Read(file, rawbytes, length);
#endif
} }
//--MIAMI: DONE
void void
CKeyArray::Unload(void) CKeyArray::Unload(void)
{ {
@ -197,6 +333,7 @@ CKeyArray::Unload(void)
numEntries = 0; numEntries = 0;
} }
//--MIAMI: DONE
void void
CKeyArray::Update(wchar *chars) CKeyArray::Update(wchar *chars)
{ {
@ -207,6 +344,7 @@ CKeyArray::Update(wchar *chars)
#endif #endif
} }
//--MIAMI: DONE
CKeyEntry* CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{ {
@ -227,11 +365,12 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi
return nil; return nil;
} }
//--MIAMI: DONE
wchar* wchar*
#ifdef FIX_BUGS #ifdef FIX_BUGS
CKeyArray::Search(const char *key, wchar *data) CKeyArray::Search(const char *key, wchar *data, uint8 *result)
#else #else
CKeyArray::Search(const char *key) CKeyArray::Search(const char *key, uint8 *result)
#endif #endif
{ {
CKeyEntry *found; CKeyEntry *found;
@ -240,34 +379,47 @@ CKeyArray::Search(const char *key)
#ifdef FIX_BUGS #ifdef FIX_BUGS
found = BinarySearch(key, entries, 0, numEntries-1); found = BinarySearch(key, entries, 0, numEntries-1);
if(found) if (found) {
*result = true;
return (wchar*)((uint8*)data + found->valueOffset); return (wchar*)((uint8*)data + found->valueOffset);
}
#else #else
found = BinarySearch(key, entries, 0, numEntries-1); found = BinarySearch(key, entries, 0, numEntries-1);
if(found) if (found) {
*result = true;
return found->value; return found->value;
}
#endif #endif
*result = false;
#ifdef MASTER
sprintf(errstr, "%");
#else
sprintf(errstr, "%s missing", key); sprintf(errstr, "%s missing", key);
#endif // MASTER
for(i = 0; i < 25; i++) for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i]; WideErrorString[i] = errstr[i];
return WideErrorString; return WideErrorString;
} }
//--MIAMI: DONE
void void
CData::Load(uint32 length, uint8 *data, int *offset) CData::Load(uint32 length, int file, uint32 *offset)
{ {
uint32 i; char *rawbytes;
uint8 *rawbytes;
numChars = length / sizeof(wchar); numChars = length / sizeof(wchar);
chars = new wchar[numChars]; chars = new wchar[numChars];
rawbytes = (uint8*)chars; rawbytes = (char*)chars;
for(i = 0; i < length; i++) #if DUMB
rawbytes[i] = data[(*offset)++]; for(uint32 i = 0; i < length; i++)
CFileMgr::Read(file, &rawbytes[i], 1);
#else
CFileMgr::Read(file, rawbytes, length);
#endif
} }
//--MIAMI: DONE
void void
CData::Unload(void) CData::Unload(void)
{ {
@ -276,6 +428,16 @@ CData::Unload(void)
numChars = 0; numChars = 0;
} }
//--MIAMI: DONE
void
CMissionTextOffsets::Load(uint32 table_size, int file, uint32 *offset, int)
{
// not exact VC code but smaller and better :P
size = table_size / sizeof(CMissionTextOffsets::Entry);
CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size);
*offset += sizeof(CMissionTextOffsets::Entry) * size;
}
void void
AsciiToUnicode(const char *src, wchar *dst) AsciiToUnicode(const char *src, wchar *dst)
{ {

View File

@ -28,14 +28,14 @@ public:
CKeyArray(void) : entries(nil), numEntries(0) {} CKeyArray(void) : entries(nil), numEntries(0) {}
~CKeyArray(void) { Unload(); } ~CKeyArray(void) { Unload(); }
void Load(uint32 length, uint8 *data, int *offset); void Load(uint32 length, int file, uint32 *offset);
void Unload(void); void Unload(void);
void Update(wchar *chars); void Update(wchar *chars);
CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high); CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
#ifdef FIX_BUGS #ifdef FIX_BUGS
wchar *Search(const char *key, wchar *data); wchar *Search(const char *key, wchar *data, uint8 *result);
#else #else
wchar *Search(const char *key); wchar *Search(const char *key, uint8* result);
#endif #endif
}; };
@ -47,15 +47,45 @@ public:
CData(void) : chars(nil), numChars(0) {} CData(void) : chars(nil), numChars(0) {}
~CData(void) { Unload(); } ~CData(void) { Unload(); }
void Load(uint32 length, uint8 *data, int *offset); void Load(uint32 length, int file, uint32 *offset);
void Unload(void); void Unload(void);
}; };
class CMissionTextOffsets
{
public:
struct Entry
{
char szMissionName[8];
uint32 offset;
};
enum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more
Entry data[MAX_MISSION_TEXTS];
uint16 size;
CMissionTextOffsets(void) : size(0) {}
void Load(uint32 table_size, int file, uint32* bytes_read, int);
};
struct ChunkHeader
{
char magic[4];
int size;
};
class CText class CText
{ {
CKeyArray keyArray; CKeyArray keyArray;
CData data; CData data;
CKeyArray mission_keyArray;
CData mission_data;
char encoding; char encoding;
bool bHasMissionTextOffsets;
bool bIsMissionTextLoaded;
char szMissionTableName[8];
CMissionTextOffsets MissionTextOffsets;
public: public:
CText(void); CText(void);
void Load(void); void Load(void);
@ -63,6 +93,9 @@ public:
wchar *Get(const char *key); wchar *Get(const char *key);
wchar GetUpperCase(wchar c); wchar GetUpperCase(wchar c);
void UpperCase(wchar *s); void UpperCase(wchar *s);
void GetNameOfLoadedMissionText(char *outName);
void ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *bytes_read);
void LoadMissionText(char *MissionTableName);
}; };
extern CText TheText; extern CText TheText;

View File

@ -72,6 +72,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
bFixedColour = false; bFixedColour = false;
bBigWheels = false; bBigWheels = false;
bWaterTight = false; bWaterTight = false;
bTankDetonateCars = true;
SetModelIndex(id); SetModelIndex(id);
@ -332,7 +333,7 @@ CAutomobile::ProcessControl(void)
bool playerRemote = false; bool playerRemote = false;
switch(GetStatus()){ switch(GetStatus()){
case STATUS_PLAYER_REMOTE: case STATUS_PLAYER_REMOTE:
if(CPad::GetPad(0)->WeaponJustDown()){ if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){
BlowUpCar(FindPlayerPed()); BlowUpCar(FindPlayerPed());
CRemote::TakeRemoteControlledCarFromPlayer(); CRemote::TakeRemoteControlledCarFromPlayer();
} }
@ -864,8 +865,14 @@ CAutomobile::ProcessControl(void)
CVector wheelFwd = GetForward(); CVector wheelFwd = GetForward();
CVector wheelRight = GetRight(); CVector wheelRight = GetRight();
#ifdef FIX_BUGS
// Not sure if this is needed, but brake usually has timestep as a factor
if(bIsHandbrakeOn)
brake = 20000.0f * CTimer::GetTimeStepFix();
#else
if(bIsHandbrakeOn) if(bIsHandbrakeOn)
brake = 20000.0f; brake = 20000.0f;
#endif
if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){ if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){
if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
@ -4148,7 +4155,7 @@ CAutomobile::BlowUpCarsInPath(void)
{ {
int i; int i;
if(m_vecMoveSpeed.Magnitude() > 0.1f) if(m_vecMoveSpeed.Magnitude() > 0.1f && bTankDetonateCars)
for(i = 0; i < m_nCollisionRecords; i++) for(i = 0; i < m_nCollisionRecords; i++)
if(m_aCollisionRecords[i] && if(m_aCollisionRecords[i] &&
m_aCollisionRecords[i]->IsVehicle() && m_aCollisionRecords[i]->IsVehicle() &&
@ -4610,6 +4617,18 @@ CAutomobile::SetAllTaxiLights(bool set)
m_sAllTaxiLights = set; m_sAllTaxiLights = set;
} }
void
CAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed)
{
AutoPilot.m_nCarMission = MISSION_HELI_FLYTOCOORS;
AutoPilot.m_vecDestinationCoors.x = x;
AutoPilot.m_vecDestinationCoors.y = y;
AutoPilot.m_vecDestinationCoors.z = z;
AutoPilot.m_nCruiseSpeed = speed;
SetStatus(STATUS_PHYSICS);
//TODO(MIAMI)
}
#ifdef COMPATIBLE_SAVES #ifdef COMPATIBLE_SAVES
void void
CAutomobile::Save(uint8*& buf) CAutomobile::Save(uint8*& buf)

View File

@ -91,6 +91,7 @@ public:
uint8 bWaterTight : 1; // no damage for non-player peds uint8 bWaterTight : 1; // no damage for non-player peds
uint8 bNotDamagedUpsideDown : 1; uint8 bNotDamagedUpsideDown : 1;
uint8 bMoreResistantToDamage : 1; uint8 bMoreResistantToDamage : 1;
uint8 bTankDetonateCars : 1;
int16 field_4E0; int16 field_4E0;
uint16 m_hydraulicState; uint16 m_hydraulicState;
uint32 m_nBusDoorTimerEnd; uint32 m_nBusDoorTimerEnd;
@ -178,6 +179,8 @@ public:
void SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents = false); void SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents = false);
void SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false); void SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false);
void TellHeliToGoToCoors(float x, float y, float z, uint8 speed);
void Fix(void); void Fix(void);
void SetComponentVisibility(RwFrame *frame, uint32 flags); void SetComponentVisibility(RwFrame *frame, uint32 flags);
void SetupModelNodes(void); void SetupModelNodes(void);

View File

@ -127,7 +127,7 @@ cHandlingDataMgr::Initialise(void)
{ {
LoadHandlingData(); LoadHandlingData();
field_0 = 0.1f; field_0 = 0.1f;
field_4 = 0.9f; fWheelFriction = 0.9f;
field_8 = 1.0f; field_8 = 1.0f;
field_C = 0.8f; field_C = 0.8f;
field_10 = 0.98f; field_10 = 0.98f;
@ -143,6 +143,9 @@ cHandlingDataMgr::LoadHandlingData(void)
int field, handlingId; int field, handlingId;
int keepGoing; int keepGoing;
tHandlingData *handling; tHandlingData *handling;
tFlyingHandlingData *flyingHandling;
tBoatHandlingData *boatHandling;
tBikeHandlingData *bikeHandling;
CFileMgr::SetDir("DATA"); CFileMgr::SetDir("DATA");
CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r"); CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
@ -151,6 +154,9 @@ cHandlingDataMgr::LoadHandlingData(void)
start = (char*)work_buff; start = (char*)work_buff;
end = start+1; end = start+1;
handling = nil; handling = nil;
flyingHandling = nil;
boatHandling = nil;
bikeHandling = nil;
keepGoing = 1; keepGoing = 1;
while(keepGoing){ while(keepGoing){
@ -166,61 +172,158 @@ cHandlingDataMgr::LoadHandlingData(void)
// yeah, this is kinda crappy // yeah, this is kinda crappy
if(strncmp(line, ";the end", 9) == 0) if(strncmp(line, ";the end", 9) == 0)
keepGoing = 0; keepGoing = 0;
// else if(line[0] != ';'){ else if(line[0] != ';'){
// TODO(MIAMI): read boat, bike, flying values if(line[0] == '!'){
else if(line[0] != ';' && line[0] != '%' && line[0] != '!' && line[0] != '$'){ // Bike data
field = 0; field = 0;
strcpy(delim, " \t"); strcpy(delim, " \t");
// FIX: game seems to use a do-while loop here // FIX: game seems to use a do-while loop here
for(word = strtok(line, delim); word; word = strtok(nil, delim)){ for(word = strtok(line, delim); word; word = strtok(nil, delim)){
switch(field){ switch(field){
case 0: case 0: break;
handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS); case 1:
assert(handlingId >= 0 && handlingId < NUMHANDLINGS); handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
handling = &HandlingData[handlingId]; assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
handling->nIdentifier = (eHandlingId)handlingId; bikeHandling = GetBikePointer(handlingId);
break; bikeHandling->nIdentifier = (eHandlingId)handlingId;
case 1: handling->fMass = strtod(word, nil); break; break;
case 2: handling->Dimension.x = strtod(word, nil); break; case 2: bikeHandling->fLeanFwdCOM = atof(word); break;
case 3: handling->Dimension.y = strtod(word, nil); break; case 3: bikeHandling->fLeanFwdForce = atof(word); break;
case 4: handling->Dimension.z = strtod(word, nil); break; case 4: bikeHandling->fLeanBakCOM = atof(word); break;
case 5: handling->CentreOfMass.x = strtod(word, nil); break; case 5: bikeHandling->fLeanBackForce = atof(word); break;
case 6: handling->CentreOfMass.y = strtod(word, nil); break; case 6: bikeHandling->fMaxLean = atof(word); break;
case 7: handling->CentreOfMass.z = strtod(word, nil); break; case 7: bikeHandling->fFullAnimLean = atof(word); break;
case 8: handling->nPercentSubmerged = atoi(word); break; case 8: bikeHandling->fDesLean = atof(word); break;
case 9: handling->fTractionMultiplier = strtod(word, nil); break; case 9: bikeHandling->fSpeedSteer = atof(word); break;
case 10: handling->fTractionLoss = strtod(word, nil); break; case 10: bikeHandling->fSlipSteer = atof(word); break;
case 11: handling->fTractionBias = strtod(word, nil); break; case 11: bikeHandling->fNoPlayerCOMz = atof(word); break;
case 12: handling->Transmission.nNumberOfGears = atoi(word); break; case 12: bikeHandling->fWheelieAng = atof(word); break;
case 13: handling->Transmission.fMaxVelocity = strtod(word, nil); break; case 13: bikeHandling->fStoppieAng = atof(word); break;
case 14: handling->Transmission.fEngineAcceleration = strtod(word, nil) * 0.4f; break; case 14: bikeHandling->fWheelieSteer = atof(word); break;
case 15: handling->Transmission.nDriveType = word[0]; break; case 15: bikeHandling->fWheelieStabMult = atof(word); break;
case 16: handling->Transmission.nEngineType = word[0]; break; case 16: bikeHandling->fStoppieStabMult = atof(word); break;
case 17: handling->fBrakeDeceleration = strtod(word, nil); break; }
case 18: handling->fBrakeBias = strtod(word, nil); break; field++;
case 19: handling->bABS = !!atoi(word); break;
case 20: handling->fSteeringLock = strtod(word, nil); break;
case 21: handling->fSuspensionForceLevel = strtod(word, nil); break;
case 22: handling->fSuspensionDampingLevel = strtod(word, nil); break;
case 23: handling->fSeatOffsetDistance = strtod(word, nil); break;
case 24: handling->fCollisionDamageMultiplier = strtod(word, nil); break;
case 25: handling->nMonetaryValue = atoi(word); break;
case 26: handling->fSuspensionUpperLimit = strtod(word, nil); break;
case 27: handling->fSuspensionLowerLimit = strtod(word, nil); break;
case 28: handling->fSuspensionBias = strtod(word, nil); break;
case 29:
// TODO(MIAMI): suspension anti-dive multiplier
break;
case 30:
sscanf(word, "%x", &handling->Flags);
handling->Transmission.Flags = handling->Flags;
break;
case 31: handling->FrontLights = atoi(word); break;
case 32: handling->RearLights = atoi(word); break;
} }
field++; ConvertBikeDataToGameUnits(bikeHandling);
}else if(line[0] == '$'){
// Flying data
field = 0;
strcpy(delim, " \t");
// FIX: game seems to use a do-while loop here
for(word = strtok(line, delim); word; word = strtok(nil, delim)){
switch(field){
case 0: break;
case 1:
handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
flyingHandling = GetFlyingPointer(handlingId);
flyingHandling->nIdentifier = (eHandlingId)handlingId;
break;
case 2: flyingHandling->fThrust = atof(word); break;
case 3: flyingHandling->fThrustFallOff = atof(word); break;
case 4: flyingHandling->fYaw = atof(word); break;
case 5: flyingHandling->fYawStab = atof(word); break;
case 6: flyingHandling->fSideSlip = atof(word); break;
case 7: flyingHandling->fRoll = atof(word); break;
case 8: flyingHandling->fRollStab = atof(word); break;
case 9: flyingHandling->fPitch = atof(word); break;
case 10: flyingHandling->fPitchStab = atof(word); break;
case 11: flyingHandling->fFormLift = atof(word); break;
case 12: flyingHandling->fAttackLift = atof(word); break;
case 13: flyingHandling->fMoveRes = atof(word); break;
case 14: flyingHandling->vecTurnRes.x = atof(word); break;
case 15: flyingHandling->vecTurnRes.y = atof(word); break;
case 16: flyingHandling->vecTurnRes.z = atof(word); break;
case 17: flyingHandling->vecSpeedRes.x = atof(word); break;
case 18: flyingHandling->vecSpeedRes.y = atof(word); break;
case 19: flyingHandling->vecSpeedRes.z = atof(word); break;
}
field++;
}
}else if(line[0] == '%'){
// Boat data
field = 0;
strcpy(delim, " \t");
// FIX: game seems to use a do-while loop here
for(word = strtok(line, delim); word; word = strtok(nil, delim)){
switch(field){
case 0: break;
case 1:
handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
boatHandling = GetBoatPointer(handlingId);
boatHandling->nIdentifier = (eHandlingId)handlingId;
break;
case 2: boatHandling->fThrustY = atof(word); break;
case 3: boatHandling->fThrustZ = atof(word); break;
case 4: boatHandling->fThrustAppZ = atof(word); break;
case 5: boatHandling->fAqPlaneForce = atof(word); break;
case 6: boatHandling->fAqPlaneLimit = atof(word); break;
case 7: boatHandling->fAqPlaneOffset = atof(word); break;
case 8: boatHandling->fWaveAudioMult = atof(word); break;
case 9: boatHandling->vecMoveRes.x = atof(word); break;
case 10: boatHandling->vecMoveRes.y = atof(word); break;
case 11: boatHandling->vecMoveRes.z = atof(word); break;
case 12: boatHandling->vecTurnRes.x = atof(word); break;
case 13: boatHandling->vecTurnRes.y = atof(word); break;
case 14: boatHandling->vecTurnRes.z = atof(word); break;
case 15: boatHandling->fLook_L_R_BehindCamHeight = atof(word); break;
}
field++;
}
}else{
field = 0;
strcpy(delim, " \t");
// FIX: game seems to use a do-while loop here
for(word = strtok(line, delim); word; word = strtok(nil, delim)){
switch(field){
case 0:
handlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);
assert(handlingId >= 0 && handlingId < NUMHANDLINGS);
handling = &HandlingData[handlingId];
handling->nIdentifier = (eHandlingId)handlingId;
break;
case 1: handling->fMass = atof(word); break;
case 2: handling->Dimension.x = atof(word); break;
case 3: handling->Dimension.y = atof(word); break;
case 4: handling->Dimension.z = atof(word); break;
case 5: handling->CentreOfMass.x = atof(word); break;
case 6: handling->CentreOfMass.y = atof(word); break;
case 7: handling->CentreOfMass.z = atof(word); break;
case 8: handling->nPercentSubmerged = atoi(word); break;
case 9: handling->fTractionMultiplier = atof(word); break;
case 10: handling->fTractionLoss = atof(word); break;
case 11: handling->fTractionBias = atof(word); break;
case 12: handling->Transmission.nNumberOfGears = atoi(word); break;
case 13: handling->Transmission.fMaxVelocity = atof(word); break;
case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4f; break;
case 15: handling->Transmission.nDriveType = word[0]; break;
case 16: handling->Transmission.nEngineType = word[0]; break;
case 17: handling->fBrakeDeceleration = atof(word); break;
case 18: handling->fBrakeBias = atof(word); break;
case 19: handling->bABS = !!atoi(word); break;
case 20: handling->fSteeringLock = atof(word); break;
case 21: handling->fSuspensionForceLevel = atof(word); break;
case 22: handling->fSuspensionDampingLevel = atof(word); break;
case 23: handling->fSeatOffsetDistance = atof(word); break;
case 24: handling->fCollisionDamageMultiplier = atof(word); break;
case 25: handling->nMonetaryValue = atoi(word); break;
case 26: handling->fSuspensionUpperLimit = atof(word); break;
case 27: handling->fSuspensionLowerLimit = atof(word); break;
case 28: handling->fSuspensionBias = atof(word); break;
case 29: handling->fSuspensionAntidiveMultiplier = atof(word); break;
case 30:
sscanf(word, "%x", &handling->Flags);
handling->Transmission.Flags = handling->Flags;
break;
case 31: handling->FrontLights = atoi(word); break;
case 32: handling->RearLights = atoi(word); break;
}
field++;
}
ConvertDataToGameUnits(handling);
} }
ConvertDataToGameUnits(handling);
} }
} }
} }
@ -253,6 +356,7 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
if(handling->fTurnMass < 10.0f) if(handling->fTurnMass < 10.0f)
handling->fTurnMass *= 5.0f; handling->fTurnMass *= 5.0f;
handling->fInvMass = 1.0f/handling->fMass; handling->fInvMass = 1.0f/handling->fMass;
handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008f*handling->fMass; handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008f*handling->fMass;
// What the hell is going on here? // What the hell is going on here?
@ -268,11 +372,16 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
if(handling->nIdentifier == HANDLING_RCBANDIT){ if(handling->nIdentifier == HANDLING_RCBANDIT){
handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity; handling->Transmission.fUnkMaxVelocity = handling->Transmission.fMaxVelocity;
handling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity;
}else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){
handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.05f;
}else{ }else{
handling->Transmission.fUnkMaxVelocity = velocity; handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f; handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.2f;
} }
handling->Transmission.fMaxReverseVelocity = -0.2f;
if(handling->Transmission.nDriveType == '4') if(handling->Transmission.nDriveType == '4')
handling->Transmission.fEngineAcceleration /= 4.0f; handling->Transmission.fEngineAcceleration /= 4.0f;
@ -282,6 +391,15 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
handling->Transmission.InitGearRatios(); handling->Transmission.InitGearRatios();
} }
void
cHandlingDataMgr::ConvertBikeDataToGameUnits(tBikeHandlingData *handling)
{
handling->fMaxLean = Sin(DEGTORAD(handling->fMaxLean));
handling->fFullAnimLean = DEGTORAD(handling->fFullAnimLean);
handling->fWheelieAng = Sin(DEGTORAD(handling->fWheelieAng));
handling->fStoppieAng = Sin(DEGTORAD(handling->fStoppieAng));
}
int32 int32
cHandlingDataMgr::GetHandlingId(const char *name) cHandlingDataMgr::GetHandlingId(const char *name)
{ {
@ -291,3 +409,19 @@ cHandlingDataMgr::GetHandlingId(const char *name)
break; break;
return i; return i;
} }
tFlyingHandlingData*
cHandlingDataMgr::GetFlyingPointer(uint8 id)
{
if(id >= HANDLING_SEAPLANE && id <= HANDLING_RCCOPTER)
return &FlyingHandlingData[id-HANDLING_SEAPLANE];
return &FlyingHandlingData[0];
}
tBoatHandlingData*
cHandlingDataMgr::GetBoatPointer(uint8 id)
{
if(id >= HANDLING_PREDATOR && id <= HANDLING_SEAPLANE)
return &BoatHandlingData[id-HANDLING_PREDATOR];
return &BoatHandlingData[0];
}

View File

@ -85,11 +85,13 @@ enum eHandlingId
HANDLING_LOVEFIST, HANDLING_LOVEFIST,
HANDLING_BLOODRA, HANDLING_BLOODRA,
HANDLING_BLOODRB, HANDLING_BLOODRB,
HANDLING_BIKE, HANDLING_BIKE,
HANDLING_MOPED, HANDLING_MOPED,
HANDLING_DIRTBIKE, HANDLING_DIRTBIKE,
HANDLING_ANGEL, HANDLING_ANGEL,
HANDLING_FREEWAY, HANDLING_FREEWAY,
HANDLING_PREDATOR, HANDLING_PREDATOR,
HANDLING_SPEEDER, HANDLING_SPEEDER,
HANDLING_REEFER, HANDLING_REEFER,
@ -100,7 +102,7 @@ enum eHandlingId
HANDLING_DINGHY, HANDLING_DINGHY,
HANDLING_MARQUIS, HANDLING_MARQUIS,
HANDLING_CUPBOAT, HANDLING_CUPBOAT,
HANDLING_SEAPLANE, HANDLING_SEAPLANE, // both boat and plane!
HANDLING_SPARROW, HANDLING_SPARROW,
HANDLING_SEASPAR, HANDLING_SEASPAR,
HANDLING_MAVERICK, HANDLING_MAVERICK,
@ -109,7 +111,13 @@ enum eHandlingId
HANDLING_HUNTER, HANDLING_HUNTER,
HANDLING_RCBARON, HANDLING_RCBARON,
HANDLING_RCGOBLIN, HANDLING_RCGOBLIN,
HANDLING_RCCOPTER HANDLING_RCCOPTER,
NUMHANDLINGS,
NUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE,
NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_SEAPLANE,
NUMBOATHANDLINGS = HANDLING_SEAPLANE+1 - HANDLING_PREDATOR,
}; };
enum enum
@ -168,6 +176,7 @@ struct tHandlingData
float fSuspensionUpperLimit; float fSuspensionUpperLimit;
float fSuspensionLowerLimit; float fSuspensionLowerLimit;
float fSuspensionBias; float fSuspensionBias;
float fSuspensionAntidiveMultiplier;
float fCollisionDamageMultiplier; float fCollisionDamageMultiplier;
uint32 Flags; uint32 Flags;
float fSeatOffsetDistance; float fSeatOffsetDistance;
@ -175,19 +184,74 @@ struct tHandlingData
int8 FrontLights; int8 FrontLights;
int8 RearLights; int8 RearLights;
}; };
VALIDATE_SIZE(tHandlingData, 0xD8);
struct tBikeHandlingData
{
eHandlingId nIdentifier;
float fLeanFwdCOM;
float fLeanFwdForce;
float fLeanBakCOM;
float fLeanBackForce;
float fMaxLean;
float fFullAnimLean;
float fDesLean;
float fSpeedSteer;
float fSlipSteer;
float fNoPlayerCOMz;
float fWheelieAng;
float fStoppieAng;
float fWheelieSteer;
float fWheelieStabMult;
float fStoppieStabMult;
};
struct tBoatHandlingData
{
eHandlingId nIdentifier;
float fThrustY;
float fThrustZ;
float fThrustAppZ;
float fAqPlaneForce;
float fAqPlaneLimit;
float fAqPlaneOffset;
float fWaveAudioMult;
float fLook_L_R_BehindCamHeight;
CVector vecMoveRes;
CVector vecTurnRes;
};
struct tFlyingHandlingData
{
eHandlingId nIdentifier;
float fThrust;
float fThrustFallOff;
float fYaw;
float fYawStab;
float fSideSlip;
float fRoll;
float fRollStab;
float fPitch;
float fPitchStab;
float fFormLift;
float fAttackLift;
float fMoveRes;
CVector vecTurnRes;
CVector vecSpeedRes;
};
class cHandlingDataMgr class cHandlingDataMgr
{ {
float field_0; // unused it seems float field_0; // unused it seems
public: public:
float field_4; // wheel related float fWheelFriction;
private: private:
float field_8; // float field_8; //
float field_C; // unused it seems float field_C; // unused it seems
float field_10; // float field_10; //
tHandlingData HandlingData[NUMHANDLINGS]; tHandlingData HandlingData[NUMHANDLINGS];
uint32 field_302C; // unused it seems tBikeHandlingData BikeHandlingData[NUMBIKEHANDLINGS];
tFlyingHandlingData FlyingHandlingData[NUMFLYINGHANDLINGS];
tBoatHandlingData BoatHandlingData[NUMBOATHANDLINGS];
public: public:
cHandlingDataMgr(void); cHandlingDataMgr(void);
@ -195,8 +259,12 @@ public:
void LoadHandlingData(void); void LoadHandlingData(void);
int FindExactWord(const char *word, const char *words, int wordLen, int numWords); int FindExactWord(const char *word, const char *words, int wordLen, int numWords);
void ConvertDataToGameUnits(tHandlingData *handling); void ConvertDataToGameUnits(tHandlingData *handling);
void ConvertBikeDataToGameUnits(tBikeHandlingData *handling);
int32 GetHandlingId(const char *name); int32 GetHandlingId(const char *name);
tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; } tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; }
tBikeHandlingData *GetBikePointer(uint8 id) { return &BikeHandlingData[id-HANDLING_BIKE]; }
tFlyingHandlingData *GetFlyingPointer(uint8 id);
tBoatHandlingData *GetBoatPointer(uint8 id);
bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; } bool HasRearWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'R'; }
bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; } bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; }
}; };

View File

@ -29,6 +29,7 @@ bool CVehicle::bCheat5;
bool CVehicle::bAltDodoCheat; bool CVehicle::bAltDodoCheat;
#endif #endif
bool CVehicle::m_bDisableMouseSteering = true; bool CVehicle::m_bDisableMouseSteering = true;
bool CVehicle::bDisableRemoteDetonation;
void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); }
void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); }
@ -493,6 +494,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(contactSpeedRight != 0.0f){ if(contactSpeedRight != 0.0f){
// exert opposing force // exert opposing force
right = -contactSpeedRight/wheelsOnGround; right = -contactSpeedRight/wheelsOnGround;
#ifdef FIX_BUGS
// contactSpeedRight is independent of framerate but right has timestep as a factor
// so we probably have to fix this
right *= CTimer::GetTimeStepFix();
#endif
if(wheelStatus == WHEEL_STATUS_BURST){ if(wheelStatus == WHEEL_STATUS_BURST){
float fwdspeed = Min(contactSpeedFwd, 0.3f); float fwdspeed = Min(contactSpeedFwd, 0.3f);
@ -513,13 +519,21 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
} }
}else if(contactSpeedFwd != 0.0f){ }else if(contactSpeedFwd != 0.0f){
fwd = -contactSpeedFwd/wheelsOnGround; fwd = -contactSpeedFwd/wheelsOnGround;
#ifdef FIX_BUGS
// contactSpeedFwd is independent of framerate but fwd has timestep as a factor
// so we probably have to fix this
fwd *= CTimer::GetTimeStepFix();
#endif
if(!bBraking){ if(!bBraking){
if(m_fGasPedal < 0.01f){ if(m_fGasPedal < 0.01f){
if(GetModelIndex() == MI_RCBANDIT) if(GetModelIndex() == MI_RCBANDIT)
brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
else else
brake = mod_HandlingManager.field_4 / m_fMass; brake = mod_HandlingManager.fWheelFriction / m_fMass;
#ifdef FIX_BUGS
brake *= CTimer::GetTimeStepFix();
#endif
} }
} }
@ -1080,14 +1094,14 @@ CVehicle::SetDriver(CPed *driver)
if(bFreebies && driver == FindPlayerPed()){ if(bFreebies && driver == FindPlayerPed()){
if(GetModelIndex() == MI_AMBULAN) if(GetModelIndex() == MI_AMBULAN)
FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f); FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth);
else if(GetModelIndex() == MI_TAXI) else if(GetModelIndex() == MI_TAXI)
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
else if (GetModelIndex() == MI_POLICE) { else if (GetModelIndex() == MI_POLICE) {
CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5); driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
} else if (GetModelIndex() == MI_ENFORCER) } else if (GetModelIndex() == MI_ENFORCER)
driver->m_fArmour = Max(driver->m_fArmour, 100.0f); driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour);
else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
bFreebies = false; bFreebies = false;
@ -1353,14 +1367,29 @@ eVehicleAppearance
CVehicle::GetVehicleAppearance(void) CVehicle::GetVehicleAppearance(void)
{ {
if (IsCar()) if (IsCar())
return VEHICLE_CAR; return VEHICLE_APPEARANCE_CAR;
if (IsBoat()) if (IsBoat())
return VEHICLE_BOAT; return VEHICLE_APPEARANCE_BOAT;
if (IsBike()) if (IsBike())
return VEHICLE_BIKE; return VEHICLE_APPEARANCE_BIKE;
if (IsPlane()) if (IsPlane())
return VEHICLE_PLANE; return VEHICLE_APPEARANCE_PLANE;
if (IsHeli()) if (IsHeli())
return VEHICLE_HELI; return VEHICLE_APPEARANCE_HELI;
return VEHICLE_NONE; return VEHICLE_APPEARANCE_NONE;
}
bool
IsVehiclePointerValid(CVehicle* pVehicle)
{
if (!pVehicle)
return false;
int index = CPools::GetVehiclePool()->GetJustIndex(pVehicle);
#ifdef FIX_BUGS
if (index < 0 || index >= NUMVEHICLES)
#else
if (index < 0 || index > NUMVEHICLES)
#endif
return false;
return pVehicle->m_vehType == VEHICLE_TYPE_PLANE || pVehicle->m_entryInfoList.first;
} }

View File

@ -112,12 +112,12 @@ enum eFlightModel
enum eVehicleAppearance enum eVehicleAppearance
{ {
VEHICLE_NONE, VEHICLE_APPEARANCE_NONE,
VEHICLE_CAR, VEHICLE_APPEARANCE_CAR,
VEHICLE_BIKE, VEHICLE_APPEARANCE_BIKE,
VEHICLE_HELI, VEHICLE_APPEARANCE_HELI,
VEHICLE_BOAT, VEHICLE_APPEARANCE_BOAT,
VEHICLE_PLANE, VEHICLE_APPEARANCE_PLANE,
}; };
// Or Weapon.h? // Or Weapon.h?
@ -311,6 +311,8 @@ public:
static bool bAltDodoCheat; static bool bAltDodoCheat;
#endif #endif
static bool m_bDisableMouseSteering; static bool m_bDisableMouseSteering;
static bool bDisableRemoteDetonation;
}; };
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle); void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);
bool IsVehiclePointerValid(CVehicle* pVehicle);