summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.h1
-rw-r--r--src/control/HandlingDataMgr.cpp242
-rw-r--r--src/control/HandlingDataMgr.h130
-rw-r--r--src/control/ObjectData.cpp2
-rw-r--r--src/control/Transmission.cpp37
-rw-r--r--src/control/Transmission.h26
-rw-r--r--src/entities/Building.cpp21
-rw-r--r--src/entities/Building.h3
8 files changed, 457 insertions, 5 deletions
diff --git a/src/config.h b/src/config.h
index 71689778..933aa53f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -42,7 +42,6 @@ enum Config {
NUMATTRIBZONES = 288,
NUMZONEINDICES = 55000,
- NUMPEDSTATS = 35,
NUMHANDLINGS = 57,
PATHNODESIZE = 4500,
diff --git a/src/control/HandlingDataMgr.cpp b/src/control/HandlingDataMgr.cpp
index 94824358..48000b48 100644
--- a/src/control/HandlingDataMgr.cpp
+++ b/src/control/HandlingDataMgr.cpp
@@ -1,7 +1,247 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
+#include "FileMgr.h"
#include "HandlingDatamgr.h"
cHandlingDataMgr &mod_HandlingManager = *(cHandlingDataMgr*)0x728060;
-WRAPPER int32 cHandlingDataMgr::GetHandlingId(const char *name){ EAXJMP(0x546B70); }
+char *HandlingFilename = "HANDLING.CFG";
+
+char VehicleNames[NUMHANDLINGS][14] = {
+ "LANDSTAL",
+ "IDAHO",
+ "STINGER",
+ "LINERUN",
+ "PEREN",
+ "SENTINEL",
+ "PATRIOT",
+ "FIRETRUK",
+ "TRASH",
+ "STRETCH",
+ "MANANA",
+ "INFERNUS",
+ "BLISTA",
+ "PONY",
+ "MULE",
+ "CHEETAH",
+ "AMBULAN",
+ "FBICAR",
+ "MOONBEAM",
+ "ESPERANT",
+ "TAXI",
+ "KURUMA",
+ "BOBCAT",
+ "MRWHOOP",
+ "BFINJECT",
+ "POLICE",
+ "ENFORCER",
+ "SECURICA",
+ "BANSHEE",
+ "PREDATOR",
+ "BUS",
+ "RHINO",
+ "BARRACKS",
+ "TRAIN",
+ "HELI",
+ "DODO",
+ "COACH",
+ "CABBIE",
+ "STALLION",
+ "RUMPO",
+ "RCBANDIT",
+ "BELLYUP",
+ "MRWONGS",
+ "MAFIA",
+ "YARDIE",
+ "YAKUZA",
+ "DIABLOS",
+ "COLUMB",
+ "HOODS",
+ "AIRTRAIN",
+ "DEADDODO",
+ "SPEEDER",
+ "REEFER",
+ "PANLANT",
+ "FLATBED",
+ "YANKEE",
+ "BORGNINE"
+};
+
+cHandlingDataMgr::cHandlingDataMgr(void)
+{
+ memset(this, 0, sizeof(this));
+}
+
+void
+cHandlingDataMgr::Initialise(void)
+{
+ LoadHandlingData();
+ field_0 = 0.1f;
+ field_4 = 0.9f;
+ field_8 = 1.0f;
+ field_C = 0.8f;
+ field_10 = 0.98f;
+}
+
+void
+cHandlingDataMgr::LoadHandlingData(void)
+{
+ char *start, *end;
+ char line[201]; // weird value
+ char delim[4]; // not sure
+ char *word;
+ int field, handlingId;
+ int keepGoing;
+ tHandlingData *handling;
+
+ CFileMgr::SetDir("DATA");
+ CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
+ CFileMgr::SetDir("");
+
+ start = (char*)work_buff;
+ end = start+1;
+ handling = nil;
+ keepGoing = 1;
+
+ while(keepGoing){
+ // find end of line
+ while(*end != '\n') end++;
+
+ // get line
+ strncpy(line, start, end - start);
+ line[end - start] = '\0';
+ start = end+1;
+ end = start+1;
+
+ // yeah, this is kinda crappy
+ if(strncmp(line, ";the end", 9) == 0)
+ keepGoing = 0;
+ else if(line[0] != ';'){
+ 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 = handlingId;
+ break;
+ case 1: handling->fMass = strtod(word, nil); break;
+ case 2: handling->Dimension.x = strtod(word, nil); break;
+ case 3: handling->Dimension.y = strtod(word, nil); break;
+ case 4: handling->Dimension.z = strtod(word, nil); break;
+ case 5: handling->CentreOfMass.x = strtod(word, nil); break;
+ case 6: handling->CentreOfMass.y = strtod(word, nil); break;
+ case 7: handling->CentreOfMass.z = strtod(word, nil); break;
+ case 8: handling->nPercentSubmerged = atoi(word); break;
+ case 9: handling->fTractionMultiplier = strtod(word, nil); break;
+ case 10: handling->fTractionLoss = strtod(word, nil); break;
+ case 11: handling->fTractionBias = strtod(word, nil); break;
+ case 12: handling->TransmissionData.nNumberOfGears = atoi(word); break;
+ case 13: handling->TransmissionData.fMaxVelocity = strtod(word, nil); break;
+ case 14: handling->TransmissionData.fEngineAcceleration = strtod(word, nil) * 0.4f; break;
+ case 15: handling->TransmissionData.nDriveType = word[0]; break;
+ case 16: handling->TransmissionData.nEngineType = word[0]; break;
+ case 17: handling->fBrakeDeceleration = strtod(word, nil); break;
+ case 18: handling->fBrakeBias = strtod(word, nil); break;
+ 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:
+ sscanf(word, "%x", &handling->Flags);
+ handling->TransmissionData.Flags = handling->Flags;
+ break;
+ case 30: handling->FrontLights = atoi(word); break;
+ case 31: handling->RearLights = atoi(word); break;
+ }
+ field++;
+ }
+ ConvertDataToGameUnits(handling);
+ }
+ }
+}
+
+int
+cHandlingDataMgr::FindExactWord(const char *word, const char *words, int wordLen, int numWords)
+{
+ int i;
+
+ for(i = 0; i < numWords; i++){
+ // BUG: the game does something really stupid here, it's fixed here
+ if(strncmp(word, words, wordLen) == 0)
+ return i;
+ words += wordLen;
+ }
+ return numWords;
+}
+
+
+void
+cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
+{
+ // TODO: figure out what exactly is being converted here
+ float velocity, a, b, specificVolume;
+
+ handling->TransmissionData.fEngineAcceleration /= 2500.0f;
+ handling->TransmissionData.fMaxVelocity /= 180.0f;
+ handling->fBrakeDeceleration /= 2500.0f;
+ handling->fTurnMass = (sq(handling->Dimension.x) + sq(handling->Dimension.y)) * handling->fMass / 12.0f;
+ if(handling->fTurnMass < 10.0f)
+ handling->fTurnMass *= 5.0f;
+ handling->fInvMass = 1.0f/handling->fMass;
+ handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008*handling->fMass;
+
+ // What the hell is going on here?
+ specificVolume = handling->Dimension.x*handling->Dimension.z*0.5f / handling->fMass; // ?
+ a = 0.0f;
+ b = 100.0f;
+ velocity = handling->TransmissionData.fMaxVelocity;
+ while(a < b && velocity > 0.0f){
+ velocity -= 0.01;
+ a = handling->TransmissionData.fEngineAcceleration/6.0f;
+ b = -velocity * (1.0f/(specificVolume * sq(velocity) + 1.0f) - 1.0f);
+ }
+
+ if(handling->nIdentifier == HANDLING_RCBANDIT){
+ handling->TransmissionData.fUnkMaxVelocity = handling->TransmissionData.fMaxVelocity;
+ }else{
+ handling->TransmissionData.fUnkMaxVelocity = velocity;
+ handling->TransmissionData.fMaxVelocity = velocity * 1.2f;
+ }
+ handling->TransmissionData.fMaxReverseVelocity = -0.2f;
+
+ if(handling->TransmissionData.nDriveType == '4')
+ handling->TransmissionData.fEngineAcceleration /= 4.0f;
+ else
+ handling->TransmissionData.fEngineAcceleration /= 2.0f;
+
+ handling->TransmissionData.InitGearRatios();
+}
+
+int32
+cHandlingDataMgr::GetHandlingId(const char *name)
+{
+ int i;
+ for(i = 0; i < NUMHANDLINGS; i++)
+ if(strncmp(VehicleNames[i], name, 14) == 0)
+ break;
+ return i;
+}
+
+STARTPATCHES
+ InjectHook(0x546D80, &cHandlingDataMgr::Initialise, PATCH_JUMP);
+ InjectHook(0x546DB0, &cHandlingDataMgr::LoadHandlingData, PATCH_JUMP);
+ InjectHook(0x546BB0, &cHandlingDataMgr::ConvertDataToGameUnits, PATCH_JUMP);
+ InjectHook(0x546AA0, &cHandlingDataMgr::FindExactWord, PATCH_JUMP);
+ InjectHook(0x546B70, &cHandlingDataMgr::GetHandlingId, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/control/HandlingDataMgr.h b/src/control/HandlingDataMgr.h
index 00e62b59..216aa7e8 100644
--- a/src/control/HandlingDataMgr.h
+++ b/src/control/HandlingDataMgr.h
@@ -1,8 +1,138 @@
#pragma once
+#include "Transmission.h"
+
+enum eHandlingId
+{
+ HANDLING_LANDSTAL,
+ HANDLING_IDAHO,
+ HANDLING_STINGER,
+ HANDLING_LINERUN,
+ HANDLING_PEREN,
+ HANDLING_SENTINEL,
+ HANDLING_PATRIOT,
+ HANDLING_FIRETRUK,
+ HANDLING_TRASH,
+ HANDLING_STRETCH,
+ HANDLING_MANANA,
+ HANDLING_INFERNUS,
+ HANDLING_BLISTA,
+ HANDLING_PONY,
+ HANDLING_MULE,
+ HANDLING_CHEETAH,
+ HANDLING_AMBULAN,
+ HANDLING_FBICAR,
+ HANDLING_MOONBEAM,
+ HANDLING_ESPERANT,
+ HANDLING_TAXI,
+ HANDLING_KURUMA,
+ HANDLING_BOBCAT,
+ HANDLING_MRWHOOP,
+ HANDLING_BFINJECT,
+ HANDLING_POLICE,
+ HANDLING_ENFORCER,
+ HANDLING_SECURICA,
+ HANDLING_BANSHEE,
+ HANDLING_PREDATOR,
+ HANDLING_BUS,
+ HANDLING_RHINO,
+ HANDLING_BARRACKS,
+ HANDLING_TRAIN,
+ HANDLING_HELI,
+ HANDLING_DODO,
+ HANDLING_COACH,
+ HANDLING_CABBIE,
+ HANDLING_STALLION,
+ HANDLING_RUMPO,
+ HANDLING_RCBANDIT,
+ HANDLING_BELLYUP,
+ HANDLING_MRWONGS,
+ HANDLING_MAFIA,
+ HANDLING_YARDIE,
+ HANDLING_YAKUZA,
+ HANDLING_DIABLOS,
+ HANDLING_COLUMB,
+ HANDLING_HOODS,
+ HANDLING_AIRTRAIN,
+ HANDLING_DEADDODO,
+ HANDLING_SPEEDER,
+ HANDLING_REEFER,
+ HANDLING_PANLANT,
+ HANDLING_FLATBED,
+ HANDLING_YANKEE,
+ HANDLING_BORGNINE
+};
+
+enum
+{
+ HANDLING_1G_BOOST = 1,
+ HANDLING_2G_BOOST = 2,
+ HANDLING_REV_BONNET = 4,
+ HANDLING_HANGING_BOOT = 8,
+ HANDLING_NO_DOORS = 0x10,
+ HANDLING_IS_VAN = 0x20,
+ HANDLING_IS_BUS = 0x40,
+ HANDLING_IS_LOW = 0x80,
+ HANDLING_DBL_EXHAUST = 0x100,
+ HANDLING_TAILGATE_BOOT = 0x200,
+ HANDLING_NOSWING_BOOT = 0x400,
+ HANDLING_NONPLAYER_STABILISER = 0x800,
+ HANDLING_NEUTRALHANDLING = 0x1000,
+ HANDLING_HAS_NO_ROOF = 0x2000,
+ HANDLING_IS_BIG = 0x4000,
+ HANDLING_HALOGEN_LIGHTS = 0x8000,
+};
+
+struct tHandlingData
+{
+ int32 nIdentifier;
+ float fMass;
+ float fInvMass;
+ float fTurnMass;
+ CVector Dimension;
+ CVector CentreOfMass;
+ int8 nPercentSubmerged;
+ float fBuoyancy;
+ float fTractionMultiplier;
+ cTransmission TransmissionData;
+ float fBrakeDeceleration;
+ float fBrakeBias;
+ int8 bABS;
+ float fSteeringLock;
+ float fTractionLoss;
+ float fTractionBias;
+ uint32 field_AC;
+ float fSuspensionForceLevel;
+ float fSuspensionDampingLevel;
+ float fSuspensionUpperLimit;
+ float fSuspensionLowerLimit;
+ float fSuspensionBias;
+ float fCollisionDamageMultiplier;
+ uint32 Flags;
+ float fSeatOffsetDistance;
+ int32 nMonetaryValue;
+ int8 FrontLights;
+ int8 RearLights;
+};
+VALIDATE_SIZE(tHandlingData, 0xD8);
+
class cHandlingDataMgr
{
+ float field_0; // unused it seems
+ float field_4; // wheel related
+ float field_8; //
+ float field_C; // unused it seems
+ float field_10; //
+ tHandlingData HandlingData[NUMHANDLINGS];
+ uint32 field_302C; // unused it seems, padding?
+
public:
+ cHandlingDataMgr(void);
+ void Initialise(void);
+ void LoadHandlingData(void);
+ int FindExactWord(const char *word, const char *words, int wordLen, int numWords);
+ void ConvertDataToGameUnits(tHandlingData *handling);
int32 GetHandlingId(const char *name);
};
+VALIDATE_SIZE(cHandlingDataMgr, 0x3030);
extern cHandlingDataMgr &mod_HandlingManager;
diff --git a/src/control/ObjectData.cpp b/src/control/ObjectData.cpp
index a0838007..ef5bcc5e 100644
--- a/src/control/ObjectData.cpp
+++ b/src/control/ObjectData.cpp
@@ -20,7 +20,7 @@ CObjectData::Initialise(const char *filename)
CBaseModelInfo *mi;
CFileMgr::SetDir("");
- CFileMgr::LoadFile(filename, work_buff, 55000, "r");
+ CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
id = 0;
p = (char*)work_buff;
diff --git a/src/control/Transmission.cpp b/src/control/Transmission.cpp
new file mode 100644
index 00000000..2be25cbb
--- /dev/null
+++ b/src/control/Transmission.cpp
@@ -0,0 +1,37 @@
+#include "common.h"
+#include "patcher.h"
+#include "Transmission.h"
+
+void
+cTransmission::InitGearRatios(void)
+{
+ static tGear *pGearRatio0 = nil;
+ static tGear *pGearRatio1 = nil;
+ int i;
+ float velocityDiff;
+
+ memset(Gears, 0, sizeof(Gears));
+
+ for(i = 1; i <= nNumberOfGears; i++){
+ pGearRatio0 = &Gears[i-1];
+ pGearRatio1 = &Gears[i];
+
+ pGearRatio1->fMaxVelocity = (float)i / nNumberOfGears * fMaxVelocity;
+
+ velocityDiff = pGearRatio1->fMaxVelocity - pGearRatio0->fMaxVelocity;
+
+ if(i >= nNumberOfGears){
+ pGearRatio1->fShiftUpVelocity = fMaxVelocity;
+ }else{
+ Gears[i+1].fShiftDownVelocity = velocityDiff*0.42f + pGearRatio0->fMaxVelocity;
+ pGearRatio1->fShiftUpVelocity = velocityDiff*0.6667f + pGearRatio0->fMaxVelocity;
+ }
+ }
+
+ // Reverse gear
+ Gears[0].fMaxVelocity = fMaxReverseVelocity;
+ Gears[0].fShiftUpVelocity = -0.01f;
+ Gears[0].fShiftDownVelocity = fMaxReverseVelocity;
+
+ Gears[1].fShiftDownVelocity = -0.01f;
+}
diff --git a/src/control/Transmission.h b/src/control/Transmission.h
new file mode 100644
index 00000000..686e0aca
--- /dev/null
+++ b/src/control/Transmission.h
@@ -0,0 +1,26 @@
+#pragma once
+
+struct tGear
+{
+ float fMaxVelocity;
+ float fShiftUpVelocity;
+ float fShiftDownVelocity;
+};
+
+class cTransmission
+{
+public:
+ // Gear 0 is reverse, 1-5 are forward
+ tGear Gears[6];
+ char nDriveType;
+ char nEngineType;
+ int8 nNumberOfGears;
+ uint8 Flags;
+ float fEngineAcceleration;
+ float fMaxVelocity;
+ float fUnkMaxVelocity;
+ float fMaxReverseVelocity;
+ float field_5C;
+
+ void InitGearRatios(void);
+};
diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp
index e8f19b01..ef236e89 100644
--- a/src/entities/Building.cpp
+++ b/src/entities/Building.cpp
@@ -1,7 +1,26 @@
#include "common.h"
-#include "rpworld.h"
+#include "patcher.h"
#include "Building.h"
+#include "Streaming.h"
#include "Pools.h"
void *CBuilding::operator new(size_t sz) { return CPools::GetBuildingPool()->New(); }
void CBuilding::operator delete(void *p, size_t sz) { CPools::GetBuildingPool()->Delete((CBuilding*)p); }
+
+void
+CBuilding::ReplaceWithNewModel(int32 id)
+{
+ DeleteRwObject();
+
+ if(CModelInfo::GetModelInfo(m_modelIndex)->m_refCount == 0)
+ CStreaming::RemoveModel(m_modelIndex);
+ m_modelIndex = id;
+
+ if(bIsBIGBuilding)
+ if(m_level == LEVEL_NONE || m_level == CGame::currLevel)
+ CStreaming::RequestModel(id, STREAM_DONT_REMOVE);
+}
+
+STARTPATCHES
+ InjectHook(0x405850, &CBuilding::ReplaceWithNewModel, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/entities/Building.h b/src/entities/Building.h
index 612e0fb3..7b837f46 100644
--- a/src/entities/Building.h
+++ b/src/entities/Building.h
@@ -5,7 +5,6 @@
class CBuilding : public CEntity
{
public:
- // TODO: ReplaceWithNewModel
CBuilding(void) {
m_type = ENTITY_TYPE_BUILDING;
bUsesCollision = true;
@@ -13,6 +12,8 @@ public:
static void *operator new(size_t);
static void operator delete(void*, size_t);
+ void ReplaceWithNewModel(int32 id);
+
virtual bool GetIsATreadable(void) { return false; }
};
static_assert(sizeof(CBuilding) == 0x64, "CBuilding: error");