From 2fcdf6fa21a173dcc033fd03b6d08b46b916c2e7 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 19 Jun 2019 23:41:43 +0200 Subject: implemented cHandlingDataMgr --- src/config.h | 1 - src/control/HandlingDataMgr.cpp | 242 +++++++++++++++++++++++++++++++++++++++- src/control/HandlingDataMgr.h | 130 +++++++++++++++++++++ src/control/ObjectData.cpp | 2 +- src/control/Transmission.cpp | 37 ++++++ src/control/Transmission.h | 26 +++++ src/entities/Building.cpp | 21 +++- src/entities/Building.h | 3 +- 8 files changed, 457 insertions(+), 5 deletions(-) create mode 100644 src/control/Transmission.cpp create mode 100644 src/control/Transmission.h (limited to 'src') 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"); -- cgit v1.2.3