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
46 changed files with 1814 additions and 578 deletions

View File

@ -72,6 +72,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
bFixedColour = false;
bBigWheels = false;
bWaterTight = false;
bTankDetonateCars = true;
SetModelIndex(id);
@ -332,7 +333,7 @@ CAutomobile::ProcessControl(void)
bool playerRemote = false;
switch(GetStatus()){
case STATUS_PLAYER_REMOTE:
if(CPad::GetPad(0)->WeaponJustDown()){
if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){
BlowUpCar(FindPlayerPed());
CRemote::TakeRemoteControlledCarFromPlayer();
}
@ -864,8 +865,14 @@ CAutomobile::ProcessControl(void)
CVector wheelFwd = GetForward();
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)
brake = 20000.0f;
#endif
if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){
if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
@ -4148,7 +4155,7 @@ CAutomobile::BlowUpCarsInPath(void)
{
int i;
if(m_vecMoveSpeed.Magnitude() > 0.1f)
if(m_vecMoveSpeed.Magnitude() > 0.1f && bTankDetonateCars)
for(i = 0; i < m_nCollisionRecords; i++)
if(m_aCollisionRecords[i] &&
m_aCollisionRecords[i]->IsVehicle() &&
@ -4610,6 +4617,18 @@ CAutomobile::SetAllTaxiLights(bool 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
void
CAutomobile::Save(uint8*& buf)

View File

@ -91,6 +91,7 @@ public:
uint8 bWaterTight : 1; // no damage for non-player peds
uint8 bNotDamagedUpsideDown : 1;
uint8 bMoreResistantToDamage : 1;
uint8 bTankDetonateCars : 1;
int16 field_4E0;
uint16 m_hydraulicState;
uint32 m_nBusDoorTimerEnd;
@ -178,6 +179,8 @@ public:
void SetBumperDamage(int32 component, ePanels panel, 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 SetComponentVisibility(RwFrame *frame, uint32 flags);
void SetupModelNodes(void);

View File

@ -127,7 +127,7 @@ cHandlingDataMgr::Initialise(void)
{
LoadHandlingData();
field_0 = 0.1f;
field_4 = 0.9f;
fWheelFriction = 0.9f;
field_8 = 1.0f;
field_C = 0.8f;
field_10 = 0.98f;
@ -143,6 +143,9 @@ cHandlingDataMgr::LoadHandlingData(void)
int field, handlingId;
int keepGoing;
tHandlingData *handling;
tFlyingHandlingData *flyingHandling;
tBoatHandlingData *boatHandling;
tBikeHandlingData *bikeHandling;
CFileMgr::SetDir("DATA");
CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r");
@ -151,6 +154,9 @@ cHandlingDataMgr::LoadHandlingData(void)
start = (char*)work_buff;
end = start+1;
handling = nil;
flyingHandling = nil;
boatHandling = nil;
bikeHandling = nil;
keepGoing = 1;
while(keepGoing){
@ -166,61 +172,158 @@ cHandlingDataMgr::LoadHandlingData(void)
// yeah, this is kinda crappy
if(strncmp(line, ";the end", 9) == 0)
keepGoing = 0;
// else if(line[0] != ';'){
// TODO(MIAMI): read boat, bike, flying values
else if(line[0] != ';' && line[0] != '%' && line[0] != '!' && 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 = (eHandlingId)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->Transmission.nNumberOfGears = atoi(word); break;
case 13: handling->Transmission.fMaxVelocity = strtod(word, nil); break;
case 14: handling->Transmission.fEngineAcceleration = strtod(word, nil) * 0.4f; break;
case 15: handling->Transmission.nDriveType = word[0]; break;
case 16: handling->Transmission.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:
// 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;
else if(line[0] != ';'){
if(line[0] == '!'){
// Bike 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);
bikeHandling = GetBikePointer(handlingId);
bikeHandling->nIdentifier = (eHandlingId)handlingId;
break;
case 2: bikeHandling->fLeanFwdCOM = atof(word); break;
case 3: bikeHandling->fLeanFwdForce = atof(word); break;
case 4: bikeHandling->fLeanBakCOM = atof(word); break;
case 5: bikeHandling->fLeanBackForce = atof(word); break;
case 6: bikeHandling->fMaxLean = atof(word); break;
case 7: bikeHandling->fFullAnimLean = atof(word); break;
case 8: bikeHandling->fDesLean = atof(word); break;
case 9: bikeHandling->fSpeedSteer = atof(word); break;
case 10: bikeHandling->fSlipSteer = atof(word); break;
case 11: bikeHandling->fNoPlayerCOMz = atof(word); break;
case 12: bikeHandling->fWheelieAng = atof(word); break;
case 13: bikeHandling->fStoppieAng = atof(word); break;
case 14: bikeHandling->fWheelieSteer = atof(word); break;
case 15: bikeHandling->fWheelieStabMult = atof(word); break;
case 16: bikeHandling->fStoppieStabMult = atof(word); break;
}
field++;
}
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)
handling->fTurnMass *= 5.0f;
handling->fInvMass = 1.0f/handling->fMass;
handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;
handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * 0.008f*handling->fMass;
// What the hell is going on here?
@ -268,11 +372,16 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
if(handling->nIdentifier == HANDLING_RCBANDIT){
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{
handling->Transmission.fUnkMaxVelocity = velocity;
handling->Transmission.fMaxVelocity = velocity * 1.2f;
handling->Transmission.fMaxReverseVelocity = -0.2f;
}
handling->Transmission.fMaxReverseVelocity = -0.2f;
if(handling->Transmission.nDriveType == '4')
handling->Transmission.fEngineAcceleration /= 4.0f;
@ -282,6 +391,15 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)
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
cHandlingDataMgr::GetHandlingId(const char *name)
{
@ -291,3 +409,19 @@ cHandlingDataMgr::GetHandlingId(const char *name)
break;
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_BLOODRA,
HANDLING_BLOODRB,
HANDLING_BIKE,
HANDLING_MOPED,
HANDLING_DIRTBIKE,
HANDLING_ANGEL,
HANDLING_FREEWAY,
HANDLING_PREDATOR,
HANDLING_SPEEDER,
HANDLING_REEFER,
@ -100,7 +102,7 @@ enum eHandlingId
HANDLING_DINGHY,
HANDLING_MARQUIS,
HANDLING_CUPBOAT,
HANDLING_SEAPLANE,
HANDLING_SEAPLANE, // both boat and plane!
HANDLING_SPARROW,
HANDLING_SEASPAR,
HANDLING_MAVERICK,
@ -109,7 +111,13 @@ enum eHandlingId
HANDLING_HUNTER,
HANDLING_RCBARON,
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
@ -168,6 +176,7 @@ struct tHandlingData
float fSuspensionUpperLimit;
float fSuspensionLowerLimit;
float fSuspensionBias;
float fSuspensionAntidiveMultiplier;
float fCollisionDamageMultiplier;
uint32 Flags;
float fSeatOffsetDistance;
@ -175,19 +184,74 @@ struct tHandlingData
int8 FrontLights;
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
{
float field_0; // unused it seems
public:
float field_4; // wheel related
float fWheelFriction;
private:
float field_8; //
float field_C; // unused it seems
float field_10; //
tHandlingData HandlingData[NUMHANDLINGS];
uint32 field_302C; // unused it seems
tBikeHandlingData BikeHandlingData[NUMBIKEHANDLINGS];
tFlyingHandlingData FlyingHandlingData[NUMFLYINGHANDLINGS];
tBoatHandlingData BoatHandlingData[NUMBOATHANDLINGS];
public:
cHandlingDataMgr(void);
@ -195,8 +259,12 @@ public:
void LoadHandlingData(void);
int FindExactWord(const char *word, const char *words, int wordLen, int numWords);
void ConvertDataToGameUnits(tHandlingData *handling);
void ConvertBikeDataToGameUnits(tBikeHandlingData *handling);
int32 GetHandlingId(const char *name);
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 HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; }
};

View File

@ -29,6 +29,7 @@ bool CVehicle::bCheat5;
bool CVehicle::bAltDodoCheat;
#endif
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, int handle) { return CPools::GetVehiclePool()->New(handle); }
@ -493,6 +494,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(contactSpeedRight != 0.0f){
// exert opposing force
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){
float fwdspeed = Min(contactSpeedFwd, 0.3f);
@ -513,13 +519,21 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
}
}else if(contactSpeedFwd != 0.0f){
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(m_fGasPedal < 0.01f){
if(GetModelIndex() == MI_RCBANDIT)
brake = 0.2f * mod_HandlingManager.field_4 / m_fMass;
brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
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(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)
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
else if (GetModelIndex() == MI_POLICE) {
CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
} 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
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
bFreebies = false;
@ -1353,14 +1367,29 @@ eVehicleAppearance
CVehicle::GetVehicleAppearance(void)
{
if (IsCar())
return VEHICLE_CAR;
return VEHICLE_APPEARANCE_CAR;
if (IsBoat())
return VEHICLE_BOAT;
return VEHICLE_APPEARANCE_BOAT;
if (IsBike())
return VEHICLE_BIKE;
return VEHICLE_APPEARANCE_BIKE;
if (IsPlane())
return VEHICLE_PLANE;
return VEHICLE_APPEARANCE_PLANE;
if (IsHeli())
return VEHICLE_HELI;
return VEHICLE_NONE;
return VEHICLE_APPEARANCE_HELI;
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
{
VEHICLE_NONE,
VEHICLE_CAR,
VEHICLE_BIKE,
VEHICLE_HELI,
VEHICLE_BOAT,
VEHICLE_PLANE,
VEHICLE_APPEARANCE_NONE,
VEHICLE_APPEARANCE_CAR,
VEHICLE_APPEARANCE_BIKE,
VEHICLE_APPEARANCE_HELI,
VEHICLE_APPEARANCE_BOAT,
VEHICLE_APPEARANCE_PLANE,
};
// Or Weapon.h?
@ -311,6 +311,8 @@ public:
static bool bAltDodoCheat;
#endif
static bool m_bDisableMouseSteering;
static bool bDisableRemoteDetonation;
};
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);
bool IsVehiclePointerValid(CVehicle* pVehicle);