mirror of
https://github.com/halpz/re3.git
synced 2025-06-29 13:26:19 +00:00
Merge branch 'master' of https://github.com/gtamodding/re3
This commit is contained in:
@ -1,247 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "FileMgr.h"
|
||||
#include "HandlingMgr.h"
|
||||
|
||||
cHandlingDataMgr &mod_HandlingManager = *(cHandlingDataMgr*)0x728060;
|
||||
|
||||
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
|
@ -1,139 +0,0 @@
|
||||
#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);
|
||||
tHandlingData *GetHandlingData(eHandlingId id) { return &HandlingData[id]; }
|
||||
};
|
||||
VALIDATE_SIZE(cHandlingDataMgr, 0x3030);
|
||||
extern cHandlingDataMgr &mod_HandlingManager;
|
@ -1,103 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "ModelInfo.h"
|
||||
#include "Object.h"
|
||||
#include "FileMgr.h"
|
||||
#include "ObjectData.h"
|
||||
|
||||
CObjectInfo CObjectData::ms_aObjectInfo[NUMOBJECTINFO];
|
||||
|
||||
// Another ugly file reader
|
||||
void
|
||||
CObjectData::Initialise(const char *filename)
|
||||
{
|
||||
char *p, *lp;
|
||||
char line[1024], name[256];
|
||||
int id;
|
||||
float percentSubmerged;
|
||||
int damageEffect, responseCase, camAvoid;
|
||||
CBaseModelInfo *mi;
|
||||
|
||||
CFileMgr::SetDir("");
|
||||
CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
|
||||
|
||||
id = 0;
|
||||
p = (char*)work_buff;
|
||||
while(*p != '*'){
|
||||
// skip over white space and comments
|
||||
while(*p == ' ' || *p == '\n' || *p == '\r' || *p == ';')
|
||||
if(*p == ';')
|
||||
while(*p != '\n' && *p != '*')
|
||||
p++;
|
||||
else
|
||||
p++;
|
||||
|
||||
if(*p == '*')
|
||||
break;
|
||||
|
||||
// read one line
|
||||
lp = line;
|
||||
while(*p != '\n' && *p != '*'){
|
||||
*lp++ = *p == ',' ? ' ' : *p;
|
||||
p++;
|
||||
}
|
||||
if(*p == '\n')
|
||||
p++;
|
||||
*lp = '\0'; // FIX: game wrote '\n' here
|
||||
|
||||
assert(id < NUMOBJECTINFO);
|
||||
sscanf(line, "%s %f %f %f %f %f %f %f %d %d %d", name,
|
||||
&ms_aObjectInfo[id].m_fMass,
|
||||
&ms_aObjectInfo[id].m_fTurnMass,
|
||||
&ms_aObjectInfo[id].m_fAirResistance,
|
||||
&ms_aObjectInfo[id].m_fElasticity,
|
||||
&percentSubmerged,
|
||||
&ms_aObjectInfo[id].m_fUprootLimit,
|
||||
&ms_aObjectInfo[id].m_fCollisionDamageMultiplier,
|
||||
&damageEffect, &responseCase, &camAvoid);
|
||||
|
||||
ms_aObjectInfo[id].m_fBuoyancy = 100.0f/percentSubmerged * 0.008*ms_aObjectInfo[id].m_fMass;
|
||||
ms_aObjectInfo[id].m_nCollisionDamageEffect = damageEffect;
|
||||
ms_aObjectInfo[id].m_nSpecialCollisionResponseCases = responseCase;
|
||||
ms_aObjectInfo[id].m_bCameraToAvoidThisObject = camAvoid;
|
||||
|
||||
mi = CModelInfo::GetModelInfo(name, nil);
|
||||
if(mi)
|
||||
mi->SetObjectID(id++);
|
||||
else
|
||||
debug("CObjectData: Cannot find object %s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CObjectData::SetObjectData(int32 modelId, CObject &object)
|
||||
{
|
||||
CObjectInfo *objinfo;
|
||||
|
||||
if(CModelInfo::GetModelInfo(modelId)->GetObjectID() == -1)
|
||||
return;
|
||||
|
||||
objinfo = &ms_aObjectInfo[CModelInfo::GetModelInfo(modelId)->GetObjectID()];
|
||||
|
||||
object.m_fMass = objinfo->m_fMass;
|
||||
object.m_fTurnMass = objinfo->m_fTurnMass;
|
||||
object.m_fAirResistance = objinfo->m_fAirResistance;
|
||||
object.m_fElasticity = objinfo->m_fElasticity;
|
||||
object.m_fBuoyancy = objinfo->m_fBuoyancy;
|
||||
object.m_fUprootLimit = objinfo->m_fUprootLimit;
|
||||
object.m_fCollisionDamageMultiplier = objinfo->m_fCollisionDamageMultiplier;
|
||||
object.m_nCollisionDamageEffect = objinfo->m_nCollisionDamageEffect;
|
||||
object.m_nSpecialCollisionResponseCases = objinfo->m_nSpecialCollisionResponseCases;
|
||||
object.m_bCameraToAvoidThisObject = objinfo->m_bCameraToAvoidThisObject;
|
||||
if(object.m_fMass >= 99998.0){
|
||||
object.bInfiniteMass = true;
|
||||
object.bAffectedByGravity = false;
|
||||
object.m_flagB2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4BC0E0, CObjectData::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4BC270, CObjectData::SetObjectData, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class CObject;
|
||||
|
||||
class CObjectInfo
|
||||
{
|
||||
public:
|
||||
float m_fMass;
|
||||
float m_fTurnMass;
|
||||
float m_fAirResistance;
|
||||
float m_fElasticity;
|
||||
float m_fBuoyancy;
|
||||
float m_fUprootLimit;
|
||||
float m_fCollisionDamageMultiplier;
|
||||
uint8 m_nCollisionDamageEffect;
|
||||
uint8 m_nSpecialCollisionResponseCases;
|
||||
bool m_bCameraToAvoidThisObject;
|
||||
};
|
||||
static_assert(sizeof(CObjectInfo) == 0x20, "CObjectInfo: error");
|
||||
|
||||
class CObjectData
|
||||
{
|
||||
static CObjectInfo ms_aObjectInfo[NUMOBJECTINFO];
|
||||
public:
|
||||
static void Initialise(const char *filename);
|
||||
static void SetObjectData(int32 modelId, CObject &object);
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "PedPlacement.h"
|
||||
#include "World.h"
|
||||
|
||||
void
|
||||
CPedPlacement::FindZCoorForPed(CVector* pos)
|
||||
{
|
||||
float zForPed;
|
||||
float startZ = pos->z - 100.0f;
|
||||
float foundColZ = -100.0f;
|
||||
float foundColZ2 = -100.0f;
|
||||
CColPoint foundCol;
|
||||
CEntity* foundEnt;
|
||||
|
||||
CVector vec(
|
||||
pos->x,
|
||||
pos->y,
|
||||
pos->z + 1.0f
|
||||
);
|
||||
|
||||
if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))
|
||||
foundColZ = foundCol.point.z;
|
||||
|
||||
// Adjust coords and do a second test
|
||||
vec.x += 0.1f;
|
||||
vec.y += 0.1f;
|
||||
|
||||
if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))
|
||||
foundColZ2 = foundCol.point.z;
|
||||
|
||||
zForPed = max(foundColZ, foundColZ2);
|
||||
|
||||
if (zForPed > -99.0f)
|
||||
pos->z = 1.04f + zForPed;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4EE340, &CPedPlacement::FindZCoorForPed, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class CVector;
|
||||
|
||||
class CPedPlacement {
|
||||
public:
|
||||
static void FindZCoorForPed(CVector* pos);
|
||||
};
|
@ -1,125 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
#include "PedStats.h"
|
||||
|
||||
CPedStats *(&CPedStats::ms_apPedStats)[NUM_PEDSTATS] = *(CPedStats *(*)[NUM_PEDSTATS]) *(uintptr*)0x9404D4;
|
||||
|
||||
void
|
||||
CPedStats::Initialise(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug("Initialising CPedStats...\n");
|
||||
for(i = 0; i < NUM_PEDSTATS; i++){
|
||||
ms_apPedStats[i] = new CPedStats;
|
||||
ms_apPedStats[i]->m_type = PEDSTAT_PLAYER;
|
||||
ms_apPedStats[i]->m_name[8] = 'R'; // WHAT?
|
||||
ms_apPedStats[i]->m_fleeDistance = 20.0f;
|
||||
ms_apPedStats[i]->m_headingChangeRate = 15.0f;
|
||||
ms_apPedStats[i]->m_fear = 50;
|
||||
ms_apPedStats[i]->m_temper = 50;
|
||||
ms_apPedStats[i]->m_lawfulness = 50;
|
||||
ms_apPedStats[i]->m_sexiness = 50;
|
||||
ms_apPedStats[i]->m_attackStrength = 1.0f;
|
||||
ms_apPedStats[i]->m_defendWeakness = 1.0f;
|
||||
ms_apPedStats[i]->m_flags = 0;
|
||||
}
|
||||
debug("Loading pedstats data...\n");
|
||||
CPedStats::LoadPedStats();
|
||||
debug("CPedStats ready\n");
|
||||
}
|
||||
|
||||
void
|
||||
CPedStats::Shutdown(void)
|
||||
{
|
||||
int i;
|
||||
debug("Shutting down CPedStats...\n");
|
||||
for(i = 0; i < NUM_PEDSTATS; i++)
|
||||
delete ms_apPedStats[i];
|
||||
debug("CPedStats shut down\n");
|
||||
}
|
||||
|
||||
void
|
||||
CPedStats::LoadPedStats(void)
|
||||
{
|
||||
char *buf;
|
||||
char line[256];
|
||||
char name[32];
|
||||
int bp, buflen;
|
||||
int lp, linelen;
|
||||
int type;
|
||||
float fleeDist, headingChangeRate, attackStrength, defendWeakness;
|
||||
int fear, temper, lawfullness, sexiness, flags;
|
||||
|
||||
|
||||
type = 0;
|
||||
buf = new char[16 * 1024];
|
||||
|
||||
CFileMgr::SetDir("DATA");
|
||||
buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r");
|
||||
CFileMgr::SetDir("");
|
||||
|
||||
for(bp = 0; bp < buflen; ){
|
||||
// read file line by line
|
||||
for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
|
||||
if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
|
||||
line[linelen++] = ' ';
|
||||
else
|
||||
line[linelen++] = buf[bp];
|
||||
line[linelen] = '\0';
|
||||
}
|
||||
bp++;
|
||||
|
||||
// skip white space
|
||||
for(lp = 0; line[lp] <= ' '; lp++);
|
||||
|
||||
if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
|
||||
line[lp] == '#')
|
||||
continue;
|
||||
|
||||
sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d",
|
||||
name,
|
||||
&fleeDist,
|
||||
&headingChangeRate,
|
||||
&fear,
|
||||
&temper,
|
||||
&lawfullness,
|
||||
&sexiness,
|
||||
&attackStrength,
|
||||
&defendWeakness,
|
||||
&flags);
|
||||
ms_apPedStats[type]->m_type = (ePedStats)type;
|
||||
strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy
|
||||
ms_apPedStats[type]->m_fleeDistance = fleeDist;
|
||||
ms_apPedStats[type]->m_headingChangeRate = headingChangeRate;
|
||||
ms_apPedStats[type]->m_fear = fear;
|
||||
ms_apPedStats[type]->m_temper = temper;
|
||||
ms_apPedStats[type]->m_lawfulness = lawfullness;
|
||||
ms_apPedStats[type]->m_sexiness = sexiness;
|
||||
ms_apPedStats[type]->m_attackStrength = attackStrength;
|
||||
ms_apPedStats[type]->m_defendWeakness = defendWeakness;
|
||||
ms_apPedStats[type]->m_flags = flags;
|
||||
type++;
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
int32
|
||||
CPedStats::GetPedStatType(char *name)
|
||||
{
|
||||
int type;
|
||||
|
||||
for(type = 0; type < NUM_PEDSTATS; type++)
|
||||
if(strcmp(ms_apPedStats[type]->m_name, name) == 0)
|
||||
return type;
|
||||
return NUM_PEDSTATS;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4EF460, &CPedStats::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4EF540, &CPedStats::Shutdown, PATCH_JUMP);
|
||||
InjectHook(0x4EF580, &CPedStats::LoadPedStats, PATCH_JUMP);
|
||||
InjectHook(0x4EF780, &CPedStats::GetPedStatType, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,79 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
enum ePedStats
|
||||
{
|
||||
PEDSTAT_PLAYER,
|
||||
PEDSTAT_COP,
|
||||
PEDSTAT_MEDIC,
|
||||
PEDSTAT_FIREMAN,
|
||||
PEDSTAT_GANG1,
|
||||
PEDSTAT_GANG2,
|
||||
PEDSTAT_GANG3,
|
||||
PEDSTAT_GANG4,
|
||||
PEDSTAT_GANG5,
|
||||
PEDSTAT_GANG6,
|
||||
PEDSTAT_GANG7,
|
||||
PEDSTAT_STREET_GUY,
|
||||
PEDSTAT_SUIT_GUY,
|
||||
PEDSTAT_SENSIBLE_GUY,
|
||||
PEDSTAT_GEEK_GUY,
|
||||
PEDSTAT_OLD_GUY,
|
||||
PEDSTAT_TOUGH_GUY,
|
||||
PEDSTAT_STREET_GIRL,
|
||||
PEDSTAT_SUIT_GIRL,
|
||||
PEDSTAT_SENSIBLE_GIRL,
|
||||
PEDSTAT_GEEK_GIRL,
|
||||
PEDSTAT_OLD_GIRL,
|
||||
PEDSTAT_TOUGH_GIRL,
|
||||
PEDSTAT_TRAMP_MALE,
|
||||
PEDSTAT_TRAMP_FEMALE,
|
||||
PEDSTAT_TOURIST,
|
||||
PEDSTAT_PROSTITUTE,
|
||||
PEDSTAT_CRIMINAL,
|
||||
PEDSTAT_BUSKER,
|
||||
PEDSTAT_TAXIDRIVER,
|
||||
PEDSTAT_PSYCHO,
|
||||
PEDSTAT_STEWARD,
|
||||
PEDSTAT_SPORTSFAN,
|
||||
PEDSTAT_SHOPPER,
|
||||
PEDSTAT_OLDSHOPPER,
|
||||
|
||||
NUM_PEDSTATS
|
||||
};
|
||||
|
||||
// flags
|
||||
enum
|
||||
{
|
||||
STAT_PUNCH_ONLY = 1,
|
||||
STAT_CAN_KNEE_HEAD = 2,
|
||||
STAT_CAN_KICK = 4,
|
||||
STAT_CAN_ROUNDHOUSE = 8,
|
||||
STAT_NO_DIVE = 0x10,
|
||||
STAT_ONE_HIT_KNOCKDOWN = 0x20,
|
||||
STAT_SHOPPING_BAGS = 0x40,
|
||||
STAT_GUN_PANIC = 0x80
|
||||
};
|
||||
|
||||
class CPedStats
|
||||
{
|
||||
public:
|
||||
ePedStats m_type;
|
||||
char m_name[24];
|
||||
float m_fleeDistance;
|
||||
float m_headingChangeRate;
|
||||
int8 m_fear;
|
||||
int8 m_temper;
|
||||
int8 m_lawfulness;
|
||||
int8 m_sexiness;
|
||||
float m_attackStrength;
|
||||
float m_defendWeakness;
|
||||
int16 m_flags;
|
||||
|
||||
static CPedStats* (&ms_apPedStats)[NUM_PEDSTATS];
|
||||
|
||||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
static void LoadPedStats(void);
|
||||
static int32 GetPedStatType(char *name);
|
||||
};
|
||||
static_assert(sizeof(CPedStats) == 0x34, "CPedStats: error");
|
@ -1,243 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
#include "PedType.h"
|
||||
|
||||
CPedType *(&CPedType::ms_apPedType)[NUM_PEDTYPES] = *(CPedType *(*)[NUM_PEDTYPES]) *(uintptr*)0x941594;
|
||||
|
||||
void
|
||||
CPedType::Initialise(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug("Initialising CPedType...\n");
|
||||
for(i = 0; i < NUM_PEDTYPES; i++){
|
||||
ms_apPedType[i] = new CPedType;
|
||||
ms_apPedType[i]->m_flag = PED_FLAG_PLAYER1;
|
||||
ms_apPedType[i]->unknown1 = 0.0f;
|
||||
ms_apPedType[i]->unknown2 = 0.0f;
|
||||
// unknown3 not initialized
|
||||
ms_apPedType[i]->unknown4 = 0.0f;
|
||||
ms_apPedType[i]->unknown5 = 0.0f;
|
||||
ms_apPedType[i]->m_threats = 0;
|
||||
ms_apPedType[i]->m_avoid = 0;
|
||||
}
|
||||
debug("Loading ped data...\n");
|
||||
LoadPedData();
|
||||
debug("CPedType ready\n");
|
||||
}
|
||||
|
||||
void
|
||||
CPedType::Shutdown(void)
|
||||
{
|
||||
int i;
|
||||
debug("Shutting down CPedType...\n");
|
||||
for(i = 0; i < NUM_PEDTYPES; i++)
|
||||
delete ms_apPedType[i];
|
||||
debug("CPedType shut down\n");
|
||||
}
|
||||
|
||||
void
|
||||
CPedType::LoadPedData(void)
|
||||
{
|
||||
char *buf;
|
||||
char line[256];
|
||||
char word[32];
|
||||
int bp, buflen;
|
||||
int lp, linelen;
|
||||
int type;
|
||||
uint32 flags;
|
||||
float f1, f2, f3, f4, f5;
|
||||
|
||||
type = NUM_PEDTYPES;
|
||||
buf = new char[16 * 1024];
|
||||
|
||||
CFileMgr::SetDir("DATA");
|
||||
buflen = CFileMgr::LoadFile("PED.DAT", (uint8*)buf, 16 * 1024, "r");
|
||||
CFileMgr::SetDir("");
|
||||
|
||||
for(bp = 0; bp < buflen; ){
|
||||
// read file line by line
|
||||
for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
|
||||
if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
|
||||
line[linelen++] = ' ';
|
||||
else
|
||||
line[linelen++] = buf[bp];
|
||||
line[linelen] = '\0';
|
||||
}
|
||||
bp++;
|
||||
|
||||
// skip white space
|
||||
for(lp = 0; line[lp] <= ' '; lp++);
|
||||
|
||||
if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
|
||||
line[lp] == '#')
|
||||
continue;
|
||||
|
||||
// FIX: game just uses line here
|
||||
sscanf(&line[lp], "%s", word);
|
||||
|
||||
if(strncmp(word, "Threat", 7) == 0){
|
||||
flags = 0;
|
||||
lp += 7;
|
||||
while(sscanf(&line[lp], "%s", word) == 1 && lp <= linelen){
|
||||
flags |= FindPedFlag(word);
|
||||
// skip word
|
||||
while(line[lp] != ' ' && line[lp] != '\n' && line[lp] != '\0')
|
||||
lp++;
|
||||
// skip white space
|
||||
while(line[lp] == ' ')
|
||||
lp++;
|
||||
}
|
||||
ms_apPedType[type]->m_threats = flags;
|
||||
}else if(strncmp(word, "Avoid", 6) == 0){
|
||||
flags = 0;
|
||||
lp += 6;
|
||||
while(sscanf(&line[lp], "%s", word) == 1 && lp <= linelen){
|
||||
flags |= FindPedFlag(word);
|
||||
// skip word
|
||||
while(line[lp] != ' ' && line[lp] != '\n' && line[lp] != '\0')
|
||||
lp++;
|
||||
// skip white space
|
||||
while(line[lp] == ' ')
|
||||
lp++;
|
||||
}
|
||||
ms_apPedType[type]->m_avoid = flags;
|
||||
}else{
|
||||
sscanf(line, "%s %f %f %f %f %f", word, &f1, &f2, &f3, &f4, &f5);
|
||||
type = FindPedType(word);
|
||||
ms_apPedType[type]->m_flag = FindPedFlag(word);
|
||||
// unknown values
|
||||
ms_apPedType[type]->unknown1 = f1 / 50.0f;
|
||||
ms_apPedType[type]->unknown2 = f2 / 50.0f;
|
||||
ms_apPedType[type]->unknown3 = f3 / 50.0f;
|
||||
ms_apPedType[type]->unknown4 = f4;
|
||||
ms_apPedType[type]->unknown5 = f5;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
int32
|
||||
CPedType::FindPedType(char *type)
|
||||
{
|
||||
if(strcmp(type, "PLAYER1") == 0) return PEDTYPE_PLAYER1;
|
||||
if(strcmp(type, "PLAYER2") == 0) return PEDTYPE_PLAYER2;
|
||||
if(strcmp(type, "PLAYER3") == 0) return PEDTYPE_PLAYER3;
|
||||
if(strcmp(type, "PLAYER4") == 0) return PEDTYPE_PLAYER4;
|
||||
if(strcmp(type, "CIVMALE") == 0) return PEDTYPE_CIVMALE;
|
||||
if(strcmp(type, "CIVFEMALE") == 0) return PEDTYPE_CIVFEMALE;
|
||||
if(strcmp(type, "COP") == 0) return PEDTYPE_COP;
|
||||
if(strcmp(type, "GANG1") == 0) return PEDTYPE_GANG1;
|
||||
if(strcmp(type, "GANG2") == 0) return PEDTYPE_GANG2;
|
||||
if(strcmp(type, "GANG3") == 0) return PEDTYPE_GANG3;
|
||||
if(strcmp(type, "GANG4") == 0) return PEDTYPE_GANG4;
|
||||
if(strcmp(type, "GANG5") == 0) return PEDTYPE_GANG5;
|
||||
if(strcmp(type, "GANG6") == 0) return PEDTYPE_GANG6;
|
||||
if(strcmp(type, "GANG7") == 0) return PEDTYPE_GANG7;
|
||||
if(strcmp(type, "GANG8") == 0) return PEDTYPE_GANG8;
|
||||
if(strcmp(type, "GANG9") == 0) return PEDTYPE_GANG9;
|
||||
if(strcmp(type, "EMERGENCY") == 0) return PEDTYPE_EMERGENCY;
|
||||
if(strcmp(type, "FIREMAN") == 0) return PEDTYPE_FIREMAN;
|
||||
if(strcmp(type, "CRIMINAL") == 0) return PEDTYPE_CRIMINAL;
|
||||
if(strcmp(type, "SPECIAL") == 0) return PEDTYPE_SPECIAL;
|
||||
if(strcmp(type, "PROSTITUTE") == 0) return PEDTYPE_PROSTITUTE;
|
||||
Error("Unknown ped type, Pedtype.cpp");
|
||||
return NUM_PEDTYPES;
|
||||
}
|
||||
|
||||
uint32
|
||||
CPedType::FindPedFlag(char *type)
|
||||
{
|
||||
if(strcmp(type, "PLAYER1") == 0) return PED_FLAG_PLAYER1;
|
||||
if(strcmp(type, "PLAYER2") == 0) return PED_FLAG_PLAYER2;
|
||||
if(strcmp(type, "PLAYER3") == 0) return PED_FLAG_PLAYER3;
|
||||
if(strcmp(type, "PLAYER4") == 0) return PED_FLAG_PLAYER4;
|
||||
if(strcmp(type, "CIVMALE") == 0) return PED_FLAG_CIVMALE;
|
||||
if(strcmp(type, "CIVFEMALE") == 0) return PED_FLAG_CIVFEMALE;
|
||||
if(strcmp(type, "COP") == 0) return PED_FLAG_COP;
|
||||
if(strcmp(type, "GANG1") == 0) return PED_FLAG_GANG1;
|
||||
if(strcmp(type, "GANG2") == 0) return PED_FLAG_GANG2;
|
||||
if(strcmp(type, "GANG3") == 0) return PED_FLAG_GANG3;
|
||||
if(strcmp(type, "GANG4") == 0) return PED_FLAG_GANG4;
|
||||
if(strcmp(type, "GANG5") == 0) return PED_FLAG_GANG5;
|
||||
if(strcmp(type, "GANG6") == 0) return PED_FLAG_GANG6;
|
||||
if(strcmp(type, "GANG7") == 0) return PED_FLAG_GANG7;
|
||||
if(strcmp(type, "GANG8") == 0) return PED_FLAG_GANG8;
|
||||
if(strcmp(type, "GANG9") == 0) return PED_FLAG_GANG9;
|
||||
if(strcmp(type, "EMERGENCY") == 0) return PED_FLAG_EMERGENCY;
|
||||
if(strcmp(type, "FIREMAN") == 0) return PED_FLAG_FIREMAN;
|
||||
if(strcmp(type, "CRIMINAL") == 0) return PED_FLAG_CRIMINAL;
|
||||
if(strcmp(type, "SPECIAL") == 0) return PED_FLAG_SPECIAL;
|
||||
if(strcmp(type, "GUN") == 0) return PED_FLAG_GUN;
|
||||
if(strcmp(type, "COP_CAR") == 0) return PED_FLAG_COP_CAR;
|
||||
if(strcmp(type, "FAST_CAR") == 0) return PED_FLAG_FAST_CAR;
|
||||
if(strcmp(type, "EXPLOSION") == 0) return PED_FLAG_EXPLOSION;
|
||||
if(strcmp(type, "PROSTITUTE") == 0) return PED_FLAG_PROSTITUTE;
|
||||
if(strcmp(type, "DEADPEDS") == 0) return PED_FLAG_DEADPEDS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CPedType::Save(uint8 *buffer, uint32 *length)
|
||||
{
|
||||
int i;
|
||||
|
||||
*length = 8 + NUM_PEDTYPES*32;
|
||||
|
||||
buffer[0] = 'P';
|
||||
buffer[1] = 'T';
|
||||
buffer[2] = 'P';
|
||||
buffer[3] = '\0';
|
||||
*(uint32*)(buffer+4) = *length - 8;
|
||||
buffer += 8;
|
||||
|
||||
for(i = 0; i < NUM_PEDTYPES; i++){
|
||||
*(uint32*)(buffer) = ms_apPedType[i]->m_flag;
|
||||
*(float*)(buffer+4) = ms_apPedType[i]->unknown1;
|
||||
*(float*)(buffer+8) = ms_apPedType[i]->unknown2;
|
||||
*(float*)(buffer+12) = ms_apPedType[i]->unknown3;
|
||||
*(float*)(buffer+16) = ms_apPedType[i]->unknown4;
|
||||
*(float*)(buffer+20) = ms_apPedType[i]->unknown5;
|
||||
*(uint32*)(buffer+24) = ms_apPedType[i]->m_threats;
|
||||
*(uint32*)(buffer+28) = ms_apPedType[i]->m_avoid;
|
||||
buffer += 32;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPedType::Load(uint8 *buffer, uint32 length)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(length == 8 + NUM_PEDTYPES*32);
|
||||
assert(buffer[0] == 'P');
|
||||
assert(buffer[1] == 'T');
|
||||
assert(buffer[2] == 'P');
|
||||
assert(buffer[3] == '\0');
|
||||
assert(*(uint32*)(buffer+4) == length - 8);
|
||||
buffer += 8;
|
||||
|
||||
for(i = 0; i < NUM_PEDTYPES; i++){
|
||||
ms_apPedType[i]->m_flag = *(uint32*)(buffer);
|
||||
ms_apPedType[i]->unknown1 = *(float*)(buffer+4);
|
||||
ms_apPedType[i]->unknown2 = *(float*)(buffer+8);
|
||||
ms_apPedType[i]->unknown3 = *(float*)(buffer+12);
|
||||
ms_apPedType[i]->unknown4 = *(float*)(buffer+16);
|
||||
ms_apPedType[i]->unknown5 = *(float*)(buffer+20);
|
||||
ms_apPedType[i]->m_threats = *(uint32*)(buffer+24);
|
||||
ms_apPedType[i]->m_avoid = *(uint32*)(buffer+28);
|
||||
buffer += 32;
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4EE890, &CPedType::Shutdown, PATCH_JUMP);
|
||||
InjectHook(0x4EEC10, &CPedType::FindPedType, PATCH_JUMP);
|
||||
InjectHook(0x4EEF40, &CPedType::FindPedFlag, PATCH_JUMP);
|
||||
InjectHook(0x4EF320, &CPedType::Save, PATCH_JUMP);
|
||||
InjectHook(0x4EF3D0, &CPedType::Load, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,90 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// Index into the PedType array
|
||||
enum
|
||||
{
|
||||
PEDTYPE_PLAYER1,
|
||||
PEDTYPE_PLAYER2,
|
||||
PEDTYPE_PLAYER3,
|
||||
PEDTYPE_PLAYER4,
|
||||
PEDTYPE_CIVMALE,
|
||||
PEDTYPE_CIVFEMALE,
|
||||
PEDTYPE_COP,
|
||||
PEDTYPE_GANG1,
|
||||
PEDTYPE_GANG2,
|
||||
PEDTYPE_GANG3,
|
||||
PEDTYPE_GANG4,
|
||||
PEDTYPE_GANG5,
|
||||
PEDTYPE_GANG6,
|
||||
PEDTYPE_GANG7,
|
||||
PEDTYPE_GANG8,
|
||||
PEDTYPE_GANG9,
|
||||
PEDTYPE_EMERGENCY,
|
||||
PEDTYPE_FIREMAN,
|
||||
PEDTYPE_CRIMINAL,
|
||||
PEDTYPE_UNUSED1,
|
||||
PEDTYPE_PROSTITUTE,
|
||||
PEDTYPE_SPECIAL,
|
||||
PEDTYPE_UNUSED2,
|
||||
|
||||
NUM_PEDTYPES
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PED_FLAG_PLAYER1 = 1 << 0,
|
||||
PED_FLAG_PLAYER2 = 1 << 1,
|
||||
PED_FLAG_PLAYER3 = 1 << 2,
|
||||
PED_FLAG_PLAYER4 = 1 << 3,
|
||||
PED_FLAG_CIVMALE = 1 << 4,
|
||||
PED_FLAG_CIVFEMALE = 1 << 5,
|
||||
PED_FLAG_COP = 1 << 6,
|
||||
PED_FLAG_GANG1 = 1 << 7,
|
||||
PED_FLAG_GANG2 = 1 << 8,
|
||||
PED_FLAG_GANG3 = 1 << 9,
|
||||
PED_FLAG_GANG4 = 1 << 10,
|
||||
PED_FLAG_GANG5 = 1 << 11,
|
||||
PED_FLAG_GANG6 = 1 << 12,
|
||||
PED_FLAG_GANG7 = 1 << 13,
|
||||
PED_FLAG_GANG8 = 1 << 14,
|
||||
PED_FLAG_GANG9 = 1 << 15,
|
||||
PED_FLAG_EMERGENCY = 1 << 16,
|
||||
PED_FLAG_PROSTITUTE = 1 << 17,
|
||||
PED_FLAG_CRIMINAL = 1 << 18,
|
||||
PED_FLAG_SPECIAL = 1 << 19,
|
||||
PED_FLAG_GUN = 1 << 20,
|
||||
PED_FLAG_COP_CAR = 1 << 21,
|
||||
PED_FLAG_FAST_CAR = 1 << 22,
|
||||
PED_FLAG_EXPLOSION = 1 << 23,
|
||||
PED_FLAG_FIREMAN = 1 << 24,
|
||||
PED_FLAG_DEADPEDS = 1 << 25,
|
||||
};
|
||||
|
||||
class CPedType
|
||||
{
|
||||
uint32 m_flag;
|
||||
float unknown1;
|
||||
float unknown2;
|
||||
float unknown3;
|
||||
float unknown4;
|
||||
float unknown5;
|
||||
uint32 m_threats;
|
||||
uint32 m_avoid;
|
||||
|
||||
static CPedType *(&ms_apPedType)[NUM_PEDTYPES];
|
||||
public:
|
||||
|
||||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
static void LoadPedData(void);
|
||||
static int32 FindPedType(char *type);
|
||||
static uint32 FindPedFlag(char *type);
|
||||
static void Save(uint8 *buffer, uint32 *length);
|
||||
static void Load(uint8 *buffer, uint32 length);
|
||||
|
||||
static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }
|
||||
static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }
|
||||
static uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(CPedType) == 0x20, "CPedType: error");
|
@ -1,6 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "PhoneInfo.h"
|
||||
#include "Phones.h"
|
||||
|
||||
WRAPPER void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F570); }
|
||||
WRAPPER void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F470); }
|
||||
WRAPPER void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F470); }
|
@ -16,7 +16,7 @@
|
||||
#include "ModelInfo.h"
|
||||
#include "Object.h"
|
||||
#include "Pad.h"
|
||||
#include "PhoneInfo.h"
|
||||
#include "Phones.h"
|
||||
#include "Pickups.h"
|
||||
#include "Plane.h"
|
||||
#include "Pools.h"
|
||||
@ -638,7 +638,7 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id)
|
||||
if (vehicle->IsCar()){
|
||||
CAutomobile* car = (CAutomobile*)vehicle;
|
||||
for (int i = 0; i < 4; i++){
|
||||
vp->wheel_susp_dist[i] = 50.0f * car->m_aWheelDist[i];
|
||||
vp->wheel_susp_dist[i] = 50.0f * car->m_aSuspensionSpringRatio[i];
|
||||
vp->wheel_rotation[i] = 128.0f / M_PI * car->m_aWheelRotation[i];
|
||||
}
|
||||
vp->door_angles[0] = 127.0f / M_PI * car->Doors[2].m_fAngle;
|
||||
@ -683,7 +683,7 @@ void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressI
|
||||
if (vehicle->IsCar()) {
|
||||
CAutomobile* car = (CAutomobile*)vehicle;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
car->m_aWheelDist[i] = vp->wheel_susp_dist[i] / 50.0f;
|
||||
car->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;
|
||||
car->m_aWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f;
|
||||
}
|
||||
car->Doors[2].m_fAngle = car->Doors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f;
|
||||
|
@ -262,8 +262,8 @@ public:
|
||||
static void StreamAllNecessaryCarsAndPeds(void);
|
||||
static bool ShouldStandardCameraBeProcessed(void);
|
||||
|
||||
inline static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
|
||||
inline static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
|
||||
static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
|
||||
static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
|
||||
|
||||
private:
|
||||
static void RecordThisFrame(void);
|
||||
|
@ -129,6 +129,10 @@ void CMissionCleanup::Process()
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: CUpsideDownCarCheck is not used by actual script at all
|
||||
* It has a weird usage: AreAnyCarsUpsideDown would fail any mission
|
||||
* just like death or arrest. */
|
||||
|
||||
void CUpsideDownCarCheck::Init()
|
||||
{
|
||||
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
|
||||
@ -137,18 +141,142 @@ void CUpsideDownCarCheck::Init()
|
||||
}
|
||||
}
|
||||
|
||||
bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id)
|
||||
{
|
||||
CVehicle* v = CPools::GetVehiclePool()->GetAt(id);
|
||||
return v->GetUp().z <= -0.97f &&
|
||||
v->GetMoveSpeed().Magnitude() < 0.01f &&
|
||||
v->GetTurnSpeed().Magnitude() < 0.02f;
|
||||
}
|
||||
|
||||
void CUpsideDownCarCheck::UpdateTimers()
|
||||
{
|
||||
uint32 timeStep = CTimer::GetTimeStepInMilliseconds();
|
||||
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
|
||||
CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);
|
||||
if (v){
|
||||
if (IsCarUpsideDown(m_sCars[i].m_nVehicleIndex))
|
||||
m_sCars[i].m_nUpsideDownTimer += timeStep;
|
||||
else
|
||||
m_sCars[i].m_nUpsideDownTimer = 0;
|
||||
}else{
|
||||
m_sCars[i].m_nVehicleIndex = -1;
|
||||
m_sCars[i].m_nUpsideDownTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CUpsideDownCarCheck::AreAnyCarsUpsideDown()
|
||||
{
|
||||
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > 1000)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CUpsideDownCarCheck::AddCarToCheck(int32 id)
|
||||
{
|
||||
uint16 index = 0;
|
||||
while (index < MAX_UPSIDEDOWN_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
|
||||
index++;
|
||||
if (index >= MAX_UPSIDEDOWN_CAR_CHECKS)
|
||||
return;
|
||||
m_sCars[index].m_nVehicleIndex = id;
|
||||
m_sCars[index].m_nUpsideDownTimer = 0;
|
||||
}
|
||||
|
||||
void CUpsideDownCarCheck::RemoveCarFromCheck(int32 id)
|
||||
{
|
||||
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex == id){
|
||||
m_sCars[i].m_nVehicleIndex = -1;
|
||||
m_sCars[i].m_nUpsideDownTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
|
||||
{
|
||||
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex == id)
|
||||
return m_sCars[i].m_nUpsideDownTimer > 1000;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStuckCarCheckEntry::Reset()
|
||||
{
|
||||
m_nVehicleIndex = -1;
|
||||
m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
|
||||
m_nLastCheck = -1;
|
||||
m_fRadius = 0.0f;
|
||||
m_nStuckTime = 0;
|
||||
m_bStuck = false;
|
||||
}
|
||||
|
||||
void CStuckCarCheck::Init()
|
||||
{
|
||||
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) {
|
||||
m_sCars[i].m_nVehicleIndex = -1;
|
||||
m_sCars[i].m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
|
||||
m_sCars[i].m_nStartTime = -1;
|
||||
m_sCars[i].m_fDistance = 0.0f;
|
||||
m_sCars[i].m_nStuckTime = 0;
|
||||
m_sCars[i].m_bStuck = false;
|
||||
m_sCars[i].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CStuckCarCheck::Process()
|
||||
{
|
||||
uint32 timer = CTimer::GetTimeInMilliseconds();
|
||||
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex < 0)
|
||||
continue;
|
||||
if (timer <= m_sCars[i].m_nStuckTime + m_sCars[i].m_nLastCheck)
|
||||
continue;
|
||||
CVehicle* pv = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);
|
||||
if (!pv){
|
||||
m_sCars[i].Reset();
|
||||
continue;
|
||||
}
|
||||
float distance = (pv->GetPosition() - m_sCars[i].m_vecPos).Magnitude();
|
||||
m_sCars[i].m_bStuck = distance < m_sCars[i].m_fRadius;
|
||||
m_sCars[i].m_vecPos = pv->GetPosition();
|
||||
m_sCars[i].m_nLastCheck = timer;
|
||||
}
|
||||
}
|
||||
|
||||
void CStuckCarCheck::AddCarToCheck(int32 id, float radius, uint32 time)
|
||||
{
|
||||
CVehicle* pv = CPools::GetVehiclePool()->GetAt(id);
|
||||
if (!pv)
|
||||
return;
|
||||
int index = 0;
|
||||
while (index < MAX_STUCK_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
|
||||
index++;
|
||||
/* Would be nice to return if index >= MAX_STUCK_CAR_CHECKS... */
|
||||
m_sCars[index].m_nVehicleIndex = id;
|
||||
m_sCars[index].m_vecPos = pv->GetPosition();
|
||||
m_sCars[index].m_nLastCheck = CTimer::GetTimeInMilliseconds();
|
||||
m_sCars[index].m_fRadius = radius;
|
||||
m_sCars[index].m_nStuckTime = time;
|
||||
m_sCars[index].m_bStuck = false;
|
||||
}
|
||||
|
||||
void CStuckCarCheck::RemoveCarFromCheck(int32 id)
|
||||
{
|
||||
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex == id){
|
||||
m_sCars[i].Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)
|
||||
{
|
||||
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
|
||||
if (m_sCars[i].m_nVehicleIndex == id)
|
||||
return m_sCars[i].m_bStuck;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
WRAPPER void CTheScripts::CleanUpThisVehicle(CVehicle*) { EAXJMP(0x4548D0); }
|
||||
WRAPPER void CTheScripts::CleanUpThisPed(CPed*) { EAXJMP(0x4547A0); }
|
||||
WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); }
|
||||
@ -160,4 +288,15 @@ InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP);
|
||||
InjectHook(0x437BA0, &CMissionCleanup::AddEntityToList, PATCH_JUMP);
|
||||
InjectHook(0x437BD0, &CMissionCleanup::RemoveEntityFromList, PATCH_JUMP);
|
||||
InjectHook(0x437C10, &CMissionCleanup::Process, PATCH_JUMP);
|
||||
InjectHook(0x437DC0, &CUpsideDownCarCheck::Init, PATCH_JUMP);
|
||||
InjectHook(0x437EE0, &CUpsideDownCarCheck::UpdateTimers, PATCH_JUMP);
|
||||
InjectHook(0x437F80, &CUpsideDownCarCheck::AreAnyCarsUpsideDown, PATCH_JUMP);
|
||||
InjectHook(0x437FB0, &CUpsideDownCarCheck::AddCarToCheck, PATCH_JUMP);
|
||||
InjectHook(0x437FE0, &CUpsideDownCarCheck::RemoveCarFromCheck, PATCH_JUMP);
|
||||
InjectHook(0x438010, &CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile, PATCH_JUMP);
|
||||
InjectHook(0x438050, &CStuckCarCheck::Init, PATCH_JUMP);
|
||||
InjectHook(0x4380A0, &CStuckCarCheck::Process, PATCH_JUMP);
|
||||
InjectHook(0x4381C0, &CStuckCarCheck::AddCarToCheck, PATCH_JUMP);
|
||||
InjectHook(0x438240, &CStuckCarCheck::RemoveCarFromCheck, PATCH_JUMP);
|
||||
InjectHook(0x4382A0, &CStuckCarCheck::HasCarBeenStuckForAWhile, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -101,16 +101,24 @@ class CUpsideDownCarCheck
|
||||
|
||||
public:
|
||||
void Init();
|
||||
bool IsCarUpsideDown(int32);
|
||||
void UpdateTimers();
|
||||
bool AreAnyCarsUpsideDown();
|
||||
void AddCarToCheck(int32);
|
||||
void RemoveCarFromCheck(int32);
|
||||
bool HasCarBeenUpsideDownForAWhile(int32);
|
||||
};
|
||||
|
||||
struct CStuckCarCheckEntry
|
||||
{
|
||||
int32 m_nVehicleIndex;
|
||||
CVector m_vecPos;
|
||||
int32 m_nStartTime;
|
||||
float m_fDistance;
|
||||
int32 m_nLastCheck;
|
||||
float m_fRadius;
|
||||
uint32 m_nStuckTime;
|
||||
bool m_bStuck;
|
||||
|
||||
inline void Reset();
|
||||
};
|
||||
|
||||
class CStuckCarCheck
|
||||
@ -119,6 +127,10 @@ class CStuckCarCheck
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void Process();
|
||||
void AddCarToCheck(int32, float, uint32);
|
||||
void RemoveCarFromCheck(int32);
|
||||
bool HasCarBeenStuckForAWhile(int32);
|
||||
};
|
||||
|
||||
class CTheScripts
|
||||
|
@ -1,37 +0,0 @@
|
||||
#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;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#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);
|
||||
};
|
Reference in New Issue
Block a user