Merge branch 'master' into master
This commit is contained in:
commit
0ac6d0515e
@ -1,21 +1,243 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "General.h"
|
||||
#include "DamageManager.h"
|
||||
|
||||
#if 0
|
||||
WRAPPER void CDamageManager::SetDoorStatus(int door, unsigned int status) { EAXJMP(0x545920); }
|
||||
#else
|
||||
void CDamageManager::SetDoorStatus(int door, unsigned int status)
|
||||
{
|
||||
m_bDoorStatus[door] = status;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
WRAPPER unsigned int CDamageManager::GetDoorStatus(int door) { EAXJMP(0x545930); }
|
||||
#else
|
||||
unsigned int CDamageManager::GetDoorStatus(int door)
|
||||
float G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f };
|
||||
|
||||
void
|
||||
CDamageManager::ResetDamageStatus(void)
|
||||
{
|
||||
return m_bDoorStatus[door];
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CDamageManager::FuckCarCompletely(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
m_wheelStatus[0] = 2;
|
||||
// wheels 1-3 not reset?
|
||||
|
||||
m_doorStatus[0] = 3;
|
||||
m_doorStatus[1] = 3;
|
||||
m_doorStatus[2] = 3;
|
||||
m_doorStatus[3] = 3;
|
||||
m_doorStatus[4] = 3;
|
||||
m_doorStatus[5] = 3;
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
#ifdef FIX_BUGS
|
||||
ProgressPanelDamage(VEHBUMPER_FRONT);
|
||||
ProgressPanelDamage(VEHBUMPER_REAR);
|
||||
#else
|
||||
// this can't be right
|
||||
ProgressPanelDamage(COMPONENT_BUMPER_FRONT);
|
||||
ProgressPanelDamage(COMPONENT_BUMPER_REAR);
|
||||
#endif
|
||||
}
|
||||
// Why set to no damage?
|
||||
m_lightStatus = 0;
|
||||
m_panelStatus = 0;
|
||||
SetEngineStatus(250);
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::ApplyDamage(tComponent component, float damage, float unused)
|
||||
{
|
||||
tComponentGroup group;
|
||||
uint8 subComp;
|
||||
|
||||
GetComponentGroup(component, &group, &subComp);
|
||||
damage *= G_aComponentDamage[group];
|
||||
if(damage > 150.0f){
|
||||
switch(group){
|
||||
case COMPGROUP_WHEEL:
|
||||
ProgressWheelDamage(subComp);
|
||||
break;
|
||||
case COMPGROUP_DOOR:
|
||||
case COMPGROUP_BOOT:
|
||||
ProgressDoorDamage(subComp);
|
||||
break;
|
||||
case COMPGROUP_BONNET:
|
||||
if(damage > 220.0f)
|
||||
ProgressEngineDamage();
|
||||
ProgressDoorDamage(subComp);
|
||||
break;
|
||||
case COMPGROUP_PANEL:
|
||||
// so windscreen is a light?
|
||||
SetLightStatus((eLights)subComp, 1);
|
||||
// fall through
|
||||
case COMPGROUP_BUMPER:
|
||||
if(damage > 220.0f &&
|
||||
(component == COMPONENT_PANEL_FRONT_LEFT ||
|
||||
component == COMPONENT_PANEL_FRONT_RIGHT ||
|
||||
component == COMPONENT_PANEL_WINDSCREEN))
|
||||
ProgressEngineDamage();
|
||||
ProgressPanelDamage(subComp);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::GetComponentGroup(tComponent component, tComponentGroup *componentGroup, uint8 *subComp)
|
||||
{
|
||||
*subComp = -2; // ??
|
||||
|
||||
// This is done very strangely in the game, maybe an optimized switch?
|
||||
if(component >= COMPONENT_PANEL_FRONT_LEFT){
|
||||
if(component >= COMPONENT_BUMPER_FRONT)
|
||||
*componentGroup = COMPGROUP_BUMPER;
|
||||
else
|
||||
*componentGroup = COMPGROUP_PANEL;
|
||||
*subComp = component - COMPONENT_PANEL_FRONT_LEFT;
|
||||
return true;
|
||||
}else if(component >= COMPONENT_DOOR_BONNET){
|
||||
if(component == COMPONENT_DOOR_BONNET)
|
||||
*componentGroup = COMPGROUP_BONNET;
|
||||
else if(component == COMPONENT_DOOR_BOOT)
|
||||
*componentGroup = COMPGROUP_BOOT;
|
||||
else
|
||||
*componentGroup = COMPGROUP_DOOR;
|
||||
*subComp = component - COMPONENT_DOOR_BONNET;
|
||||
return true;
|
||||
}else if(component >= COMPONENT_WHEEL_FRONT_LEFT){
|
||||
*componentGroup = COMPGROUP_WHEEL;
|
||||
*subComp = component - COMPONENT_WHEEL_FRONT_LEFT;
|
||||
return true;
|
||||
}else if(component >= COMPONENT_DEFAULT){
|
||||
*componentGroup = COMPGROUP_DEFAULT;
|
||||
*subComp = component - COMPONENT_DEFAULT;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CDamageManager::SetDoorStatus(int32 door, uint32 status)
|
||||
{
|
||||
m_doorStatus[door] = status;
|
||||
}
|
||||
|
||||
int32
|
||||
CDamageManager::GetDoorStatus(int32 door)
|
||||
{
|
||||
return m_doorStatus[door];
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::ProgressDoorDamage(uint8 door)
|
||||
{
|
||||
int status = GetDoorStatus(door);
|
||||
if(status == 3)
|
||||
return false;
|
||||
SetDoorStatus(door, status+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CDamageManager::SetPanelStatus(int32 panel, uint32 status)
|
||||
{
|
||||
m_panelStatus = dpb(status, panel*4, 4, m_panelStatus);
|
||||
}
|
||||
|
||||
int32
|
||||
CDamageManager::GetPanelStatus(int32 panel)
|
||||
{
|
||||
return ldb(panel*4, 4, m_panelStatus);
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::ProgressPanelDamage(uint8 panel)
|
||||
{
|
||||
int status = GetPanelStatus(panel);
|
||||
if(status == 3)
|
||||
return false;
|
||||
SetPanelStatus(panel, status+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CDamageManager::SetLightStatus(eLights light, uint32 status)
|
||||
{
|
||||
m_lightStatus = dpb(status, light*2, 2, m_lightStatus);
|
||||
}
|
||||
|
||||
int32
|
||||
CDamageManager::GetLightStatus(eLights light)
|
||||
{
|
||||
return ldb(light*2, 2, m_lightStatus);
|
||||
}
|
||||
|
||||
void
|
||||
CDamageManager::SetWheelStatus(int32 wheel, uint32 status)
|
||||
{
|
||||
m_wheelStatus[wheel] = status;
|
||||
}
|
||||
|
||||
int32
|
||||
CDamageManager::GetWheelStatus(int32 wheel)
|
||||
{
|
||||
return m_wheelStatus[wheel];
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::ProgressWheelDamage(uint8 wheel)
|
||||
{
|
||||
int status = GetWheelStatus(wheel);
|
||||
if(status == 3)
|
||||
return false;
|
||||
SetWheelStatus(wheel, status+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CDamageManager::SetEngineStatus(uint32 status)
|
||||
{
|
||||
if(status > 250)
|
||||
m_engineStatus = 250;
|
||||
else
|
||||
m_engineStatus = status;
|
||||
}
|
||||
|
||||
int32
|
||||
CDamageManager::GetEngineStatus(void)
|
||||
{
|
||||
return m_engineStatus;
|
||||
}
|
||||
|
||||
bool
|
||||
CDamageManager::ProgressEngineDamage(void)
|
||||
{
|
||||
int status = GetEngineStatus();
|
||||
int newstatus = status + 32 + (CGeneral::GetRandomNumber() & 0x1F);
|
||||
if(status < 225 && newstatus > 224)
|
||||
newstatus = 224;
|
||||
SetEngineStatus(newstatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x545850, &CDamageManager::ResetDamageStatus, PATCH_JUMP);
|
||||
InjectHook(0x545B70, &CDamageManager::FuckCarCompletely, PATCH_JUMP);
|
||||
InjectHook(0x545790, &CDamageManager::GetComponentGroup, PATCH_JUMP);
|
||||
InjectHook(0x545A80, &CDamageManager::ApplyDamage, PATCH_JUMP);
|
||||
InjectHook(0x545920, &CDamageManager::SetDoorStatus, PATCH_JUMP);
|
||||
InjectHook(0x545930, &CDamageManager::GetDoorStatus, PATCH_JUMP);
|
||||
InjectHook(0x545970, &CDamageManager::ProgressDoorDamage, PATCH_JUMP);
|
||||
InjectHook(0x5458B0, &CDamageManager::SetPanelStatus, PATCH_JUMP);
|
||||
InjectHook(0x5458E0, (int32 (CDamageManager::*)(int32))&CDamageManager::GetPanelStatus, PATCH_JUMP);
|
||||
InjectHook(0x545A00, &CDamageManager::ProgressPanelDamage, PATCH_JUMP);
|
||||
InjectHook(0x545860, &CDamageManager::SetLightStatus, PATCH_JUMP);
|
||||
InjectHook(0x545890, &CDamageManager::GetLightStatus, PATCH_JUMP);
|
||||
InjectHook(0x545900, &CDamageManager::SetWheelStatus, PATCH_JUMP);
|
||||
InjectHook(0x545910, &CDamageManager::GetWheelStatus, PATCH_JUMP);
|
||||
InjectHook(0x545A40, &CDamageManager::ProgressWheelDamage, PATCH_JUMP);
|
||||
InjectHook(0x545940, &CDamageManager::SetEngineStatus, PATCH_JUMP);
|
||||
InjectHook(0x545960, &CDamageManager::GetEngineStatus, PATCH_JUMP);
|
||||
InjectHook(0x5459B0, &CDamageManager::ProgressEngineDamage, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -2,53 +2,91 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// TODO: move some of this into Vehicle.h
|
||||
|
||||
enum tComponent
|
||||
{
|
||||
COMPONENT_DEFAULT,
|
||||
COMPONENT_WHEEL_FRONT_LEFT,
|
||||
COMPONENT_WHEEL_FRONT_RIGHT,
|
||||
COMPONENT_WHEEL_REAR_LEFT,
|
||||
COMPONENT_WHEEL_REAR_RIGHT,
|
||||
COMPONENT_DOOR_BONNET,
|
||||
COMPONENT_DOOR_BOOT,
|
||||
COMPONENT_DOOR_FRONT_LEFT,
|
||||
COMPONENT_DOOR_FRONT_RIGHT,
|
||||
COMPONENT_DOOR_REAR_LEFT,
|
||||
COMPONENT_DOOR_REAR_RIGHT,
|
||||
COMPONENT_PANEL_FRONT_LEFT,
|
||||
COMPONENT_PANEL_FRONT_RIGHT,
|
||||
COMPONENT_PANEL_REAR_LEFT,
|
||||
COMPONENT_PANEL_REAR_RIGHT,
|
||||
COMPONENT_PANEL_WINDSCREEN,
|
||||
COMPONENT_BUMPER_FRONT,
|
||||
COMPONENT_BUMPER_REAR,
|
||||
};
|
||||
|
||||
enum tComponentGroup
|
||||
{
|
||||
COMPGROUP_BUMPER,
|
||||
COMPGROUP_WHEEL,
|
||||
COMPGROUP_DOOR,
|
||||
COMPGROUP_BONNET,
|
||||
COMPGROUP_BOOT,
|
||||
COMPGROUP_PANEL,
|
||||
COMPGROUP_DEFAULT,
|
||||
};
|
||||
|
||||
enum eLights
|
||||
{
|
||||
VEHLIGHT_FRONT_LEFT,
|
||||
VEHLIGHT_FRONT_RIGHT,
|
||||
VEHLIGHT_REAR_LEFT,
|
||||
VEHLIGHT_REAR_RIGHT,
|
||||
};
|
||||
|
||||
enum {
|
||||
VEHPANEL_FRONT_LEFT,
|
||||
VEHPANEL_FRONT_RIGHT,
|
||||
VEHPANEL_REAR_LEFT,
|
||||
VEHPANEL_REAR_RIGHT,
|
||||
VEHPANEL_WINDSCREEN,
|
||||
VEHBUMPER_FRONT,
|
||||
VEHBUMPER_REAR,
|
||||
};
|
||||
|
||||
class CDamageManager
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
CAR_DOOR_BONNET = 0,
|
||||
CAR_DOOR_BUMPER,
|
||||
CAR_DOOR_LF,
|
||||
CAR_DOOR_RF,
|
||||
CAR_DOOR_LR,
|
||||
CAR_DOOR_RR
|
||||
};
|
||||
|
||||
enum {
|
||||
PANEL_FL = 0,
|
||||
PANEL_FR,
|
||||
PANEL_RL,
|
||||
PANEL_RR,
|
||||
PANEL_WINDSHIELD,
|
||||
PANEL_FRONT,
|
||||
PANEL_BACK
|
||||
};
|
||||
|
||||
struct PanelStatus {
|
||||
uint32 m_nPanelFrontLeftStatus : 4;
|
||||
uint32 m_nPanelFrontRightStatus : 4;
|
||||
uint32 m_nPanelBackLeftStatus : 4;
|
||||
uint32 m_nPanelBackRightStatus : 4;
|
||||
uint32 m_nWindshieldStatus : 4;
|
||||
uint32 m_nPanelFrontStatus : 4;
|
||||
uint32 m_nPanelBackStatus : 4;
|
||||
};
|
||||
|
||||
float field_0;
|
||||
char m_bEngineStatus;
|
||||
char m_bWheelStatus[4];
|
||||
char m_bDoorStatus[7];
|
||||
uint32 m_abLightStatus;
|
||||
union{
|
||||
PanelStatus m_sPanelsStatus;
|
||||
uint32 m_abPanelsStatus;
|
||||
};
|
||||
char field_24;
|
||||
char field_25;
|
||||
char field_26;
|
||||
char field_27;
|
||||
uint8 m_engineStatus;
|
||||
uint8 m_wheelStatus[4];
|
||||
uint8 m_doorStatus[6];
|
||||
uint32 m_lightStatus;
|
||||
uint32 m_panelStatus;
|
||||
uint32 field_24;
|
||||
|
||||
void SetDoorStatus(int, unsigned int);
|
||||
unsigned int GetDoorStatus(int);
|
||||
};
|
||||
void ResetDamageStatus(void);
|
||||
void FuckCarCompletely(void);
|
||||
bool ApplyDamage(tComponent component, float damage, float unused);
|
||||
bool GetComponentGroup(tComponent component, tComponentGroup *componentGroup, uint8 *foo);
|
||||
|
||||
void SetDoorStatus(int32 door, uint32 status);
|
||||
int32 GetDoorStatus(int32 door);
|
||||
bool ProgressDoorDamage(uint8 door);
|
||||
void SetPanelStatus(int32 panel, uint32 status);
|
||||
int32 GetPanelStatus(int32 panel);
|
||||
bool ProgressPanelDamage(uint8 panel);
|
||||
// needed for CReplay
|
||||
static int32 GetPanelStatus(uint32 panelstatus, int32 panel) { return ldb(panel*4, 4, panelstatus); }
|
||||
void SetLightStatus(eLights light, uint32 status);
|
||||
int32 GetLightStatus(eLights light);
|
||||
void SetWheelStatus(int32 wheel, uint32 status);
|
||||
int32 GetWheelStatus(int32 wheel);
|
||||
bool ProgressWheelDamage(uint8 wheel);
|
||||
void SetEngineStatus(uint32 status);
|
||||
int32 GetEngineStatus(void);
|
||||
bool ProgressEngineDamage(void);
|
||||
};
|
||||
VALIDATE_SIZE(CDamageManager, 0x1C);
|
||||
|
17
src/Door.h
17
src/Door.h
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct CDoor
|
||||
{
|
||||
float m_fAngleWhenOpened;
|
||||
float m_fAngleWhenClosed;
|
||||
char field_8;
|
||||
char field_9;
|
||||
char field_10;
|
||||
char field_11;
|
||||
float m_fAngle;
|
||||
float m_fPreviousAngle;
|
||||
float m_fAngularVelocity;
|
||||
CVector m_vecVelocity;
|
||||
};
|
@ -4,10 +4,6 @@ class CGeneral
|
||||
{
|
||||
public:
|
||||
static float GetATanOfXY(float x, float y){
|
||||
// why exactly doesn't this work?
|
||||
// if(y >= 0.0f) return atan2(x, y);
|
||||
// return atan2(x, y) + 2*M_PI;
|
||||
|
||||
if(x == 0.0f && y == 0.0f)
|
||||
return 0.0f;
|
||||
float xabs = fabs(x);
|
||||
@ -85,7 +81,7 @@ public:
|
||||
|
||||
// not too sure about all these...
|
||||
static uint16 GetRandomNumber(void)
|
||||
{ return myrand() & 0xFFFF; }
|
||||
{ return myrand() & MYRAND_MAX; }
|
||||
// Probably don't want to ever reach high
|
||||
static float GetRandomNumberInRange(float low, float high)
|
||||
{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }
|
||||
|
@ -1,5 +1,9 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Pools.h"
|
||||
#include "References.h"
|
||||
|
||||
CReference *CReferences::aRefs = (CReference*)0x70BBE0; //[NUMREFERENCES];
|
||||
@ -17,6 +21,45 @@ CReferences::Init(void)
|
||||
aRefs[NUMREFERENCES-1].next = nil;
|
||||
}
|
||||
|
||||
void
|
||||
CReferences::RemoveReferencesToPlayer(void)
|
||||
{
|
||||
if(FindPlayerVehicle())
|
||||
FindPlayerVehicle()->ResolveReferences();
|
||||
if(FindPlayerPed())
|
||||
FindPlayerPed()->ResolveReferences();
|
||||
}
|
||||
|
||||
void
|
||||
CReferences::PruneAllReferencesInWorld(void)
|
||||
{
|
||||
int i;
|
||||
CEntity *e;
|
||||
|
||||
i = CPools::GetPedPool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetPedPool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
|
||||
i = CPools::GetVehiclePool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetVehiclePool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
|
||||
i = CPools::GetObjectPool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetObjectPool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4A7350, CReferences::Init, PATCH_JUMP);
|
||||
InjectHook(0x4A7570, CReferences::RemoveReferencesToPlayer, PATCH_JUMP);
|
||||
InjectHook(0x4A75A0, CReferences::PruneAllReferencesInWorld, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -13,5 +13,8 @@ class CReferences
|
||||
public:
|
||||
static CReference *aRefs; //[NUMREFERENCES];
|
||||
static CReference *&pEmptyList;
|
||||
|
||||
static void Init(void);
|
||||
static void RemoveReferencesToPlayer(void);
|
||||
static void PruneAllReferencesInWorld(void);
|
||||
};
|
||||
|
@ -3,10 +3,11 @@
|
||||
|
||||
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
|
||||
int32 &CStats::HeadShots = *(int32*)0x8F647C;
|
||||
bool& CStats::CommercialPassed = *(bool*)0x8F4334;
|
||||
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
|
||||
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
|
||||
|
||||
void CStats::AnotherKillFrenzyPassed()
|
||||
{
|
||||
++NumberKillFrenziesPassed;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ class CStats
|
||||
public:
|
||||
static int32 &DaysPassed;
|
||||
static int32 &HeadShots;
|
||||
static bool& CommercialPassed;
|
||||
static int32 &NumberKillFrenziesPassed;
|
||||
static int32 &PeopleKilledByOthers;
|
||||
|
||||
|
@ -1,11 +1,57 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Weather.h"
|
||||
#include "Collision.h"
|
||||
#include "SurfaceTable.h"
|
||||
|
||||
float (*CSurfaceTable::ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS] = (float (*)[NUMADHESIVEGROUPS])0x8E29D4;
|
||||
|
||||
void
|
||||
CSurfaceTable::Initialise(char *filename)
|
||||
{
|
||||
int lineno, fieldno;
|
||||
char *line;
|
||||
char surfname[256];
|
||||
float adhesiveLimit;
|
||||
|
||||
CFileMgr::SetDir("");
|
||||
CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
|
||||
|
||||
line = (char*)work_buff;
|
||||
for(lineno = 0; lineno < NUMADHESIVEGROUPS; lineno++){
|
||||
// skip white space and comments
|
||||
while(*line == ' ' || *line == '\t' || *line == '\n' || *line == '\r' || *line == ';'){
|
||||
if(*line == ';'){
|
||||
while(*line != '\n' && *line != '\r')
|
||||
line++;
|
||||
}else
|
||||
line++;
|
||||
}
|
||||
|
||||
sscanf(line, "%s", surfname);
|
||||
// skip what we just read
|
||||
while(!(*line == ' ' || *line == '\t' || *line == ','))
|
||||
line++;
|
||||
|
||||
for(fieldno = 0; fieldno <= lineno; fieldno++){
|
||||
// skip white space
|
||||
while(*line == ' ' || *line == '\t' || *line == ',')
|
||||
line++;
|
||||
adhesiveLimit = 0.0f;
|
||||
if(*line != '-')
|
||||
sscanf(line, "%f", &adhesiveLimit);
|
||||
// skip what we just read
|
||||
while(!(*line == ' ' || *line == '\t' || *line == ',' || *line == '\n'))
|
||||
line++;
|
||||
|
||||
ms_aAdhesiveLimitTable[lineno][fieldno] = adhesiveLimit;
|
||||
ms_aAdhesiveLimitTable[fieldno][lineno] = adhesiveLimit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CSurfaceTable::GetAdhesionGroup(uint8 surfaceType)
|
||||
{
|
||||
@ -95,3 +141,10 @@ CSurfaceTable::GetAdhesiveLimit(CColPoint &colpoint)
|
||||
{
|
||||
return ms_aAdhesiveLimitTable[GetAdhesionGroup(colpoint.surfaceB)][GetAdhesionGroup(colpoint.surfaceA)];
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4AB8F0, CSurfaceTable::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4ABA60, CSurfaceTable::GetAdhesionGroup, PATCH_JUMP);
|
||||
InjectHook(0x4ABAA0, CSurfaceTable::GetWetMultiplier, PATCH_JUMP);
|
||||
InjectHook(0x4ABA30, CSurfaceTable::GetAdhesiveLimit, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -99,6 +99,7 @@ class CSurfaceTable
|
||||
// static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS];
|
||||
static float (*ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS];
|
||||
public:
|
||||
static void Initialise(char *filename);
|
||||
static int GetAdhesionGroup(uint8 surfaceType);
|
||||
static float GetWetMultiplier(uint8 surfaceType);
|
||||
static float GetAdhesiveLimit(CColPoint &colpoint);
|
||||
|
225
src/Zones.cpp
225
src/Zones.cpp
@ -43,7 +43,9 @@ CheckZoneInfo(CZoneInfo *info)
|
||||
assert(info->gangThreshold[7] <= info->gangThreshold[8]);
|
||||
}
|
||||
|
||||
wchar* CZone::GetTranslatedName() {
|
||||
wchar*
|
||||
CZone::GetTranslatedName(void)
|
||||
{
|
||||
return TheText.Get(name);
|
||||
}
|
||||
|
||||
@ -621,6 +623,224 @@ CTheZones::InitialiseAudioZoneArray(void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SaveAllZones(uint8 *buffer, uint32 *length)
|
||||
{
|
||||
int i;
|
||||
|
||||
*length = 8 + 12 +
|
||||
NUMZONES*56 + 2*NUMZONES*58 + 4 +
|
||||
NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4;
|
||||
|
||||
buffer[0] = 'Z';
|
||||
buffer[1] = 'N';
|
||||
buffer[2] = 'S';
|
||||
buffer[3] = '\0';
|
||||
*(uint32*)(buffer+4) = *length - 8;
|
||||
buffer += 8;
|
||||
|
||||
*(int32*)(buffer) = GetIndexForZonePointer(m_pPlayersZone);
|
||||
*(int32*)(buffer+4) = m_CurrLevel;
|
||||
*(int16*)(buffer+8) = FindIndex;
|
||||
*(int16*)(buffer+10) = 0;
|
||||
buffer += 12;
|
||||
|
||||
for(i = 0; i < NUMZONES; i++){
|
||||
memcpy(buffer, ZoneArray[i].name, 8);
|
||||
*(float*)(buffer+8) = ZoneArray[i].minx;
|
||||
*(float*)(buffer+12) = ZoneArray[i].miny;
|
||||
*(float*)(buffer+16) = ZoneArray[i].minz;
|
||||
*(float*)(buffer+20) = ZoneArray[i].maxx;
|
||||
*(float*)(buffer+24) = ZoneArray[i].maxy;
|
||||
*(float*)(buffer+28) = ZoneArray[i].maxz;
|
||||
*(int32*)(buffer+32) = ZoneArray[i].type;
|
||||
*(int32*)(buffer+36) = ZoneArray[i].level;
|
||||
*(int16*)(buffer+40) = ZoneArray[i].zoneinfoDay;
|
||||
*(int16*)(buffer+42) = ZoneArray[i].zoneinfoNight;
|
||||
*(int32*)(buffer+44) = GetIndexForZonePointer(ZoneArray[i].child);
|
||||
*(int32*)(buffer+48) = GetIndexForZonePointer(ZoneArray[i].parent);
|
||||
*(int32*)(buffer+52) = GetIndexForZonePointer(ZoneArray[i].next);
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < 2*NUMZONES; i++){
|
||||
*(int16*)(buffer) = ZoneInfoArray[i].carDensity;
|
||||
*(int16*)(buffer+2) = ZoneInfoArray[i].carThreshold[0];
|
||||
*(int16*)(buffer+4) = ZoneInfoArray[i].carThreshold[1];
|
||||
*(int16*)(buffer+6) = ZoneInfoArray[i].carThreshold[2];
|
||||
*(int16*)(buffer+8) = ZoneInfoArray[i].carThreshold[3];
|
||||
*(int16*)(buffer+10) = ZoneInfoArray[i].carThreshold[4];
|
||||
*(int16*)(buffer+12) = ZoneInfoArray[i].carThreshold[5];
|
||||
*(int16*)(buffer+14) = ZoneInfoArray[i].copThreshold;
|
||||
*(int16*)(buffer+16) = ZoneInfoArray[i].gangThreshold[0];
|
||||
*(int16*)(buffer+18) = ZoneInfoArray[i].gangThreshold[1];
|
||||
*(int16*)(buffer+20) = ZoneInfoArray[i].gangThreshold[2];
|
||||
*(int16*)(buffer+22) = ZoneInfoArray[i].gangThreshold[3];
|
||||
*(int16*)(buffer+24) = ZoneInfoArray[i].gangThreshold[4];
|
||||
*(int16*)(buffer+26) = ZoneInfoArray[i].gangThreshold[5];
|
||||
*(int16*)(buffer+28) = ZoneInfoArray[i].gangThreshold[6];
|
||||
*(int16*)(buffer+30) = ZoneInfoArray[i].gangThreshold[7];
|
||||
*(int16*)(buffer+32) = ZoneInfoArray[i].gangThreshold[8];
|
||||
*(uint16*)(buffer+34) = ZoneInfoArray[i].pedDensity;
|
||||
*(uint16*)(buffer+36) = ZoneInfoArray[i].copDensity;
|
||||
*(uint16*)(buffer+38) = ZoneInfoArray[i].gangDensity[0];
|
||||
*(uint16*)(buffer+40) = ZoneInfoArray[i].gangDensity[1];
|
||||
*(uint16*)(buffer+42) = ZoneInfoArray[i].gangDensity[2];
|
||||
*(uint16*)(buffer+44) = ZoneInfoArray[i].gangDensity[3];
|
||||
*(uint16*)(buffer+46) = ZoneInfoArray[i].gangDensity[4];
|
||||
*(uint16*)(buffer+48) = ZoneInfoArray[i].gangDensity[5];
|
||||
*(uint16*)(buffer+50) = ZoneInfoArray[i].gangDensity[6];
|
||||
*(uint16*)(buffer+52) = ZoneInfoArray[i].gangDensity[7];
|
||||
*(uint16*)(buffer+54) = ZoneInfoArray[i].gangDensity[8];
|
||||
*(uint16*)(buffer+56) = ZoneInfoArray[i].pedGroup;
|
||||
buffer += 58;
|
||||
}
|
||||
|
||||
*(uint16*)(buffer) = TotalNumberOfZones;
|
||||
*(uint16*)(buffer+2) = TotalNumberOfZoneInfos;
|
||||
buffer += 4;
|
||||
|
||||
for(i = 0; i < NUMMAPZONES; i++){
|
||||
memcpy(buffer, MapZoneArray[i].name, 8);
|
||||
*(float*)(buffer+8) = MapZoneArray[i].minx;
|
||||
*(float*)(buffer+12) = MapZoneArray[i].miny;
|
||||
*(float*)(buffer+16) = MapZoneArray[i].minz;
|
||||
*(float*)(buffer+20) = MapZoneArray[i].maxx;
|
||||
*(float*)(buffer+24) = MapZoneArray[i].maxy;
|
||||
*(float*)(buffer+28) = MapZoneArray[i].maxz;
|
||||
*(int32*)(buffer+32) = MapZoneArray[i].type;
|
||||
*(int32*)(buffer+36) = MapZoneArray[i].level;
|
||||
*(int16*)(buffer+40) = MapZoneArray[i].zoneinfoDay;
|
||||
*(int16*)(buffer+42) = MapZoneArray[i].zoneinfoNight;
|
||||
#ifdef STANDALONE
|
||||
// BUG: GetIndexForZonePointer uses ZoneArray
|
||||
// so indices will be unpredictable with different memory layout
|
||||
assert(0);
|
||||
#endif
|
||||
*(int32*)(buffer+44) = GetIndexForZonePointer(MapZoneArray[i].child);
|
||||
*(int32*)(buffer+48) = GetIndexForZonePointer(MapZoneArray[i].parent);
|
||||
*(int32*)(buffer+52) = GetIndexForZonePointer(MapZoneArray[i].next);
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < NUMAUDIOZONES; i++){
|
||||
*(int16*)buffer = AudioZoneArray[i];
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
*(uint16*)(buffer) = TotalNumberOfMapZones;
|
||||
*(uint16*)(buffer+2) = NumberOfAudioZones;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::LoadAllZones(uint8 *buffer, uint32 length)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(length == 8 + 12 +
|
||||
NUMZONES*56 + 2*NUMZONES*58 + 4 +
|
||||
NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4);
|
||||
assert(buffer[0] == 'Z');
|
||||
assert(buffer[1] == 'N');
|
||||
assert(buffer[2] == 'S');
|
||||
assert(buffer[3] == '\0');
|
||||
assert(*(uint32*)(buffer+4) == length - 8);
|
||||
buffer += 8;
|
||||
|
||||
m_pPlayersZone = GetPointerForZoneIndex(*(int32*)(buffer));
|
||||
m_CurrLevel = (eLevelName)*(int32*)(buffer+4);
|
||||
FindIndex = *(int16*)(buffer+8);
|
||||
assert(*(int16*)(buffer+10) == 0);
|
||||
buffer += 12;
|
||||
|
||||
for(i = 0; i < NUMZONES; i++){
|
||||
memcpy(ZoneArray[i].name, buffer, 8);
|
||||
ZoneArray[i].minx = *(float*)(buffer+8);
|
||||
ZoneArray[i].miny = *(float*)(buffer+12);
|
||||
ZoneArray[i].minz = *(float*)(buffer+16);
|
||||
ZoneArray[i].maxx = *(float*)(buffer+20);
|
||||
ZoneArray[i].maxy = *(float*)(buffer+24);
|
||||
ZoneArray[i].maxz = *(float*)(buffer+28);
|
||||
ZoneArray[i].type = (eZoneType)*(int32*)(buffer+32);
|
||||
ZoneArray[i].level = (eLevelName)*(int32*)(buffer+36);
|
||||
ZoneArray[i].zoneinfoDay = *(int16*)(buffer+40);
|
||||
ZoneArray[i].zoneinfoNight = *(int16*)(buffer+42);
|
||||
ZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44));
|
||||
ZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48));
|
||||
ZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52));
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < 2*NUMZONES; i++){
|
||||
ZoneInfoArray[i].carDensity = *(int16*)(buffer);
|
||||
ZoneInfoArray[i].carThreshold[0] = *(int16*)(buffer+2);
|
||||
ZoneInfoArray[i].carThreshold[1] = *(int16*)(buffer+4);
|
||||
ZoneInfoArray[i].carThreshold[2] = *(int16*)(buffer+6);
|
||||
ZoneInfoArray[i].carThreshold[3] = *(int16*)(buffer+8);
|
||||
ZoneInfoArray[i].carThreshold[4] = *(int16*)(buffer+10);
|
||||
ZoneInfoArray[i].carThreshold[5] = *(int16*)(buffer+12);
|
||||
ZoneInfoArray[i].copThreshold = *(int16*)(buffer+14);
|
||||
ZoneInfoArray[i].gangThreshold[0] = *(int16*)(buffer+16);
|
||||
ZoneInfoArray[i].gangThreshold[1] = *(int16*)(buffer+18);
|
||||
ZoneInfoArray[i].gangThreshold[2] = *(int16*)(buffer+20);
|
||||
ZoneInfoArray[i].gangThreshold[3] = *(int16*)(buffer+22);
|
||||
ZoneInfoArray[i].gangThreshold[4] = *(int16*)(buffer+24);
|
||||
ZoneInfoArray[i].gangThreshold[5] = *(int16*)(buffer+26);
|
||||
ZoneInfoArray[i].gangThreshold[6] = *(int16*)(buffer+28);
|
||||
ZoneInfoArray[i].gangThreshold[7] = *(int16*)(buffer+30);
|
||||
ZoneInfoArray[i].gangThreshold[8] = *(int16*)(buffer+32);
|
||||
ZoneInfoArray[i].pedDensity = *(uint16*)(buffer+34);
|
||||
ZoneInfoArray[i].copDensity = *(uint16*)(buffer+36);
|
||||
ZoneInfoArray[i].gangDensity[0] = *(uint16*)(buffer+38);
|
||||
ZoneInfoArray[i].gangDensity[1] = *(uint16*)(buffer+40);
|
||||
ZoneInfoArray[i].gangDensity[2] = *(uint16*)(buffer+42);
|
||||
ZoneInfoArray[i].gangDensity[3] = *(uint16*)(buffer+44);
|
||||
ZoneInfoArray[i].gangDensity[4] = *(uint16*)(buffer+46);
|
||||
ZoneInfoArray[i].gangDensity[5] = *(uint16*)(buffer+48);
|
||||
ZoneInfoArray[i].gangDensity[6] = *(uint16*)(buffer+50);
|
||||
ZoneInfoArray[i].gangDensity[7] = *(uint16*)(buffer+52);
|
||||
ZoneInfoArray[i].gangDensity[8] = *(uint16*)(buffer+54);
|
||||
ZoneInfoArray[i].pedGroup = *(uint16*)(buffer+56);
|
||||
buffer += 58;
|
||||
}
|
||||
|
||||
TotalNumberOfZones = *(uint16*)(buffer);
|
||||
TotalNumberOfZoneInfos = *(uint16*)(buffer+2);
|
||||
buffer += 4;
|
||||
|
||||
for(i = 0; i < NUMMAPZONES; i++){
|
||||
memcpy(MapZoneArray[i].name, buffer, 8);
|
||||
MapZoneArray[i].minx = *(float*)(buffer+8);
|
||||
MapZoneArray[i].miny = *(float*)(buffer+12);
|
||||
MapZoneArray[i].minz = *(float*)(buffer+16);
|
||||
MapZoneArray[i].maxx = *(float*)(buffer+20);
|
||||
MapZoneArray[i].maxy = *(float*)(buffer+24);
|
||||
MapZoneArray[i].maxz = *(float*)(buffer+28);
|
||||
MapZoneArray[i].type = (eZoneType)*(int32*)(buffer+32);
|
||||
MapZoneArray[i].level = (eLevelName)*(int32*)(buffer+36);
|
||||
MapZoneArray[i].zoneinfoDay = *(int16*)(buffer+40);
|
||||
MapZoneArray[i].zoneinfoNight = *(int16*)(buffer+42);
|
||||
#ifdef STANDALONE
|
||||
// BUG: GetPointerForZoneIndex uses ZoneArray
|
||||
// so pointers will be unpredictable with different memory layout
|
||||
assert(0);
|
||||
#endif
|
||||
MapZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44));
|
||||
MapZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48));
|
||||
MapZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52));
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < NUMAUDIOZONES; i++){
|
||||
AudioZoneArray[i] = *(int16*)buffer;
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
TotalNumberOfMapZones = *(uint16*)(buffer);
|
||||
NumberOfAudioZones = *(uint16*)(buffer+2);
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4B5DD0, &CZone::GetTranslatedName, PATCH_JUMP);
|
||||
InjectHook(0x4B5DE0, CTheZones::Init, PATCH_JUMP);
|
||||
@ -649,5 +869,6 @@ STARTPATCHES
|
||||
InjectHook(0x4B83E0, CTheZones::FindAudioZone, PATCH_JUMP);
|
||||
InjectHook(0x4B8430, CTheZones::FindZoneForPoint, PATCH_JUMP);
|
||||
InjectHook(0x4B8340, CTheZones::AddZoneToAudioZoneArray, PATCH_JUMP);
|
||||
InjectHook(0x4B8380, CTheZones::InitialiseAudioZoneArray, PATCH_JUMP);
|
||||
InjectHook(0x4B8510, CTheZones::SaveAllZones, PATCH_JUMP);
|
||||
InjectHook(0x4B8950, CTheZones::LoadAllZones, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
CZone *parent;
|
||||
CZone *next;
|
||||
|
||||
wchar *GetTranslatedName();
|
||||
wchar *GetTranslatedName(void);
|
||||
};
|
||||
|
||||
class CZoneInfo
|
||||
@ -104,6 +104,9 @@ public:
|
||||
static int16 FindAudioZone(CVector *pos);
|
||||
static eLevelName FindZoneForPoint(const CVector &pos);
|
||||
static CZone *GetPointerForZoneIndex(int32 i) { return i == -1 ? nil : &ZoneArray[i]; }
|
||||
static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - ZoneArray; }
|
||||
static void AddZoneToAudioZoneArray(CZone *zone);
|
||||
static void InitialiseAudioZoneArray(void);
|
||||
static void SaveAllZones(uint8 *buffer, uint32 *length);
|
||||
static void LoadAllZones(uint8 *buffer, uint32 length);
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,12 +71,14 @@ enum eAudioType : int32 {
|
||||
TOTAL_AUDIO_TYPES = 14,
|
||||
};
|
||||
|
||||
class CPhysical;
|
||||
|
||||
class tAudioEntity
|
||||
{
|
||||
public:
|
||||
eAudioType m_nType;
|
||||
void *m_pEntity;
|
||||
char m_bIsUsed;
|
||||
CPhysical *m_pEntity;
|
||||
bool m_bIsUsed;
|
||||
char m_bStatus;
|
||||
int16 m_awAudioEvent[4];
|
||||
char gap_18[2];
|
||||
@ -159,7 +161,7 @@ public:
|
||||
char field_22;
|
||||
char field_23;
|
||||
int field_24;
|
||||
char m_bIsPlayed;
|
||||
bool m_bIsPlayed;
|
||||
char field_29;
|
||||
char field_30;
|
||||
char field_31;
|
||||
@ -175,7 +177,7 @@ public:
|
||||
char field_2;
|
||||
char m_bActiveSamples;
|
||||
char field_4;
|
||||
char m_bDynamicAcousticModelingStatus;
|
||||
bool m_bDynamicAcousticModelingStatus;
|
||||
char field_6;
|
||||
char field_7;
|
||||
float field_8;
|
||||
@ -185,7 +187,7 @@ public:
|
||||
char field_15;
|
||||
int m_nTimer;
|
||||
tActiveSample m_sQueueSample;
|
||||
char m_bActiveSampleQueue;
|
||||
uint8 m_bActiveSampleQueue;
|
||||
char gap_109[3];
|
||||
tActiveSample m_asSamples[54];
|
||||
char m_abSampleQueueIndexTable[54];
|
||||
@ -216,7 +218,92 @@ public:
|
||||
char field_19195;
|
||||
int m_nTimeOfRecentCrime;
|
||||
|
||||
void PlayerJustLeftCar(void);
|
||||
char GetMissionScriptPoliceAudioPlayingStatus();
|
||||
bool GetMissionAudioLoadingStatus();
|
||||
|
||||
uint8 GetNum3DProvidersAvailable();
|
||||
int8 AutoDetect3DProviders();
|
||||
bool IsMP3RadioChannelAvailable();
|
||||
uint8 GetCDAudioDriveLetter();
|
||||
|
||||
void SetEffectsMasterVolume(uint8 volume);
|
||||
void SetMusicMasterVolume(uint8 volume);
|
||||
void SetEffectsFadeVol(uint8 volume);
|
||||
void SetMusicFadeVol(uint8 volume);
|
||||
|
||||
void SetSpeakerConfig(int32 conf);
|
||||
|
||||
void ProcessJumboFlying();
|
||||
bool SetupJumboEngineSound(uint8, int32); // todo
|
||||
void PreInitialiseGameSpecificSetup();
|
||||
void SetMissionScriptPoliceAudio(int32 sfx);
|
||||
|
||||
void CalculateDistance(bool *ptr, float dist);
|
||||
|
||||
bool UsesSiren(int32 model);
|
||||
bool UsesSirenSwitching(int32 model);
|
||||
|
||||
bool MissionScriptAudioUsesPoliceChannel(int32 soundMission);
|
||||
|
||||
uint8 Get3DProviderName(uint8 id);
|
||||
|
||||
void ProcessJumboTaxi();
|
||||
bool SetupJumboFlySound(uint8); // todo
|
||||
bool SetupJumboTaxiSound(uint8); // todo
|
||||
bool SetupJumboWhineSound(uint8, int32); // todo
|
||||
|
||||
void PlayLoadedMissionAudio();
|
||||
|
||||
void SetMissionAudioLocation(float x, float y, float z);
|
||||
|
||||
void ResetPoliceRadio();
|
||||
|
||||
void InterrogateAudioEntities();
|
||||
|
||||
void ClearRequestedQueue();
|
||||
// void AgeCrimes();
|
||||
|
||||
bool UsesReverseWarning(int32 model);
|
||||
bool HasAirBrakes(int32 model);
|
||||
|
||||
int32 GetJumboTaxiFreq();
|
||||
|
||||
void ProcessPhysical(int32 id);
|
||||
void ProcessVehicle(CPhysical *); // todo
|
||||
void ProcessPed(CPhysical *); // todo
|
||||
void ProcessPlane(void *); // todo
|
||||
|
||||
void ClearMissionAudio();
|
||||
// void ProcessReverb();
|
||||
|
||||
bool IsMissionAudioSampleFinished();
|
||||
|
||||
void ProcessEntity(int32);
|
||||
|
||||
void InitialisePoliceRadio();
|
||||
|
||||
// done
|
||||
|
||||
int32 RandomDisplacement(uint32 seed);
|
||||
|
||||
void ReleaseDigitalHandle();
|
||||
void RequireDigitalHandle();
|
||||
void SetDynamicAcousticModelingStatus(bool status);
|
||||
|
||||
bool IsAudioInitialised() const;
|
||||
|
||||
int32 CreateEntity(int32 type, CPhysical *memory);
|
||||
void DestroyEntity(int32 id);
|
||||
void SetEntityStatus(int32 id, bool status);
|
||||
|
||||
void PreTerminateGameSpecificShutdown();
|
||||
void PostTerminateGameSpecificShutdown();
|
||||
|
||||
void GenerateIntegerRandomNumberTable();
|
||||
|
||||
void PlayerJustGotInCar();
|
||||
void PlayerJustLeftCar();
|
||||
|
||||
void Service();
|
||||
void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample,
|
||||
uint32 maxOffset);
|
||||
|
@ -1,9 +1,92 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "SampleManager.h"
|
||||
|
||||
CSampleManager &cSampleManager = *(CSampleManager *)0x7341E0;
|
||||
uint32 &CSampleManager::nNumOfMp3Files = *(uint32*)0x95CC00;
|
||||
|
||||
uint32 &nNumOfMp3Files = *(uint32 *)0x95CC00;
|
||||
uint8 &num3DProvidersAvailable = *(uint8 *)0x734237;
|
||||
uint32 *asName3DProviders = (uint32 *)0x734238;
|
||||
|
||||
bool CSampleManager::IsMP3RadioChannelAvailable() {
|
||||
return nNumOfMp3Files != 0;
|
||||
}
|
||||
|
||||
WRAPPER void
|
||||
CSampleManager::ReleaseDigitalHandle()
|
||||
{
|
||||
EAXJMP(0x5664B0);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::RequireDigitalHandle()
|
||||
{
|
||||
EAXJMP(0x5664F0);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
char
|
||||
CSampleManager::AutoDetect3DProviders()
|
||||
{
|
||||
EAXJMP(0x565990);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
uint8
|
||||
CSampleManager::GetCDAudioDriveLetter()
|
||||
{
|
||||
EAXJMP(0x566F20);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::SetEffectsMasterVolume(uint8 volume)
|
||||
{
|
||||
EAXJMP(0x567010);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::SetMusicMasterVolume(uint8 volume)
|
||||
{
|
||||
EAXJMP(0x567020);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::SetEffectsFadeVol(uint8 volume)
|
||||
{
|
||||
EAXJMP(0x567030);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::SetMusicFadeVol(uint8 volume)
|
||||
{
|
||||
EAXJMP(0x567040);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::SetSpeakerConfig(uint32 config)
|
||||
{
|
||||
EAXJMP(0x565900);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
bool
|
||||
CSampleManager::GetChannelUsedFlag(int32 id)
|
||||
{
|
||||
EAXJMP(0x567B00);
|
||||
}
|
||||
|
||||
WRAPPER
|
||||
void
|
||||
CSampleManager::StopChannel(int32 id)
|
||||
{
|
||||
EAXJMP(0x567BE0);
|
||||
}
|
||||
STARTPATCHES
|
||||
InjectHook(0x566490, CSampleManager::IsMP3RadioChannelAvailable, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,11 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
class CSampleManager {
|
||||
public:
|
||||
static uint32 &nNumOfMp3Files;
|
||||
struct tSample {
|
||||
int m_nOffset;
|
||||
unsigned int m_nSize;
|
||||
int m_nFrequency;
|
||||
int m_nLoopStart;
|
||||
int m_nLoopEnd;
|
||||
};
|
||||
|
||||
class CSampleManager
|
||||
{
|
||||
public:
|
||||
void ReleaseDigitalHandle();
|
||||
void RequireDigitalHandle();
|
||||
|
||||
char AutoDetect3DProviders();
|
||||
uint8 GetCDAudioDriveLetter();
|
||||
|
||||
void SetEffectsMasterVolume(uint8 volume);
|
||||
void SetMusicMasterVolume(uint8 volume);
|
||||
void SetEffectsFadeVol(uint8 volume);
|
||||
void SetMusicFadeVol(uint8 volume);
|
||||
|
||||
void SetSpeakerConfig(uint32 config);
|
||||
|
||||
bool GetChannelUsedFlag(int32 id);
|
||||
void StopChannel(int32 id);
|
||||
|
||||
static bool IsMP3RadioChannelAvailable();
|
||||
};
|
||||
|
||||
extern uint32 &nNumOfMp3Files;
|
||||
extern uint8 &num3DProvidersAvailable;
|
||||
extern uint32* asName3DProviders;
|
||||
|
||||
extern CSampleManager &cSampleManager;
|
13
src/common.h
13
src/common.h
@ -49,6 +49,19 @@ typedef uint16_t wchar;
|
||||
|
||||
#define ALIGNPTR(p) (void*)((((uintptr)(void*)p) + sizeof(void*)-1) & ~(sizeof(void*)-1))
|
||||
|
||||
// PDP-10 like byte functions
|
||||
#define MASK(p, s) (((1<<(s))-1) << (p))
|
||||
inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)
|
||||
{
|
||||
uint32 m = MASK(p,s);
|
||||
return w & ~m | b<<p & m;
|
||||
}
|
||||
inline uint32 ldb(uint32 p, uint32 s, uint32 w)
|
||||
{
|
||||
return w>>p & (1<<s)-1;
|
||||
}
|
||||
|
||||
|
||||
// little hack
|
||||
extern void **rwengine;
|
||||
#define RwEngineInstance (*rwengine)
|
||||
|
@ -62,6 +62,9 @@ enum Config {
|
||||
NUMPICKUPS = 336,
|
||||
};
|
||||
|
||||
// We'll use this once we're ready to become independent of the game
|
||||
// Use it to mark bugs in the code that will prevent the game from working then
|
||||
//#define STANDALONE
|
||||
|
||||
// We don't expect to compile for PS2 or Xbox
|
||||
// but it might be interesting for documentation purposes
|
||||
@ -85,7 +88,7 @@ enum Config {
|
||||
#elif defined GTA_PC
|
||||
# define GTA3_1_1_PATCH
|
||||
# ifdef GTA_PS2_STUFF
|
||||
# define USE_PS2_RAND
|
||||
//# define USE_PS2_RAND // this is unsafe until we have the game reversed
|
||||
# define RANDOMSPLASH // use random splash as on PS2
|
||||
# define PS2_MATFX
|
||||
# endif
|
||||
|
89
src/control/AutoPilot.h
Normal file
89
src/control/AutoPilot.h
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
class CVehicle;
|
||||
|
||||
enum eCarMission : uint8
|
||||
{
|
||||
MISSION_NONE,
|
||||
MISSION_CRUISE,
|
||||
MISSION_RAMPLAYER_FARAWAY,
|
||||
MISSION_RAMPLAYER_CLOSE,
|
||||
MISSION_BLOCKPLAYER_FARAWAY,
|
||||
MISSION_BLOCKPLAYER_CLOSE,
|
||||
MISSION_BLOCKPLAYER_HANDBRAKESTOP,
|
||||
MISSION_WAITFORDELETION,
|
||||
MISSION_GOTOCOORDS,
|
||||
MISSION_GOTOCOORDS_STRAIGHT,
|
||||
MISSION_EMERGENCYVEHICLE_STOP,
|
||||
MISSION_STOP_FOREVER,
|
||||
MISSION_GOTOCOORDS_ACCURATE,
|
||||
MISSION_GOTO_COORDS_STRAIGHT_ACCURATE,
|
||||
MISSION_GOTOCOORDS_ASTHECROWSWIMS,
|
||||
MISSION_RAMCAR_FARAWAY,
|
||||
MISSION_RAMCAR_CLOSE,
|
||||
MISSION_BLOCKCAR_FARAWAY,
|
||||
MISSION_BLOCKCAR_CLOSE,
|
||||
MISSION_BLOCKCAR_HANDBRAKESTOP,
|
||||
MISSION_HELI_FLYTOCOORS,
|
||||
MISSION_ATTACKPLAYER,
|
||||
MISSION_PLANE_FLYTOCOORS,
|
||||
MISSION_HELI_LAND,
|
||||
MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1,
|
||||
MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2,
|
||||
MISSION_BLOCKPLAYER_FORWARDANDBACK
|
||||
};
|
||||
|
||||
enum eCarTempAction : uint8
|
||||
{
|
||||
TEMPACT_NONE,
|
||||
TEMPACT_WAIT,
|
||||
TEMPACT_REVERSE,
|
||||
TEMPACT_HANDBRAKETURNLEFT,
|
||||
TEMPACT_HANDBRAKETURNRIGHT,
|
||||
TEMPACT_HANDBRAKESTRAIGHT,
|
||||
TEMPACT_TURNLEFT,
|
||||
TEMPACT_TURNRIGHT,
|
||||
TEMPACT_GOFORWARD,
|
||||
TEMPACT_SWERVELEFT,
|
||||
TEMPACT_SWERVERIGHT
|
||||
};
|
||||
|
||||
enum eCarDrivingStyle : uint8
|
||||
{
|
||||
DRIVINGSTYLE_STOP_FOR_CARS,
|
||||
DRIVINGSTYLE_SLOW_DOWN_FOR_CARS,
|
||||
DRIVINGSTYLE_AVOID_CARS,
|
||||
DRIVINGSTYLE_PLOUGH_THROUGH,
|
||||
DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS
|
||||
};
|
||||
|
||||
class CAutoPilot {
|
||||
public:
|
||||
void *m_currentAddress;
|
||||
void *m_startingRouteNode;
|
||||
void *m_PreviousRouteNode;
|
||||
uint32 m_nTotalSpeedScaleFactor;
|
||||
uint32 m_nSpeedScaleFactor;
|
||||
uint32 m_nCurrentPathNodeInfo;
|
||||
uint32 m_nNextPathNodeInfo;
|
||||
uint32 m_nPreviousPathNodeInfo;
|
||||
uint32 m_nTimeToStartMission;
|
||||
uint32 m_nTimeSwitchedToRealPhysics;
|
||||
int8 m_nPreviousDirection;
|
||||
int8 m_nCurrentDirecton;
|
||||
int8 m_nNextDirection;
|
||||
int8 m_nPreviousPathDirection;
|
||||
int8 m_nCurrentPathDirection;
|
||||
eCarDrivingStyle m_nDrivingStyle;
|
||||
eCarMission m_nCarMission;
|
||||
eCarTempAction m_nAnimationId;
|
||||
uint8 m_nAnimationTime;
|
||||
float m_fMaxTrafficSpeed;
|
||||
uint8 m_nCruiseSpeed;
|
||||
uint8 m_nCarCtrlFlags;
|
||||
CVector m_vecDestinationCoors;
|
||||
void *m_aPathFindNodesInfo[8];
|
||||
uint16 m_nPathFindNodesCount;
|
||||
CVehicle *m_pTargetCar;
|
||||
};
|
||||
static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error");
|
@ -1,5 +1,154 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Bridge.h"
|
||||
#include "Pools.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "PathFind.h"
|
||||
#include "Stats.h"
|
||||
|
||||
WRAPPER bool CBridge::ShouldLightsBeFlashing(void) { EAXJMP(0x413D10); }
|
||||
CEntity*& CBridge::pLiftRoad = *(CEntity**)0x8E2C8C;
|
||||
CEntity*& CBridge::pLiftPart = *(CEntity**)0x8E2C94;
|
||||
CEntity*& CBridge::pWeight = *(CEntity**)0x8E28BC;
|
||||
|
||||
int& CBridge::State = *(int*)0x8F2A1C;
|
||||
int& CBridge::OldState = *(int*)0x8F2A20;
|
||||
|
||||
float& CBridge::DefaultZLiftPart = *(float*)0x941430;
|
||||
float& CBridge::DefaultZLiftRoad = *(float*)0x941438;
|
||||
float& CBridge::DefaultZLiftWeight = *(float*)0x8F1A44;
|
||||
|
||||
float& CBridge::OldLift = *(float*)0x8F6254;
|
||||
|
||||
uint32& CBridge::TimeOfBridgeBecomingOperational = *(uint32*)0x8F2BC0;
|
||||
|
||||
void CBridge::Init()
|
||||
{
|
||||
FindBridgeEntities();
|
||||
OldLift = -1.0;
|
||||
if (pLiftPart && pWeight)
|
||||
{
|
||||
DefaultZLiftPart = pLiftPart->GetPosition().z;
|
||||
DefaultZLiftWeight = pWeight->GetPosition().z;
|
||||
|
||||
if (pLiftRoad)
|
||||
DefaultZLiftRoad = pLiftRoad->GetPosition().z;
|
||||
|
||||
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CBridge::Update()
|
||||
{
|
||||
if (!pLiftPart || !pWeight)
|
||||
return;
|
||||
|
||||
OldState = State;
|
||||
|
||||
float liftHeight;
|
||||
|
||||
if (CStats::CommercialPassed)
|
||||
{
|
||||
if (TimeOfBridgeBecomingOperational == 0)
|
||||
TimeOfBridgeBecomingOperational = CTimer::GetTimeInMilliseconds();
|
||||
|
||||
// Time remaining for bridge to become operational
|
||||
// uint16, so after about a minute it overflows to 0 and the cycle repeats
|
||||
uint16 timeElapsed = CTimer::GetTimeInMilliseconds() - TimeOfBridgeBecomingOperational;
|
||||
|
||||
// Calculate lift part height and bridge state
|
||||
if (timeElapsed < 10000)
|
||||
{
|
||||
State = STATE_LIFT_PART_MOVING_DOWN;
|
||||
liftHeight = 25.0 - timeElapsed / 10000.0 * 25.0;
|
||||
}
|
||||
else if (timeElapsed < 40000)
|
||||
{
|
||||
liftHeight = 0.0;
|
||||
State = STATE_LIFT_PART_IS_DOWN;
|
||||
}
|
||||
else if (timeElapsed < 50000)
|
||||
{
|
||||
liftHeight = 0.0;
|
||||
State = STATE_LIFT_PART_ABOUT_TO_MOVE_UP;
|
||||
}
|
||||
else if (timeElapsed < 60000)
|
||||
{
|
||||
State = STATE_LIFT_PART_MOVING_UP;
|
||||
liftHeight = (timeElapsed - 50000) / 10000.0 * 25.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
liftHeight = 25.0;
|
||||
State = STATE_LIFT_PART_IS_UP;
|
||||
}
|
||||
|
||||
// Move bridge part
|
||||
if (liftHeight != OldLift)
|
||||
{
|
||||
pLiftPart->GetPosition().z = DefaultZLiftPart + liftHeight;
|
||||
pLiftPart->GetMatrix().UpdateRW();
|
||||
pLiftPart->UpdateRwFrame();
|
||||
if (pLiftRoad)
|
||||
{
|
||||
pLiftRoad->GetPosition().z = DefaultZLiftRoad + liftHeight;
|
||||
pLiftRoad->GetMatrix().UpdateRW();
|
||||
pLiftRoad->UpdateRwFrame();
|
||||
}
|
||||
pWeight->GetPosition().z = DefaultZLiftWeight - liftHeight;
|
||||
pWeight->GetMatrix().UpdateRW();
|
||||
pWeight->UpdateRwFrame();
|
||||
|
||||
OldLift = liftHeight;
|
||||
}
|
||||
|
||||
if (State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP && OldState == STATE_LIFT_PART_IS_DOWN)
|
||||
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
|
||||
else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)
|
||||
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
liftHeight = 25.0;
|
||||
TimeOfBridgeBecomingOperational = 0;
|
||||
State = STATE_BRIDGE_LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
bool CBridge::ShouldLightsBeFlashing() { return State != STATE_LIFT_PART_IS_DOWN; }
|
||||
|
||||
void CBridge::FindBridgeEntities()
|
||||
{
|
||||
pWeight = nil;
|
||||
pLiftRoad = nil;
|
||||
pLiftPart = nil;
|
||||
|
||||
for (int i = 1; i < CPools::GetBuildingPool()->GetSize(); ++i)
|
||||
{
|
||||
CBuilding* entry = CPools::GetBuildingPool()->GetSlot(i);
|
||||
if (entry)
|
||||
{
|
||||
if (entry->GetModelIndex() == MI_BRIDGELIFT)
|
||||
pLiftPart = entry;
|
||||
else if (entry->GetModelIndex() == MI_BRIDGEROADSEGMENT)
|
||||
pLiftRoad = entry;
|
||||
else if (entry->GetModelIndex() == MI_BRIDGEWEIGHT)
|
||||
pWeight = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CBridge::ThisIsABridgeObjectMovingUp(int index)
|
||||
{
|
||||
if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT)
|
||||
return false;
|
||||
|
||||
return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x413A30, &CBridge::Init, PATCH_JUMP);
|
||||
InjectHook(0x413AC0, &CBridge::Update, PATCH_JUMP);
|
||||
InjectHook(0x413D10, &CBridge::ShouldLightsBeFlashing, PATCH_JUMP);
|
||||
InjectHook(0x413D20, &CBridge::FindBridgeEntities, PATCH_JUMP);
|
||||
InjectHook(0x413DE0, &CBridge::ThisIsABridgeObjectMovingUp, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,7 +1,30 @@
|
||||
#pragma once
|
||||
#include "Entity.h"
|
||||
|
||||
class CBridge
|
||||
{
|
||||
private:
|
||||
enum bridgeStates
|
||||
{
|
||||
STATE_BRIDGE_LOCKED,
|
||||
STATE_LIFT_PART_IS_UP,
|
||||
STATE_LIFT_PART_MOVING_DOWN,
|
||||
STATE_LIFT_PART_IS_DOWN,
|
||||
STATE_LIFT_PART_ABOUT_TO_MOVE_UP,
|
||||
STATE_LIFT_PART_MOVING_UP
|
||||
};
|
||||
|
||||
|
||||
static CEntity *&pLiftRoad, *&pLiftPart, *&pWeight;
|
||||
static int &State, &OldState;
|
||||
static float &DefaultZLiftPart, &DefaultZLiftRoad, &DefaultZLiftWeight;
|
||||
static float& OldLift;
|
||||
static uint32& TimeOfBridgeBecomingOperational;
|
||||
|
||||
public:
|
||||
static bool ShouldLightsBeFlashing(void);
|
||||
static void Init();
|
||||
static void Update();
|
||||
static bool ShouldLightsBeFlashing();
|
||||
static void FindBridgeEntities();
|
||||
static bool ThisIsABridgeObjectMovingUp(int);
|
||||
};
|
||||
|
@ -626,6 +626,8 @@ CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out)
|
||||
*out = m_mapObjects[id]->GetMatrix() * pos;
|
||||
}
|
||||
|
||||
WRAPPER void CPathFind::SetLinksBridgeLights(float, float, float, float, bool) { EAXJMP(0x42E3B0); }
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x429610, &CPathFind::PreparePathData, PATCH_JUMP);
|
||||
InjectHook(0x429C20, &CPathFind::PreparePathDataForType, PATCH_JUMP);
|
||||
|
@ -131,6 +131,8 @@ public:
|
||||
int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool disabled, bool betweenLevels);
|
||||
|
||||
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
|
||||
|
||||
void SetLinksBridgeLights(float, float, float, float, bool);
|
||||
};
|
||||
static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error");
|
||||
|
||||
|
@ -10,3 +10,4 @@ float &CPopulation::PedDensityMultiplier = *(float*)0x5FA56C;
|
||||
|
||||
WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); }
|
||||
WRAPPER void CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool) { EAXJMP(0x4F6200); }
|
||||
WRAPPER CPed *CPopulation::AddPedInCar(CVehicle *vehicle) { EAXJMP(0x4F5800); }
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "PedType.h"
|
||||
class CPed;
|
||||
class CVehicle;
|
||||
|
||||
struct PedGroup
|
||||
{
|
||||
@ -17,4 +18,5 @@ public:
|
||||
|
||||
static void UpdatePedCount(uint32, bool);
|
||||
static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
|
||||
static CPed *AddPedInCar(CVehicle *vehicle);
|
||||
};
|
||||
|
@ -135,34 +135,33 @@ WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0
|
||||
#else
|
||||
static void ApplyPanelDamageToCar(uint32 panels, CAutomobile* vehicle, bool flying)
|
||||
{
|
||||
CDamageManager::PanelStatus rp = *(CDamageManager::PanelStatus*)&panels;
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontLeftStatus != rp.m_nPanelFrontLeftStatus){
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontLeftStatus = rp.m_nPanelFrontLeftStatus;
|
||||
vehicle->SetPanelDamage(13, CDamageManager::PANEL_FL, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHPANEL_FRONT_LEFT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_LEFT)){
|
||||
vehicle->Damage.SetPanelStatus(VEHPANEL_FRONT_LEFT, CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_LEFT));
|
||||
vehicle->SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontRightStatus != rp.m_nPanelFrontRightStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontRightStatus = rp.m_nPanelFrontRightStatus;
|
||||
vehicle->SetPanelDamage(9, CDamageManager::PANEL_FR, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHPANEL_FRONT_RIGHT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_RIGHT)){
|
||||
vehicle->Damage.SetPanelStatus(VEHPANEL_FRONT_RIGHT, CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_RIGHT));
|
||||
vehicle->SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackLeftStatus != rp.m_nPanelBackLeftStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackLeftStatus = rp.m_nPanelBackLeftStatus;
|
||||
vehicle->SetPanelDamage(14, CDamageManager::PANEL_RL, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHPANEL_REAR_LEFT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_LEFT)){
|
||||
vehicle->Damage.SetPanelStatus(VEHPANEL_REAR_LEFT, CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_LEFT));
|
||||
vehicle->SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackRightStatus != rp.m_nPanelBackRightStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackRightStatus = rp.m_nPanelBackRightStatus;
|
||||
vehicle->SetPanelDamage(10, CDamageManager::PANEL_RR, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHPANEL_REAR_RIGHT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_RIGHT)){
|
||||
vehicle->Damage.SetPanelStatus(VEHPANEL_REAR_RIGHT, CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_RIGHT));
|
||||
vehicle->SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nWindshieldStatus != rp.m_nWindshieldStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nWindshieldStatus = rp.m_nWindshieldStatus;
|
||||
vehicle->SetPanelDamage(19, CDamageManager::PANEL_WINDSHIELD, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) != CDamageManager::GetPanelStatus(panels, VEHPANEL_WINDSCREEN)){
|
||||
vehicle->Damage.SetPanelStatus(VEHPANEL_WINDSCREEN, CDamageManager::GetPanelStatus(panels, VEHPANEL_WINDSCREEN));
|
||||
vehicle->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontStatus != rp.m_nPanelFrontStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontStatus = rp.m_nPanelFrontStatus;
|
||||
vehicle->SetPanelDamage(7, CDamageManager::PANEL_FRONT, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHBUMPER_FRONT) != CDamageManager::GetPanelStatus(panels, VEHBUMPER_FRONT)){
|
||||
vehicle->Damage.SetPanelStatus(VEHBUMPER_FRONT, CDamageManager::GetPanelStatus(panels, VEHBUMPER_FRONT));
|
||||
vehicle->SetPanelDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT, flying);
|
||||
}
|
||||
if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackStatus != rp.m_nPanelBackStatus) {
|
||||
vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackStatus = rp.m_nPanelBackStatus;
|
||||
vehicle->SetPanelDamage(8, CDamageManager::PANEL_BACK, flying);
|
||||
if(vehicle->Damage.GetPanelStatus(VEHBUMPER_REAR) != CDamageManager::GetPanelStatus(panels, VEHBUMPER_REAR)){
|
||||
vehicle->Damage.SetPanelStatus(VEHBUMPER_REAR, CDamageManager::GetPanelStatus(panels, VEHBUMPER_REAR));
|
||||
vehicle->SetPanelDamage(CAR_BUMP_REAR, VEHBUMPER_REAR, flying);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -625,7 +624,7 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id)
|
||||
vp->matrix.CompressFromFullMatrix(vehicle->GetMatrix());
|
||||
vp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */
|
||||
vp->acceleration = vehicle->m_fGasPedal * 100.0f;
|
||||
vp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->m_DamageManager.m_abPanelsStatus : 0;
|
||||
vp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->Damage.m_panelStatus : 0;
|
||||
vp->velocityX = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().x)); /* 8000!? */
|
||||
vp->velocityY = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().y));
|
||||
vp->velocityZ = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().z));
|
||||
@ -639,14 +638,14 @@ 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_afWheelSuspDist[i];
|
||||
vp->wheel_rotation[i] = 128.0f / M_PI * car->m_afWheelRotation[i];
|
||||
vp->wheel_susp_dist[i] = 50.0f * car->m_aWheelDist[i];
|
||||
vp->wheel_rotation[i] = 128.0f / M_PI * car->m_aWheelRotation[i];
|
||||
}
|
||||
vp->door_angles[0] = 127.0f / M_PI * car->m_aDoors[2].m_fAngle;
|
||||
vp->door_angles[1] = 127.0f / M_PI * car->m_aDoors[3].m_fAngle;
|
||||
vp->door_angles[0] = 127.0f / M_PI * car->Doors[2].m_fAngle;
|
||||
vp->door_angles[1] = 127.0f / M_PI * car->Doors[3].m_fAngle;
|
||||
vp->door_status = 0;
|
||||
for (int i = 0; i < 6; i++){
|
||||
if (car->m_DamageManager.m_bDoorStatus[i] == 3)
|
||||
if (car->Damage.GetDoorStatus(i) == 3)
|
||||
vp->door_status |= BIT(i);
|
||||
}
|
||||
}
|
||||
@ -684,42 +683,42 @@ void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressI
|
||||
if (vehicle->IsCar()) {
|
||||
CAutomobile* car = (CAutomobile*)vehicle;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
car->m_afWheelSuspDist[i] = vp->wheel_susp_dist[i] / 50.0f;
|
||||
car->m_afWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f;
|
||||
car->m_aWheelDist[i] = vp->wheel_susp_dist[i] / 50.0f;
|
||||
car->m_aWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f;
|
||||
}
|
||||
car->m_aDoors[2].m_fAngle = car->m_aDoors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f;
|
||||
car->m_aDoors[3].m_fAngle = car->m_aDoors[3].m_fPreviousAngle = vp->door_angles[1] * M_PI / 127.0f;
|
||||
car->Doors[2].m_fAngle = car->Doors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f;
|
||||
car->Doors[3].m_fAngle = car->Doors[3].m_fPreviousAngle = vp->door_angles[1] * M_PI / 127.0f;
|
||||
if (vp->door_angles[0])
|
||||
car->m_DamageManager.m_bDoorStatus[2] = 2;
|
||||
car->Damage.SetDoorStatus(2, 2);
|
||||
if (vp->door_angles[1])
|
||||
car->m_DamageManager.m_bDoorStatus[3] = 2;
|
||||
if (vp->door_status & 1 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BONNET) != 3){
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BONNET, 3);
|
||||
car->SetDoorDamage(17, CDamageManager::CAR_DOOR_BONNET, true);
|
||||
car->Damage.SetDoorStatus(3, 2);
|
||||
if (vp->door_status & 1 && car->Damage.GetDoorStatus(DOOR_BONNET) != 3){
|
||||
car->Damage.SetDoorStatus(DOOR_BONNET, 3);
|
||||
car->SetDoorDamage(CAR_BONNET, DOOR_BONNET, true);
|
||||
}
|
||||
if (vp->door_status & 2 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BUMPER) != 3) {
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BUMPER, 3);
|
||||
car->SetDoorDamage(18, CDamageManager::CAR_DOOR_BUMPER, true);
|
||||
if (vp->door_status & 2 && car->Damage.GetDoorStatus(DOOR_BOOT) != 3) {
|
||||
car->Damage.SetDoorStatus(DOOR_BOOT, 3);
|
||||
car->SetDoorDamage(CAR_BOOT, DOOR_BOOT, true);
|
||||
}
|
||||
if (vp->door_status & 4 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LF) != 3) {
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LF, 3);
|
||||
car->SetDoorDamage(15, CDamageManager::CAR_DOOR_LF, true);
|
||||
if (vp->door_status & 4 && car->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != 3) {
|
||||
car->Damage.SetDoorStatus(DOOR_FRONT_LEFT, 3);
|
||||
car->SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT, true);
|
||||
}
|
||||
if (vp->door_status & 8 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RF) != 3) {
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RF, 3);
|
||||
car->SetDoorDamage(11, CDamageManager::CAR_DOOR_RF, true);
|
||||
if (vp->door_status & 8 && car->Damage.GetDoorStatus(DOOR_FRONT_RIGHT) != 3) {
|
||||
car->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, 3);
|
||||
car->SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT, true);
|
||||
}
|
||||
if (vp->door_status & 0x10 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LR) != 3) {
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LR, 3);
|
||||
car->SetDoorDamage(16, CDamageManager::CAR_DOOR_LR, true);
|
||||
if (vp->door_status & 0x10 && car->Damage.GetDoorStatus(DOOR_REAR_LEFT) != 3) {
|
||||
car->Damage.SetDoorStatus(DOOR_REAR_LEFT, 3);
|
||||
car->SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT, true);
|
||||
}
|
||||
if (vp->door_status & 0x20 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RR) != 3) {
|
||||
car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RR, 3);
|
||||
car->SetDoorDamage(12, CDamageManager::CAR_DOOR_RR, true);
|
||||
if (vp->door_status & 0x20 && car->Damage.GetDoorStatus(DOOR_REAR_RIGHT) != 3) {
|
||||
car->Damage.SetDoorStatus(DOOR_REAR_RIGHT, 3);
|
||||
car->SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT, true);
|
||||
}
|
||||
vehicle->m_veh_flagA10 = true;
|
||||
vehicle->bEngineOn = true;
|
||||
if (vehicle->IsCar())
|
||||
((CAutomobile*)vehicle)->m_nDriveWheelsOnGround = 4;
|
||||
((CAutomobile*)vehicle)->m_nWheelsOnGround = 4;
|
||||
CWorld::Remove(vehicle);
|
||||
CWorld::Add(vehicle);
|
||||
if (vehicle->IsBoat())
|
||||
@ -1186,24 +1185,24 @@ void CReplay::RestoreStuffFromMem(void)
|
||||
vehicle->SetModelIndex(mi);
|
||||
if (mi == MI_DODO){
|
||||
CAutomobile* dodo = (CAutomobile*)vehicle;
|
||||
GetFirstObject(dodo->m_apModelNodes[4])->flags = 0; /* TODO: 4 to enum */
|
||||
RpAtomicSetFlags(GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0);
|
||||
CMatrix tmp1;
|
||||
tmp1.Attach(&dodo->m_apModelNodes[1]->modelling, false);
|
||||
CMatrix tmp2(&dodo->m_apModelNodes[4]->modelling, false);
|
||||
tmp1.Attach(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_RF]), false);
|
||||
CMatrix tmp2(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_LF]), false);
|
||||
*tmp1.GetPosition() += CVector(tmp2.GetPosition()->x + 0.1f, 0.0f, tmp2.GetPosition()->z);
|
||||
tmp1.UpdateRW();
|
||||
}
|
||||
if (vehicle->IsCar()){
|
||||
CAutomobile* car = (CAutomobile*)vehicle;
|
||||
int32 panels = car->m_DamageManager.m_abPanelsStatus;
|
||||
car->m_DamageManager.m_abPanelsStatus = 0;
|
||||
int32 panels = car->Damage.m_panelStatus;
|
||||
car->Damage.m_panelStatus = 0;
|
||||
ApplyPanelDamageToCar(panels, car, true);
|
||||
car->SetDoorDamage(17, 0, true); /* BONNET */
|
||||
car->SetDoorDamage(18, 1, true); /* BUMPER */
|
||||
car->SetDoorDamage(15, 2, true); /* DOOR_FRONT_LEFT */
|
||||
car->SetDoorDamage(11, 3, true); /* DOOR_FRONT_RIGHT */
|
||||
car->SetDoorDamage(16, 4, true); /* DOOR_BACK_LEFT */
|
||||
car->SetDoorDamage(12, 5, true); /* DOOR_BACK_RIGHT */
|
||||
car->SetDoorDamage(CAR_BONNET, DOOR_BONNET, true);
|
||||
car->SetDoorDamage(CAR_BOOT, DOOR_BOOT, true);
|
||||
car->SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT, true);
|
||||
car->SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT, true);
|
||||
car->SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT, true);
|
||||
car->SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT, true);
|
||||
}
|
||||
vehicle->m_audioEntityId = DMAudio.CreateEntity(0, vehicle);
|
||||
DMAudio.SetEntityStatus(vehicle->m_audioEntityId, true);
|
||||
|
@ -1,26 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "DamageManager.h"
|
||||
#include "Door.h"
|
||||
#include "RwHelper.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
struct CDoor
|
||||
{
|
||||
float m_fAngleWhenOpened;
|
||||
float m_fAngleWhenClosed;
|
||||
char field_8;
|
||||
char field_9;
|
||||
char field_10;
|
||||
char field_11;
|
||||
float m_fAngle;
|
||||
float m_fPreviousAngle;
|
||||
float m_fAngularVelocity;
|
||||
CVector m_vecVelocity;
|
||||
};
|
||||
|
||||
class CAutomobile : public CVehicle
|
||||
{
|
||||
public:
|
||||
// 0x288
|
||||
CDamageManager m_DamageManager;
|
||||
CDoor m_aDoors[6];
|
||||
RwFrame *m_apModelNodes[20];
|
||||
uint8 stuff1[160];
|
||||
float m_afWheelSuspDist[4];
|
||||
uint8 stuff2[44];
|
||||
float m_afWheelRotation[4];
|
||||
uint8 stuff3[200];
|
||||
CDamageManager Damage;
|
||||
CDoor Doors[6];
|
||||
RwFrame *m_aCarNodes[NUM_CAR_NODES];
|
||||
CColPoint m_aWheelColPoints[4];
|
||||
float m_aWheelDist[4];
|
||||
float m_aWheelDist_2[4];
|
||||
float m_aWheelSkidThing[4];
|
||||
int field_49C;
|
||||
bool m_aWheelSkidmarkMuddy[4];
|
||||
bool m_aWheelSkidmarkBloody[4];
|
||||
float m_aWheelRotation[4];
|
||||
float m_aWheelPosition[4];
|
||||
float m_aWheelSpeed[4];
|
||||
uint8 stuff3[12];
|
||||
uint32 m_nBusDoorTimerEnd;
|
||||
uint32 m_nBusDoorTimerStart;
|
||||
float m_aSuspensionRange[4];
|
||||
float m_aSuspensionLineLength[4];
|
||||
float m_fHeightAboveRoad;
|
||||
float m_fImprovedHandling;
|
||||
uint8 stuff6[32];
|
||||
CPhysical *m_aGroundPhysical[4]; // physicals touching wheels
|
||||
CVector m_aGroundOffset[4]; // from ground object to colpoint
|
||||
CEntity *m_pBlowUpEntity;
|
||||
float m_weaponThingA; // TODO
|
||||
float m_weaponThingB; // TODO
|
||||
float m_fCarGunLR;
|
||||
uint8 stuff4[13];
|
||||
uint8 m_nDriveWheelsOnGround;
|
||||
uint8 stuff5[22];
|
||||
float m_fCarGunUD;
|
||||
float m_fWindScreenRotation;
|
||||
uint8 stuff4[4];
|
||||
uint8 m_nWheelsOnGround_2;
|
||||
uint8 m_nWheelsOnGround;
|
||||
uint8 m_nWheelsOnGroundPrev;
|
||||
uint8 stuff5[5];
|
||||
int32 m_aWheelState[4];
|
||||
|
||||
CAutomobile(int, uint8);
|
||||
CAutomobile* ctor(int, uint8);
|
||||
@ -30,4 +65,4 @@ public:
|
||||
void dtor() { this->CAutomobile::~CAutomobile(); }
|
||||
};
|
||||
static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error");
|
||||
static_assert(offsetof(CAutomobile, m_afWheelSuspDist) == 0x46C, "CAutomobile: error");
|
||||
static_assert(offsetof(CAutomobile, m_aWheelDist) == 0x46C, "CAutomobile: error");
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "Lights.h"
|
||||
#include "Pools.h"
|
||||
#include "Radar.h"
|
||||
#include "Object.h"
|
||||
@ -63,6 +65,26 @@ CObject::Render(void)
|
||||
CEntity::Render();
|
||||
}
|
||||
|
||||
bool
|
||||
CObject::SetupLighting(void)
|
||||
{
|
||||
DeActivateDirectional();
|
||||
SetAmbientColours();
|
||||
|
||||
if(bRenderScorched){
|
||||
WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CObject::RemoveLighting(bool reset)
|
||||
{
|
||||
if(reset)
|
||||
WorldReplaceScorchedLightsWithNormal(Scene.world);
|
||||
}
|
||||
|
||||
WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); }
|
||||
|
||||
STARTPATCHES
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
~CObject(void);
|
||||
|
||||
void Render(void);
|
||||
bool SetupLighting(void);
|
||||
void RemoveLighting(bool reset);
|
||||
|
||||
void ObjectDamage(float amount);
|
||||
|
||||
|
@ -24,21 +24,23 @@
|
||||
#include "PointLights.h"
|
||||
#include "Pad.h"
|
||||
|
||||
WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); }
|
||||
WRAPPER void CPed::KillPedWithCar(CVehicle* veh, float impulse) { EAXJMP(0x4EC430); }
|
||||
WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); }
|
||||
WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); }
|
||||
WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); }
|
||||
WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
|
||||
WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); }
|
||||
WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); }
|
||||
WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2480); }
|
||||
WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2920); }
|
||||
WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); }
|
||||
WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); }
|
||||
WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
|
||||
WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); }
|
||||
WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); }
|
||||
WRAPPER void CPed::Render(void) { EAXJMP(0x4D03F0); }
|
||||
WRAPPER int32 CPed::ProcessEntityCollision(CEntity*, CColPoint*) { EAXJMP(0x4CBB30); }
|
||||
WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
|
||||
WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); }
|
||||
WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); }
|
||||
WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); }
|
||||
WRAPPER void CPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); }
|
||||
|
||||
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
|
||||
@ -61,14 +63,7 @@ CPed::~CPed(void)
|
||||
CWorld::Remove(this);
|
||||
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
|
||||
if (bInVehicle && m_pMyVehicle){
|
||||
uint8 door_flag = 0;
|
||||
switch (m_vehEnterType) {
|
||||
case VEHICLE_ENTER_FRONT_LEFT: door_flag = 1; break;
|
||||
case VEHICLE_ENTER_REAR_LEFT: door_flag = 2; break;
|
||||
case VEHICLE_ENTER_FRONT_RIGHT: door_flag = 4; break;
|
||||
case VEHICLE_ENTER_REAR_RIGHT: door_flag = 8; break;
|
||||
default: break;
|
||||
}
|
||||
uint8 door_flag = GetVehEnterExitFlag(m_vehEnterType);
|
||||
if (m_pMyVehicle->pDriver == this)
|
||||
m_pMyVehicle->pDriver = nil;
|
||||
else {
|
||||
@ -105,7 +100,7 @@ CPed::FlagToDestroyWhenNextProcessed(void)
|
||||
}
|
||||
bInVehicle = false;
|
||||
m_pMyVehicle = nil;
|
||||
if (m_nCreatedBy == CREATED_BY_SCRIPT)
|
||||
if (CharCreatedBy == MISSION_CHAR)
|
||||
m_nPedState = PED_DEAD;
|
||||
else
|
||||
m_nPedState = PED_NONE;
|
||||
@ -284,7 +279,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||
m_talkType = 167;
|
||||
m_objective = OBJECTIVE_NONE;
|
||||
m_prevObjective = OBJECTIVE_NONE;
|
||||
m_nCreatedBy = CREATED_BY_RANDOM;
|
||||
CharCreatedBy = RANDOM_CHAR;
|
||||
m_leader = nil;
|
||||
m_pedInObjective = nil;
|
||||
m_carInObjective = nil;
|
||||
@ -331,7 +326,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||
m_fleeTimer = 0;
|
||||
m_vecSeekPosEx = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_seekExAngle = 0.0f;
|
||||
m_nWaitState = 0;
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
m_nWaitTimer = 0;
|
||||
m_pCollidingEntity = nil;
|
||||
m_nPedState = PED_IDLE;
|
||||
@ -371,15 +366,15 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||
|
||||
bIsRestoringGun = false;
|
||||
bCanPointGunAtTarget = false;
|
||||
m_ped_flagB4 = false;
|
||||
m_ped_flagB8 = false;
|
||||
m_ped_flagB10 = false;
|
||||
bIsTalking = false;
|
||||
bIsInTheAir = false;
|
||||
bIsLanding = false;
|
||||
m_ped_flagB20 = false;
|
||||
m_ped_flagB40 = false;
|
||||
m_ped_flagB80 = false;
|
||||
|
||||
m_ped_flagC1 = false;
|
||||
m_ped_flagC2 = true;
|
||||
bRespondsToThreats = true;
|
||||
m_ped_flagC4 = true;
|
||||
m_ped_flagC8 = false;
|
||||
m_ped_flagC10 = false;
|
||||
@ -398,9 +393,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||
|
||||
m_ped_flagE1 = false;
|
||||
m_ped_flagE2 = false;
|
||||
m_ped_flagE4 = false;
|
||||
m_ped_flagE8 = false;
|
||||
bCantFireBecauseCrouched = false;
|
||||
bNotAllowedToDuck = false;
|
||||
bCrouchWhenShooting = false;
|
||||
bIsDucking = false;
|
||||
m_ped_flagE20 = false;
|
||||
bDoBloodyFootprints = false;
|
||||
m_ped_flagE80 = false;
|
||||
@ -636,7 +631,7 @@ bool
|
||||
CPed::IsPedInControl(void)
|
||||
{
|
||||
return m_nPedState <= PED_STATES_NO_AI
|
||||
&& !m_ped_flagB8 && !m_ped_flagB10
|
||||
&& !bIsInTheAir && !bIsLanding
|
||||
&& m_fHealth > 0.0f;
|
||||
}
|
||||
|
||||
@ -1020,7 +1015,7 @@ CPed::Attack(void)
|
||||
if (reloadAnim != NUM_ANIMS)
|
||||
reloadAnimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, reloadAnim);
|
||||
|
||||
if (bCantFireBecauseCrouched)
|
||||
if (bIsDucking)
|
||||
return;
|
||||
|
||||
if (reloadAnimAssoc) {
|
||||
@ -1281,7 +1276,7 @@ CPed::ClearDuck(void)
|
||||
|
||||
if (animAssoc) {
|
||||
|
||||
if (m_ped_flagE8) {
|
||||
if (bCrouchWhenShooting) {
|
||||
|
||||
if (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN) {
|
||||
animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_RBLOCK_CSHOOT);
|
||||
@ -1291,7 +1286,7 @@ CPed::ClearDuck(void)
|
||||
}
|
||||
}
|
||||
} else
|
||||
bCantFireBecauseCrouched = false;
|
||||
bIsDucking = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1342,13 +1337,13 @@ CPed::BeingDraggedFromCar(void)
|
||||
if (m_vehEnterType == VEHICLE_ENTER_FRONT_LEFT || m_vehEnterType == VEHICLE_ENTER_REAR_LEFT) {
|
||||
if (m_ped_flagF10) {
|
||||
enterAnim = ANIM_CAR_QJACKED;
|
||||
} else if (m_pMyVehicle->bIsLow) {
|
||||
} else if (m_pMyVehicle->bLowVehicle) {
|
||||
enterAnim = ANIM_CAR_LJACKED_LHS;
|
||||
} else {
|
||||
enterAnim = ANIM_CAR_JACKED_LHS;
|
||||
}
|
||||
} else if (m_vehEnterType == VEHICLE_ENTER_FRONT_RIGHT || m_vehEnterType == VEHICLE_ENTER_REAR_RIGHT) {
|
||||
if (m_pMyVehicle->bIsLow)
|
||||
if (m_pMyVehicle->bLowVehicle)
|
||||
enterAnim = ANIM_CAR_LJACKED_RHS;
|
||||
else
|
||||
enterAnim = ANIM_CAR_JACKED_RHS;
|
||||
@ -1401,20 +1396,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
|
||||
ped->m_pSeekTarget = nil;
|
||||
vehicle = ped->m_pMyVehicle;
|
||||
|
||||
switch (ped->m_vehEnterType) {
|
||||
case VEHICLE_ENTER_FRONT_RIGHT:
|
||||
vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FR;
|
||||
break;
|
||||
case VEHICLE_ENTER_REAR_RIGHT:
|
||||
vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RR;
|
||||
break;
|
||||
case VEHICLE_ENTER_FRONT_LEFT:
|
||||
vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_FL;
|
||||
break;
|
||||
case VEHICLE_ENTER_REAR_LEFT:
|
||||
vehicle->m_nGettingOutFlags &= ~GETTING_IN_OUT_RL;
|
||||
break;
|
||||
}
|
||||
vehicle->m_nGettingOutFlags &= ~GetVehEnterExitFlag(ped->m_vehEnterType);
|
||||
|
||||
if (vehicle->pDriver == ped) {
|
||||
vehicle->RemoveDriver();
|
||||
@ -1471,7 +1453,7 @@ CPed::GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enter
|
||||
vehDoorOffset = offsetToOpenVanDoor;
|
||||
} else {
|
||||
seatOffset = veh->m_handling->fSeatOffsetDistance * seatPosMult;
|
||||
if (veh->bIsLow) {
|
||||
if (veh->bLowVehicle) {
|
||||
vehDoorOffset = offsetToOpenLowCarDoor;
|
||||
} else {
|
||||
vehDoorOffset = offsetToOpenRegularCarDoor;
|
||||
@ -1743,7 +1725,6 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
|
||||
}
|
||||
}
|
||||
|
||||
// I hope
|
||||
bool stillGettingInOut = false;
|
||||
if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
|
||||
stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || m_ped_flagG10;
|
||||
@ -1938,7 +1919,7 @@ CPed::IsPointerValid(void)
|
||||
|
||||
// Some kind of binary sort
|
||||
void
|
||||
CPed::SortPeds(CPed** list, int min, int max)
|
||||
CPed::SortPeds(CPed **list, int min, int max)
|
||||
{
|
||||
if (min >= max)
|
||||
return;
|
||||
@ -1978,7 +1959,7 @@ CPed::SortPeds(CPed** list, int min, int max)
|
||||
void
|
||||
CPed::BuildPedLists(void)
|
||||
{
|
||||
static CPed* unsortedNearPeds[10];
|
||||
static CPed *unsortedNearPeds[10];
|
||||
uint16 nextNearPedSlot = 0;
|
||||
|
||||
if ((CTimer::GetFrameCounter() + m_randomSeed) & 15) {
|
||||
@ -2223,10 +2204,10 @@ CPed::CanBeDeleted(void)
|
||||
if (this->bInVehicle)
|
||||
return false;
|
||||
|
||||
switch (m_nCreatedBy) {
|
||||
case CREATED_BY_RANDOM:
|
||||
switch (CharCreatedBy) {
|
||||
case RANDOM_CHAR:
|
||||
return true;
|
||||
case CREATED_BY_SCRIPT:
|
||||
case MISSION_CHAR:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
@ -2522,7 +2503,7 @@ CPed::SetObjective(eObjective newObj, void *entity)
|
||||
m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f);
|
||||
if (newObj == OBJECTIVE_SOLICIT) {
|
||||
m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
|
||||
} else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_nCreatedBy == CREATED_BY_SCRIPT &&
|
||||
} else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR &&
|
||||
(m_carInObjective->m_status == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls)) {
|
||||
SetObjectiveTimer(14000);
|
||||
} else {
|
||||
@ -2544,6 +2525,350 @@ CPed::SetObjective(eObjective newObj, void *entity)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPed::SetIdle(void)
|
||||
{
|
||||
if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
|
||||
m_nPedState = PED_IDLE;
|
||||
SetMoveState(PEDMOVE_STILL);
|
||||
}
|
||||
if (m_nWaitState == WAITSTATE_FALSE) {
|
||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPed::SetObjective(eObjective newObj)
|
||||
{
|
||||
if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
|
||||
return;
|
||||
|
||||
if (newObj == OBJECTIVE_NONE) {
|
||||
if ((m_objective == OBJECTIVE_LEAVE_VEHICLE || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
|
||||
&& IsPedInControl()) {
|
||||
|
||||
m_ped_flagG8 = true;
|
||||
return;
|
||||
}
|
||||
// Unused code from assembly...
|
||||
/*
|
||||
else if(m_objective == OBJECTIVE_FLEE_CAR) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
*/
|
||||
m_objective = newObj;
|
||||
m_prevObjective = OBJECTIVE_NONE;
|
||||
} else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) {
|
||||
SetObjectiveTimer(0);
|
||||
|
||||
if (m_objective == newObj)
|
||||
return;
|
||||
|
||||
if (IsTemporaryObjective(m_objective)) {
|
||||
m_prevObjective = newObj;
|
||||
} else {
|
||||
if (m_objective != newObj)
|
||||
SetStoredObjective();
|
||||
|
||||
m_objective = newObj;
|
||||
}
|
||||
m_ped_flagD40 = false;
|
||||
|
||||
switch (newObj) {
|
||||
case OBJECTIVE_NONE:
|
||||
m_prevObjective = OBJECTIVE_NONE;
|
||||
break;
|
||||
case OBJECTIVE_HAIL_TAXI:
|
||||
m_nWaitTimer = 0;
|
||||
SetIdle();
|
||||
SetMoveState(PEDMOVE_STILL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode
|
||||
// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call...
|
||||
void
|
||||
CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)
|
||||
{
|
||||
if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD)
|
||||
return;
|
||||
|
||||
if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
|
||||
return;
|
||||
|
||||
SetObjectiveTimer(0);
|
||||
|
||||
if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
|
||||
return;
|
||||
|
||||
m_ped_flagD40 = false;
|
||||
if (IsTemporaryObjective(m_objective)) {
|
||||
m_prevObjective = newObj;
|
||||
} else {
|
||||
if (m_objective != newObj)
|
||||
SetStoredObjective();
|
||||
|
||||
m_objective = newObj;
|
||||
}
|
||||
|
||||
if (newObj == OBJECTIVE_FOLLOW_ROUTE) {
|
||||
SetFollowRoute(routePoint, routeType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPed::ClearChat(void)
|
||||
{
|
||||
CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT);
|
||||
if (animAssoc) {
|
||||
animAssoc->blendDelta = -8.0f;
|
||||
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
||||
}
|
||||
bIsTalking = false;
|
||||
ClearLookFlag();
|
||||
RestorePreviousState();
|
||||
}
|
||||
|
||||
bool
|
||||
CPed::IsGangMember(void)
|
||||
{
|
||||
return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;
|
||||
}
|
||||
|
||||
void
|
||||
CPed::InformMyGangOfAttack(CEntity *attacker)
|
||||
{
|
||||
CPed *attackerPed;
|
||||
|
||||
if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)
|
||||
return;
|
||||
|
||||
if (attacker->IsPed()) {
|
||||
attackerPed = (CPed*)attacker;
|
||||
} else {
|
||||
if (!attacker->IsVehicle())
|
||||
return;
|
||||
|
||||
attackerPed = ((CVehicle*)attacker)->pDriver;
|
||||
if (!attackerPed)
|
||||
return;
|
||||
}
|
||||
|
||||
if (attackerPed->m_nPedType == PEDTYPE_COP)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < m_numNearPeds; i++) {
|
||||
CPed *nearPed = m_nearPeds[i];
|
||||
if (nearPed && nearPed != this) {
|
||||
CPed *leader = nearPed->m_leader;
|
||||
if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper)
|
||||
{
|
||||
nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed);
|
||||
nearPed->SetObjectiveTimer(30000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPed::QuitEnteringCar(void)
|
||||
{
|
||||
CAnimBlendAssociation *animAssoc = m_pVehicleAnim;
|
||||
CVehicle *veh = m_pMyVehicle;
|
||||
if (animAssoc)
|
||||
animAssoc->blendDelta = -1000.0f;
|
||||
|
||||
RestartNonPartialAnims();
|
||||
|
||||
if (!RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_STANCE))
|
||||
CAnimManager::BlendAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE, 100.0f);
|
||||
|
||||
if (veh) {
|
||||
if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
|
||||
veh->m_veh_flagC10 = false;
|
||||
|
||||
if (veh->m_nNumGettingIn != 0)
|
||||
veh->m_nNumGettingIn--;
|
||||
|
||||
veh->m_nGettingInFlags = GetVehEnterExitFlag(m_vehEnterType);
|
||||
}
|
||||
|
||||
bUsesCollision = true;
|
||||
|
||||
if (IsPlayer() && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
|
||||
if (IsPlayer() && m_storedWeapon != NO_STORED_WEAPON) {
|
||||
SetCurrentWeapon(m_storedWeapon);
|
||||
m_storedWeapon = NO_STORED_WEAPON;
|
||||
}
|
||||
} else {
|
||||
CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
|
||||
AddWeaponModel(curWeapon->m_nModelId);
|
||||
}
|
||||
if (m_nPedState == PED_DIE || m_nPedState == PED_DEAD) {
|
||||
animAssoc = m_pVehicleAnim;
|
||||
if (animAssoc) {
|
||||
animAssoc->blendDelta = -4.0;
|
||||
animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
|
||||
animAssoc = m_pVehicleAnim;
|
||||
animAssoc->flags &= ~ASSOC_RUNNING;
|
||||
}
|
||||
} else
|
||||
SetIdle();
|
||||
|
||||
m_pVehicleAnim = nil;
|
||||
|
||||
if (veh) {
|
||||
if (veh->m_autoPilot.m_nCruiseSpeed == 0)
|
||||
veh->m_autoPilot.m_nCruiseSpeed = 17;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPed::ReactToAttack(CEntity *attacker)
|
||||
{
|
||||
if (IsPlayer() && attacker->IsPed()) {
|
||||
InformMyGangOfAttack(attacker);
|
||||
SetLookFlag(attacker, 1);
|
||||
SetLookTimer(700);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
|
||||
CPed *ourLeader = m_leader;
|
||||
if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader)
|
||||
&& attacker->IsPed()) {
|
||||
|
||||
CPed *attackerPed = (CPed*)attacker;
|
||||
if (bNotAllowedToDuck) {
|
||||
if (!attackerPed->GetWeapon()->IsTypeMelee()) {
|
||||
field_4E8 = CTimer::GetTimeInMilliseconds();
|
||||
return;
|
||||
}
|
||||
} else if (bCrouchWhenShooting || m_ped_flagE1) {
|
||||
SetDuck(CGeneral::GetRandomNumberInRange(1000,3000));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) {
|
||||
if (m_pedStats != attackerPed->m_pedStats) {
|
||||
if (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {
|
||||
RegisterThreatWithGangPeds(attackerPed);
|
||||
}
|
||||
if (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) {
|
||||
SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker);
|
||||
SetMoveState(PEDMOVE_RUN);
|
||||
} else {
|
||||
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);
|
||||
SetObjectiveTimer(20000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed);
|
||||
SetMoveState(PEDMOVE_RUN);
|
||||
if (attackerPed->GetWeapon()->IsTypeMelee())
|
||||
Say(SOUND_PED_FLEE_RUN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CPed::TurnBody(void)
|
||||
{
|
||||
float lookDir;
|
||||
bool doneSmoothly = true;
|
||||
|
||||
if (m_pLookTarget) {
|
||||
CVector &lookPos = m_pLookTarget->GetPosition();
|
||||
|
||||
lookDir = CGeneral::GetRadianAngleBetweenPoints(
|
||||
lookPos.x,
|
||||
lookPos.y,
|
||||
GetPosition().x,
|
||||
GetPosition().y);
|
||||
} else
|
||||
lookDir = m_fLookDirection;
|
||||
|
||||
float limitedLookDir = CGeneral::LimitRadianAngle(lookDir);
|
||||
float currentRot = m_fRotationCur;
|
||||
|
||||
if (currentRot - PI > limitedLookDir)
|
||||
limitedLookDir += 2 * PI;
|
||||
else if (PI + currentRot < limitedLookDir)
|
||||
limitedLookDir -= 2 * PI;
|
||||
|
||||
float neededTurn = currentRot - limitedLookDir;
|
||||
m_fRotationDest = limitedLookDir;
|
||||
|
||||
if (fabs(neededTurn) > 0.05f) {
|
||||
doneSmoothly = false;
|
||||
currentRot -= neededTurn * 0.2f;
|
||||
}
|
||||
|
||||
m_fRotationCur = currentRot;
|
||||
m_fLookDirection = limitedLookDir;
|
||||
return doneSmoothly;
|
||||
}
|
||||
|
||||
void
|
||||
CPed::Chat(void)
|
||||
{
|
||||
if (bIsLooking && TurnBody())
|
||||
ClearLookFlag();
|
||||
|
||||
if (!m_pLookTarget || !m_pLookTarget->IsPed()) {
|
||||
ClearChat();
|
||||
return;
|
||||
}
|
||||
|
||||
CPed *partner = (CPed*) m_pLookTarget;
|
||||
|
||||
if (partner->m_nPedState != PED_CHAT) {
|
||||
ClearChat();
|
||||
if (partner->m_pedInObjective) {
|
||||
if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
|
||||
partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)
|
||||
ReactToAttack(partner->m_pedInObjective);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (bIsTalking) {
|
||||
if (CGeneral::GetRandomNumber() < 512) {
|
||||
CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation((RpClump*) m_rwObject, ANIM_IDLE_CHAT);
|
||||
if (chatAssoc) {
|
||||
chatAssoc->blendDelta = -4.0f;
|
||||
chatAssoc->flags |= ASSOC_FADEOUTWHENDONE;
|
||||
}
|
||||
bIsTalking = false;
|
||||
} else
|
||||
Say(SOUND_PED_CHAT);
|
||||
|
||||
} else if (!RpAnimBlendClumpGetFirstAssociation((RpClump*)m_rwObject, ASSOC_FLAG100)) {
|
||||
|
||||
if (CGeneral::GetRandomNumber() < 20) {
|
||||
CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
|
||||
}
|
||||
if (!bIsTalking) {
|
||||
CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation((RpClump*) m_rwObject, ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
|
||||
float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
|
||||
chatAssoc->SetCurrentTime(chatTime);
|
||||
|
||||
bIsTalking = true;
|
||||
Say(SOUND_PED_CHAT);
|
||||
}
|
||||
}
|
||||
if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
|
||||
ClearChat();
|
||||
m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
|
||||
}
|
||||
}
|
||||
|
||||
WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); }
|
||||
WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); }
|
||||
WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); }
|
||||
@ -2612,5 +2937,14 @@ STARTPATCHES
|
||||
InjectHook(0x4D72F0, &CPed::CanPedJumpThis, PATCH_JUMP);
|
||||
InjectHook(0x4DD820, &CPed::CanSeeEntity, PATCH_JUMP);
|
||||
InjectHook(0x4D9460, &CPed::RestorePreviousObjective, PATCH_JUMP);
|
||||
InjectHook(0x4D82C0, (void (CPed::*)(eObjective)) &CPed::SetObjective, PATCH_JUMP);
|
||||
InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP);
|
||||
InjectHook(0x4D89A0, (void (CPed::*)(eObjective, int16, int16)) &CPed::SetObjective, PATCH_JUMP);
|
||||
InjectHook(0x4DDEC0, &CPed::ReactToAttack, PATCH_JUMP);
|
||||
InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP);
|
||||
InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP);
|
||||
InjectHook(0x4E4AD0, &CPed::InformMyGangOfAttack, PATCH_JUMP);
|
||||
InjectHook(0x4D3C80, &CPed::ClearChat, PATCH_JUMP);
|
||||
InjectHook(0x4D1390, &CPed::TurnBody, PATCH_JUMP);
|
||||
InjectHook(0x4D3AC0, &CPed::Chat, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -13,7 +13,31 @@
|
||||
|
||||
struct CPathNode;
|
||||
|
||||
enum eObjective {
|
||||
enum eWaitState : uint32 {
|
||||
WAITSTATE_FALSE,
|
||||
WAITSTATE_TRAFFIC_LIGHTS,
|
||||
WAITSTATE_CROSS_ROAD,
|
||||
WAITSTATE_CROSS_ROAD_LOOK,
|
||||
WAITSTATE_LOOK_PED,
|
||||
WAITSTATE_LOOK_SHOP,
|
||||
WAITSTATE_LOOK_ACCIDENT,
|
||||
WAITSTATE_FACEOFF_GANG,
|
||||
WAITSTATE_DOUBLEBACK,
|
||||
WAITSTATE_HITWALL,
|
||||
WAITSTATE_TURN180,
|
||||
WAITSTATE_SURPRISE,
|
||||
WAITSTATE_STUCK,
|
||||
WAITSTATE_LOOK_ABOUT,
|
||||
WAITSTATE_PLAYANIM_DUCK,
|
||||
WAITSTATE_PLAYANIM_COWER,
|
||||
WAITSTATE_PLAYANIM_TAXI,
|
||||
WAITSTATE_PLAYANIM_HANDSUP,
|
||||
WAITSTATE_PLAYANIM_HANDSCOWER,
|
||||
WAITSTATE_PLAYANIM_CHAT,
|
||||
WAITSTATE_FINISH_FLEE
|
||||
};
|
||||
|
||||
enum eObjective : uint32 {
|
||||
OBJECTIVE_NONE,
|
||||
OBJECTIVE_IDLE,
|
||||
OBJECTIVE_FLEE_TILL_SAFE,
|
||||
@ -52,7 +76,7 @@ enum eObjective {
|
||||
OBJECTIVE_35
|
||||
};
|
||||
|
||||
enum {
|
||||
enum eVehEnter : uint16 {
|
||||
VEHICLE_ENTER_FRONT_RIGHT = 11,
|
||||
VEHICLE_ENTER_REAR_RIGHT = 12,
|
||||
VEHICLE_ENTER_FRONT_LEFT = 15,
|
||||
@ -60,8 +84,8 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
CREATED_BY_RANDOM = 1,
|
||||
CREATED_BY_SCRIPT
|
||||
RANDOM_CHAR = 1,
|
||||
MISSION_CHAR,
|
||||
};
|
||||
|
||||
enum PedLineUpPhase {
|
||||
@ -130,15 +154,15 @@ enum PedState
|
||||
PED_PASSENGER,
|
||||
PED_TAXI_PASSENGER,
|
||||
PED_OPEN_DOOR,
|
||||
PED_DIE = 48,
|
||||
PED_DEAD = 49,
|
||||
PED_DIE,
|
||||
PED_DEAD,
|
||||
PED_CARJACK,
|
||||
PED_DRAG_FROM_CAR,
|
||||
PED_ENTER_CAR,
|
||||
PED_STEAL_CAR,
|
||||
PED_EXIT_CAR,
|
||||
PED_HANDS_UP,
|
||||
PED_ARRESTED = 56,
|
||||
PED_ARRESTED,
|
||||
};
|
||||
|
||||
enum eMoveState {
|
||||
@ -157,6 +181,8 @@ public:
|
||||
// 0x128
|
||||
CStoredCollPoly m_collPoly;
|
||||
float m_fCollisionSpeed;
|
||||
|
||||
// cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPed.h from R*
|
||||
uint8 bIsStanding : 1;
|
||||
uint8 m_ped_flagA2 : 1;
|
||||
uint8 m_ped_flagA4 : 1; // stores (CTimer::GetTimeInMilliseconds() < m_lastHitTime)
|
||||
@ -168,16 +194,16 @@ public:
|
||||
|
||||
uint8 bIsRestoringGun : 1;
|
||||
uint8 bCanPointGunAtTarget : 1;
|
||||
uint8 m_ped_flagB4 : 1;
|
||||
uint8 m_ped_flagB8 : 1;
|
||||
uint8 m_ped_flagB10 : 1;
|
||||
uint8 bIsTalking : 1;
|
||||
uint8 bIsInTheAir : 1;
|
||||
uint8 bIsLanding : 1;
|
||||
uint8 m_ped_flagB20 : 1;
|
||||
uint8 m_ped_flagB40 : 1;
|
||||
uint8 m_ped_flagB80 : 1;
|
||||
|
||||
uint8 m_ped_flagC1 : 1;
|
||||
uint8 m_ped_flagC2 : 1;
|
||||
uint8 m_ped_flagC4 : 1;
|
||||
uint8 bRespondsToThreats : 1;
|
||||
uint8 m_ped_flagC4 : 1; // false when in bus, bRenderPedInCar?
|
||||
uint8 m_ped_flagC8 : 1;
|
||||
uint8 m_ped_flagC10 : 1;
|
||||
uint8 m_ped_flagC20 : 1; // just left some body part?
|
||||
@ -195,9 +221,9 @@ public:
|
||||
|
||||
uint8 m_ped_flagE1 : 1;
|
||||
uint8 m_ped_flagE2 : 1;
|
||||
uint8 m_ped_flagE4 : 1;
|
||||
uint8 m_ped_flagE8 : 1; // can duck?
|
||||
uint8 bCantFireBecauseCrouched : 1; // set if you don't want ped to attack
|
||||
uint8 bNotAllowedToDuck : 1;
|
||||
uint8 bCrouchWhenShooting : 1;
|
||||
uint8 bIsDucking : 1; // set if you don't want ped to attack
|
||||
uint8 m_ped_flagE20 : 1;
|
||||
uint8 bDoBloodyFootprints : 1;
|
||||
uint8 m_ped_flagE80 : 1;
|
||||
@ -237,8 +263,9 @@ public:
|
||||
uint8 m_ped_flagI20 : 1;
|
||||
uint8 m_ped_flagI40 : 1;
|
||||
uint8 m_ped_flagI80 : 1;
|
||||
|
||||
uint8 stuff10[3];
|
||||
uint8 m_nCreatedBy;
|
||||
uint8 CharCreatedBy;
|
||||
uint8 field_161;
|
||||
uint8 pad_162[2];
|
||||
eObjective m_objective;
|
||||
@ -270,7 +297,7 @@ public:
|
||||
eMoveState m_nMoveState;
|
||||
int32 m_nStoredActionState;
|
||||
int32 m_nPrevActionState;
|
||||
int32 m_nWaitState;
|
||||
eWaitState m_nWaitState;
|
||||
uint32 m_nWaitTimer;
|
||||
void *m_pPathNodesStates[8];
|
||||
CVector2D m_stPathNodeStates[10];
|
||||
@ -286,15 +313,15 @@ public:
|
||||
float m_fArmour;
|
||||
int16 m_routeLastPoint;
|
||||
uint16 m_routePoints;
|
||||
uint16 m_routePos;
|
||||
uint16 m_routeType;
|
||||
uint16 m_routeCurDir;
|
||||
int16 m_routePos;
|
||||
int16 m_routeType;
|
||||
int16 m_routeCurDir;
|
||||
uint16 field_2D2;
|
||||
CVector2D m_moved;
|
||||
float m_fRotationCur;
|
||||
float m_fRotationDest;
|
||||
float m_headingRate;
|
||||
uint16 m_vehEnterType;
|
||||
eVehEnter m_vehEnterType;
|
||||
uint16 m_walkAroundType;
|
||||
CEntity *m_pCurrentPhysSurface;
|
||||
CVector m_vecOffsetFromPhysSurface;
|
||||
@ -426,8 +453,20 @@ public:
|
||||
bool CanPedJumpThis(int32);
|
||||
bool CanSeeEntity(CEntity*, float);
|
||||
void RestorePreviousObjective(void);
|
||||
void SetIdle(void);
|
||||
void SetObjective(eObjective, void*);
|
||||
void MakeChangesForNewWeapon(int8);
|
||||
void SetObjective(eObjective);
|
||||
void SetObjective(eObjective, int16, int16);
|
||||
void ClearChat(void);
|
||||
void InformMyGangOfAttack(CEntity*);
|
||||
void SetFollowRoute(int16, int16);
|
||||
void ReactToAttack(CEntity*);
|
||||
void SetDuck(uint32);
|
||||
void RegisterThreatWithGangPeds(CEntity*);
|
||||
bool TurnBody(void);
|
||||
void Chat(void);
|
||||
void MakeChangesForNewWeapon(int8);
|
||||
|
||||
|
||||
// Static methods
|
||||
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset);
|
||||
@ -483,11 +522,28 @@ public:
|
||||
void SetStoredObjective(void);
|
||||
void SetLeader(CEntity* leader);
|
||||
void SetPedStats(ePedStats);
|
||||
bool IsGangMember(void);
|
||||
|
||||
inline bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
|
||||
inline CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
|
||||
inline CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
|
||||
inline RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; }
|
||||
inline static uint8 GetVehEnterExitFlag(eVehEnter vehEnter) {
|
||||
switch (vehEnter) {
|
||||
case VEHICLE_ENTER_FRONT_RIGHT:
|
||||
return 4;
|
||||
case VEHICLE_ENTER_REAR_RIGHT:
|
||||
return 8;
|
||||
case VEHICLE_ENTER_FRONT_LEFT:
|
||||
return 1;
|
||||
case VEHICLE_ENTER_REAR_LEFT:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PedState GetPedState(void) { return m_nPedState; }
|
||||
void SetPedState(PedState state) { m_nPedState = state; }
|
||||
|
||||
// to make patching virtual functions possible
|
||||
void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); }
|
||||
|
@ -1858,10 +1858,10 @@ CPhysical::ProcessCollision(void)
|
||||
CVehicle *veh = (CVehicle*)this;
|
||||
if(veh->m_vehType == VEHICLE_TYPE_CAR){
|
||||
CAutomobile *car = (CAutomobile*)this;
|
||||
car->m_afWheelSuspDist[0] = 1.0f;
|
||||
car->m_afWheelSuspDist[1] = 1.0f;
|
||||
car->m_afWheelSuspDist[2] = 1.0f;
|
||||
car->m_afWheelSuspDist[3] = 1.0f;
|
||||
car->m_aWheelDist[0] = 1.0f;
|
||||
car->m_aWheelDist[1] = 1.0f;
|
||||
car->m_aWheelDist[2] = 1.0f;
|
||||
car->m_aWheelDist[3] = 1.0f;
|
||||
}else if(veh->m_vehType == VEHICLE_TYPE_BIKE){
|
||||
assert(0 && "TODO - but unused");
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ public:
|
||||
// Force actually means Impulse here
|
||||
void ApplyMoveForce(float jx, float jy, float jz);
|
||||
void ApplyMoveForce(const CVector &j) { ApplyMoveForce(j.x, j.y, j.z); }
|
||||
// v(x,y,z) is direction of force, p(x,y,z) is point relative to model center where force is applied
|
||||
void ApplyTurnForce(float jx, float jy, float jz, float rx, float ry, float rz);
|
||||
// v is direction of force, p is point relative to model center where force is applied
|
||||
// j(x,y,z) is direction of force, p(x,y,z) is point relative to model center where force is applied
|
||||
void ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz);
|
||||
// j is direction of force, p is point relative to model center where force is applied
|
||||
void ApplyTurnForce(const CVector &j, const CVector &p) { ApplyTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }
|
||||
void ApplyFrictionMoveForce(float jx, float jy, float jz);
|
||||
void ApplyFrictionMoveForce(const CVector &j) { ApplyFrictionMoveForce(j.x, j.y, j.z); }
|
||||
|
@ -1,9 +1,17 @@
|
||||
#include "common.h"
|
||||
#include "main.h"
|
||||
#include "patcher.h"
|
||||
#include "Timer.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Pools.h"
|
||||
#include "HandlingMgr.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "Population.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "World.h"
|
||||
#include "Lights.h"
|
||||
#include "PointLights.h"
|
||||
#include "Renderer.h"
|
||||
#include "DMAudio.h"
|
||||
#include "Radar.h"
|
||||
|
||||
@ -40,30 +48,238 @@ CVehicle::~CVehicle()
|
||||
CCarCtrl::NumAmbulancesOnDuty--;
|
||||
bIsAmbulanceOnDuty = false;
|
||||
}
|
||||
if (bIsFiretruckOnDuty){
|
||||
if (bIsFireTruckOnDuty){
|
||||
CCarCtrl::NumFiretrucksOnDuty--;
|
||||
bIsFiretruckOnDuty = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::IsLawEnforcementVehicle(void)
|
||||
{
|
||||
switch (m_modelIndex) {
|
||||
case MI_FBICAR:
|
||||
case MI_POLICE:
|
||||
case MI_ENFORCER:
|
||||
case MI_PREDATOR:
|
||||
case MI_RHINO:
|
||||
case MI_BARRACKS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
bIsFireTruckOnDuty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::ChangeLawEnforcerState(bool enable)
|
||||
CVehicle::SetModelIndex(uint32 id)
|
||||
{
|
||||
CEntity::SetModelIndex(id);
|
||||
m_aExtras[0] = CVehicleModelInfo::ms_compsUsed[0];
|
||||
m_aExtras[1] = CVehicleModelInfo::ms_compsUsed[1];
|
||||
m_nNumMaxPassengers = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(id);
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::SetupLighting(void)
|
||||
{
|
||||
ActivateDirectional();
|
||||
SetAmbientColoursForPedsCarsAndObjects();
|
||||
|
||||
if(bRenderScorched){
|
||||
WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
|
||||
}else{
|
||||
CVector coors = GetPosition();
|
||||
float lighting = CPointLights::GenerateLightsAffectingObject(&coors);
|
||||
if(!bHasBlip && lighting != 1.0f){
|
||||
SetAmbientAndDirectionalColours(lighting);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::RemoveLighting(bool reset)
|
||||
{
|
||||
CRenderer::RemoveVehiclePedLights(this, reset);
|
||||
}
|
||||
|
||||
float
|
||||
CVehicle::GetHeightAboveRoad(void)
|
||||
{
|
||||
return -1.0f * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.min.z;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CVehicle::IsLawEnforcementVehicle(void)
|
||||
{
|
||||
switch(GetModelIndex()){
|
||||
case MI_FBICAR:
|
||||
case MI_POLICE:
|
||||
case MI_ENFORCER:
|
||||
case MI_PREDATOR:
|
||||
case MI_RHINO:
|
||||
case MI_BARRACKS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::UsesSiren(uint32 id)
|
||||
{
|
||||
switch(id){
|
||||
case MI_FIRETRUCK:
|
||||
case MI_AMBULAN:
|
||||
case MI_FBICAR:
|
||||
case MI_MRWHOOP:
|
||||
case MI_POLICE:
|
||||
case MI_ENFORCER:
|
||||
case MI_PREDATOR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::IsVehicleNormal(void)
|
||||
{
|
||||
if(pDriver && m_nNumPassengers == 0 && m_status != STATUS_WRECKED){
|
||||
switch(GetModelIndex())
|
||||
case MI_FIRETRUCK:
|
||||
case MI_AMBULAN:
|
||||
case MI_TAXI:
|
||||
case MI_POLICE:
|
||||
case MI_ENFORCER:
|
||||
case MI_BUS:
|
||||
case MI_RHINO:
|
||||
case MI_BARRACKS:
|
||||
case MI_DODO:
|
||||
case MI_COACH:
|
||||
case MI_CABBIE:
|
||||
case MI_RCBANDIT:
|
||||
case MI_BORGNINE:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::CarHasRoof(void)
|
||||
{
|
||||
if((m_handling->Flags & HANDLING_HAS_NO_ROOF) == 0)
|
||||
return true;
|
||||
if(m_aExtras[0] && m_aExtras[1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::IsUpsideDown(void)
|
||||
{
|
||||
if(GetUp().z > -0.9f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::IsOnItsSide(void)
|
||||
{
|
||||
if(GetRight().z < 0.8f && GetRight().z > -0.8f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::CanBeDeleted(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(m_nNumGettingIn || m_nGettingOutFlags)
|
||||
return false;
|
||||
|
||||
if(pDriver){
|
||||
// This looks like it was inlined
|
||||
if(pDriver->CharCreatedBy == MISSION_CHAR)
|
||||
return false;
|
||||
if(pDriver->GetPedState() != PED_DRIVING &&
|
||||
pDriver->GetPedState() != PED_DEAD)
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; i++){
|
||||
// Same check as above
|
||||
if(pPassengers[i]){
|
||||
if(pPassengers[i]->CharCreatedBy == MISSION_CHAR)
|
||||
return false;
|
||||
if(pPassengers[i]->GetPedState() != PED_DRIVING &&
|
||||
pPassengers[i]->GetPedState() != PED_DEAD)
|
||||
return false;
|
||||
}
|
||||
// and then again... probably because something was inlined
|
||||
if(pPassengers[i]){
|
||||
if(pPassengers[i]->GetPedState() != PED_DRIVING &&
|
||||
pPassengers[i]->GetPedState() != PED_DEAD)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch(VehicleCreatedBy){
|
||||
case RANDOM_VEHICLE: return true;
|
||||
case MISSION_VEHICLE: return false;
|
||||
case PARKED_VEHICLE: return true;
|
||||
case PERMANENT_VEHICLE: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::CanPedOpenLocks(CPed *ped)
|
||||
{
|
||||
if(m_nDoorLock == CARLOCK_LOCKED ||
|
||||
m_nDoorLock == CARLOCK_COP_CAR ||
|
||||
m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE)
|
||||
return false;
|
||||
if(ped->IsPlayer() && m_nDoorLock == CARLOCK_LOCKOUT_PLAYER_ONLY)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::CanPedEnterCar(void)
|
||||
{
|
||||
CVector up = GetUp();
|
||||
// can't enter when car is on side
|
||||
if(up.z > 0.1f || up.z < -0.1f){
|
||||
// also when car is moving too fast
|
||||
if(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f))
|
||||
return false;
|
||||
if(m_vecTurnSpeed.MagnitudeSqr() > sq(0.2f))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::CanPedExitCar(void)
|
||||
{
|
||||
CVector up = GetUp();
|
||||
if(up.z > 0.1f || up.z < -0.1f){
|
||||
// can't exit when car is moving too fast
|
||||
if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f)
|
||||
return false;
|
||||
// if car is slow enough, check turn speed
|
||||
if(fabs(m_vecTurnSpeed.x) > 0.01f ||
|
||||
fabs(m_vecTurnSpeed.y) > 0.01f ||
|
||||
fabs(m_vecTurnSpeed.z) > 0.01f)
|
||||
return false;
|
||||
return true;
|
||||
}else{
|
||||
// What is this? just > replaced by >= ??
|
||||
|
||||
// can't exit when car is moving too fast
|
||||
if(m_vecMoveSpeed.MagnitudeSqr() >= 0.005f)
|
||||
return false;
|
||||
// if car is slow enough, check turn speed
|
||||
if(fabs(m_vecTurnSpeed.x) >= 0.01f ||
|
||||
fabs(m_vecTurnSpeed.y) >= 0.01f ||
|
||||
fabs(m_vecTurnSpeed.z) >= 0.01f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::ChangeLawEnforcerState(uint8 enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (!bIsLawEnforcer) {
|
||||
@ -78,6 +294,111 @@ CVehicle::ChangeLawEnforcerState(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
CPed*
|
||||
CVehicle::SetUpDriver(void)
|
||||
{
|
||||
if(pDriver)
|
||||
return pDriver;
|
||||
if(VehicleCreatedBy != RANDOM_VEHICLE)
|
||||
return nil;
|
||||
|
||||
pDriver = CPopulation::AddPedInCar(this);
|
||||
pDriver->m_pMyVehicle = this;
|
||||
pDriver->m_pMyVehicle->RegisterReference((CEntity**)&pDriver->m_pMyVehicle);
|
||||
pDriver->bInVehicle = true;
|
||||
pDriver->SetPedState(PED_DRIVING);
|
||||
if(bIsBus)
|
||||
pDriver->m_ped_flagC4 = false;
|
||||
return pDriver;
|
||||
}
|
||||
|
||||
CPed*
|
||||
CVehicle::SetupPassenger(int n)
|
||||
{
|
||||
if(pPassengers[n])
|
||||
return pPassengers[n];
|
||||
|
||||
pPassengers[n] = CPopulation::AddPedInCar(this);
|
||||
pPassengers[n]->m_pMyVehicle = this;
|
||||
pPassengers[n]->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle);
|
||||
pPassengers[n]->bInVehicle = true;
|
||||
pPassengers[n]->SetPedState(PED_DRIVING);
|
||||
if(bIsBus)
|
||||
pPassengers[n]->m_ped_flagC4 = false;
|
||||
return pPassengers[n];
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::SetDriver(CPed *driver)
|
||||
{
|
||||
pDriver = driver;
|
||||
pDriver->RegisterReference((CEntity**)&pDriver);
|
||||
|
||||
if(bFreebies && driver == FindPlayerPed()){
|
||||
if(GetModelIndex() == MI_AMBULAN)
|
||||
FindPlayerPed()->m_fHealth = min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f);
|
||||
else if(GetModelIndex() == MI_TAXI)
|
||||
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
|
||||
else if(GetModelIndex() == MI_POLICE)
|
||||
driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
|
||||
else if(GetModelIndex() == MI_ENFORCER)
|
||||
driver->m_fArmour = max(driver->m_fArmour, 100.0f);
|
||||
else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE)
|
||||
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
|
||||
bFreebies = false;
|
||||
}
|
||||
|
||||
ApplyTurnForce(0.0f, 0.0f, -0.2f*driver->m_fMass,
|
||||
driver->GetPosition().x - GetPosition().x,
|
||||
driver->GetPosition().y - GetPosition().y,
|
||||
0.0f);
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::AddPassenger(CPed *passenger)
|
||||
{
|
||||
int i;
|
||||
|
||||
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
|
||||
passenger->GetPosition().x - GetPosition().x,
|
||||
passenger->GetPosition().y - GetPosition().y,
|
||||
0.0f);
|
||||
|
||||
for(i = 0; i < m_nNumMaxPassengers; i++)
|
||||
if(pPassengers[i] == nil){
|
||||
pPassengers[i] = passenger;
|
||||
m_nNumPassengers++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::AddPassenger(CPed *passenger, uint8 n)
|
||||
{
|
||||
if(bIsBus)
|
||||
return AddPassenger(passenger);
|
||||
|
||||
ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
|
||||
passenger->GetPosition().x - GetPosition().x,
|
||||
passenger->GetPosition().y - GetPosition().y,
|
||||
0.0f);
|
||||
|
||||
if(n < m_nNumMaxPassengers && pPassengers[n] == nil){
|
||||
pPassengers[n] = passenger;
|
||||
m_nNumPassengers++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::RemoveDriver(void)
|
||||
{
|
||||
m_status = STATUS_ABANDONED;
|
||||
pDriver = nil;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::RemovePassenger(CPed *p)
|
||||
{
|
||||
@ -101,19 +422,68 @@ CVehicle::RemovePassenger(CPed *p)
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::RemoveDriver(void)
|
||||
CVehicle::ProcessCarAlarm(void)
|
||||
{
|
||||
m_status = STATUS_ABANDONED;
|
||||
pDriver = nil;
|
||||
uint32 step;
|
||||
|
||||
if(m_nAlarmState == 0 || m_nAlarmState == -1)
|
||||
return;
|
||||
|
||||
step = CTimer::GetTimeStep()/50.0f * 1000.0f;
|
||||
if((uint16)m_nAlarmState < step)
|
||||
m_nAlarmState = 0;
|
||||
else
|
||||
m_nAlarmState -= step;
|
||||
}
|
||||
|
||||
bool
|
||||
CVehicle::IsUpsideDown(void)
|
||||
CVehicle::IsSphereTouchingVehicle(float sx, float sy, float sz, float radius)
|
||||
{
|
||||
return GetUp().z <= -0.9f;
|
||||
float x, y, z;
|
||||
// sphere relative to vehicle
|
||||
CVector sph = CVector(sx, sy, sz) - GetPosition();
|
||||
CColModel *colmodel = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();
|
||||
|
||||
x = DotProduct(sph, GetRight());
|
||||
if(colmodel->boundingBox.min.x - radius > x ||
|
||||
colmodel->boundingBox.max.x + radius < x)
|
||||
return false;
|
||||
y = DotProduct(sph, GetForward());
|
||||
if(colmodel->boundingBox.min.y - radius > y ||
|
||||
colmodel->boundingBox.max.y + radius < y)
|
||||
return false;
|
||||
z = DotProduct(sph, GetUp());
|
||||
if(colmodel->boundingBox.min.z - radius > z ||
|
||||
colmodel->boundingBox.max.z + radius < z)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x551170, &CVehicle::SetModelIndex_, PATCH_JUMP);
|
||||
InjectHook(0x4A7DD0, &CVehicle::SetupLighting_, PATCH_JUMP);
|
||||
InjectHook(0x4A7E60, &CVehicle::RemoveLighting_, PATCH_JUMP);
|
||||
InjectHook(0x417E60, &CVehicle::GetHeightAboveRoad_, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x552880, &CVehicle::IsLawEnforcementVehicle, PATCH_JUMP);
|
||||
InjectHook(0x552820, &CVehicle::ChangeLawEnforcerState, PATCH_JUMP);
|
||||
InjectHook(0x552200, &CVehicle::UsesSiren, PATCH_JUMP);
|
||||
InjectHook(0x5527E0, &CVehicle::IsVehicleNormal, PATCH_JUMP);
|
||||
InjectHook(0x552B70, &CVehicle::CarHasRoof, PATCH_JUMP);
|
||||
InjectHook(0x552230, &CVehicle::IsUpsideDown, PATCH_JUMP);
|
||||
InjectHook(0x552260, &CVehicle::IsOnItsSide, PATCH_JUMP);
|
||||
InjectHook(0x5511B0, &CVehicle::CanBeDeleted, PATCH_JUMP);
|
||||
InjectHook(0x5522A0, &CVehicle::CanPedOpenLocks, PATCH_JUMP);
|
||||
InjectHook(0x5522F0, &CVehicle::CanPedEnterCar, PATCH_JUMP);
|
||||
InjectHook(0x5523C0, &CVehicle::CanPedExitCar, PATCH_JUMP);
|
||||
InjectHook(0x5520C0, &CVehicle::SetUpDriver, PATCH_JUMP);
|
||||
InjectHook(0x552160, &CVehicle::SetupPassenger, PATCH_JUMP);
|
||||
InjectHook(0x551F20, &CVehicle::SetDriver, PATCH_JUMP);
|
||||
InjectHook(0x551D90, (bool (CVehicle::*)(CPed*))&CVehicle::AddPassenger, PATCH_JUMP);
|
||||
InjectHook(0x551E10, (bool (CVehicle::*)(CPed*,uint8))&CVehicle::AddPassenger, PATCH_JUMP);
|
||||
InjectHook(0x5520A0, &CVehicle::RemoveDriver, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
InjectHook(0x551EB0, &CVehicle::RemovePassenger, PATCH_JUMP);
|
||||
InjectHook(0x5525A0, &CVehicle::ProcessCarAlarm, PATCH_JUMP);
|
||||
InjectHook(0x552620, &CVehicle::IsSphereTouchingVehicle, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "Physical.h"
|
||||
#include "AutoPilot.h"
|
||||
|
||||
class CPed;
|
||||
class CFire;
|
||||
struct tHandlingData;
|
||||
|
||||
enum {
|
||||
GETTING_IN_OUT_FL = 1,
|
||||
GETTING_IN_OUT_RL = 2,
|
||||
GETTING_IN_OUT_FR = 4,
|
||||
GETTING_IN_OUT_RR = 8
|
||||
RANDOM_VEHICLE = 1,
|
||||
MISSION_VEHICLE = 2,
|
||||
PARKED_VEHICLE = 3,
|
||||
PERMANENT_VEHICLE = 4,
|
||||
};
|
||||
|
||||
enum eCarLock : uint8 {
|
||||
enum eCarLock {
|
||||
CARLOCK_NOT_USED,
|
||||
CARLOCK_UNLOCKED,
|
||||
CARLOCK_LOCKED,
|
||||
@ -24,15 +25,66 @@ enum eCarLock : uint8 {
|
||||
CARLOCK_SKIP_SHUT_DOORS
|
||||
};
|
||||
|
||||
|
||||
enum eCarNodes
|
||||
{
|
||||
CAR_WHEEL_RF = 1,
|
||||
CAR_WHEEL_RM,
|
||||
CAR_WHEEL_RB,
|
||||
CAR_WHEEL_LF,
|
||||
CAR_WHEEL_LM,
|
||||
CAR_WHEEL_LB,
|
||||
CAR_BUMP_FRONT,
|
||||
CAR_BUMP_REAR,
|
||||
CAR_WING_RF,
|
||||
CAR_WING_RR,
|
||||
CAR_DOOR_RF,
|
||||
CAR_DOOR_RR,
|
||||
CAR_WING_LF,
|
||||
CAR_WING_LR,
|
||||
CAR_DOOR_LF,
|
||||
CAR_DOOR_LR,
|
||||
CAR_BONNET,
|
||||
CAR_BOOT,
|
||||
CAR_WINDSCREEN,
|
||||
NUM_CAR_NODES,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CAR_POS_HEADLIGHTS,
|
||||
CAR_POS_TAILLIGHTS,
|
||||
CAR_POS_FRONTSEAT,
|
||||
CAR_POS_BACKSEAT,
|
||||
CAR_POS_EXHAUST = 9,
|
||||
};
|
||||
|
||||
enum eDoors
|
||||
{
|
||||
DOOR_BONNET = 0,
|
||||
DOOR_BOOT,
|
||||
DOOR_FRONT_LEFT,
|
||||
DOOR_FRONT_RIGHT,
|
||||
DOOR_REAR_LEFT,
|
||||
DOOR_REAR_RIGHT
|
||||
};
|
||||
|
||||
enum {
|
||||
GETTING_IN_OUT_FL = 1,
|
||||
GETTING_IN_OUT_RL = 2,
|
||||
GETTING_IN_OUT_FR = 4,
|
||||
GETTING_IN_OUT_RR = 8
|
||||
};
|
||||
|
||||
class CVehicle : public CPhysical
|
||||
{
|
||||
public:
|
||||
// 0x128
|
||||
tHandlingData *m_handling;
|
||||
uint8 stuff1[112];
|
||||
CAutoPilot m_autoPilot;
|
||||
uint8 m_currentColour1;
|
||||
uint8 m_currentColour2;
|
||||
uint8 m_anExtras[2];
|
||||
uint8 m_aExtras[2];
|
||||
int16 m_nAlarmState; // m_nWantedStarsOnEnter on DK22
|
||||
int16 m_nMissionValue;
|
||||
CPed *pDriver;
|
||||
@ -48,23 +100,27 @@ public:
|
||||
float m_fSteerAngle;
|
||||
float m_fGasPedal;
|
||||
float m_fBreakPedal;
|
||||
uint8 m_nCreatedBy; // eVehicleCreatedBy
|
||||
uint8 bIsLawEnforcer : 1;
|
||||
uint8 bIsAmbulanceOnDuty : 1;
|
||||
uint8 bIsFiretruckOnDuty : 1;
|
||||
uint8 m_veh_flagA8 : 1;
|
||||
uint8 m_veh_flagA10 : 1;
|
||||
uint8 m_veh_flagA20 : 1;
|
||||
uint8 m_veh_flagA40 : 1;
|
||||
uint8 m_veh_flagA80 : 1;
|
||||
uint8 bIsVan : 1;
|
||||
uint8 bIsBus : 1;
|
||||
uint8 bIsBig : 1;
|
||||
uint8 bIsLow : 1;
|
||||
uint8 VehicleCreatedBy;
|
||||
|
||||
// cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CVehicle.h from R*
|
||||
uint8 bIsLawEnforcer: 1; // Is this guy chasing the player at the moment
|
||||
uint8 bIsAmbulanceOnDuty: 1; // Ambulance trying to get to an accident
|
||||
uint8 bIsFireTruckOnDuty: 1; // Firetruck trying to get to a fire
|
||||
uint8 bIsLocked: 1; // Is this guy locked by the script (cannot be removed)
|
||||
uint8 bEngineOn: 1; // For sound purposes. Parked cars have their engines switched off (so do destroyed cars)
|
||||
uint8 bIsHandbrakeOn: 1; // How's the handbrake doing ?
|
||||
uint8 bLightsOn: 1; // Are the lights switched on ?
|
||||
uint8 bFreebies: 1; // Any freebies left in this vehicle ?
|
||||
|
||||
uint8 bIsVan: 1; // Is this vehicle a van (doors at back of vehicle)
|
||||
uint8 bIsBus: 1; // Is this vehicle a bus
|
||||
uint8 bIsBig: 1; // Is this vehicle a bus
|
||||
uint8 bLowVehicle: 1; // Need this for sporty type cars to use low getting-in/out anims
|
||||
uint8 m_veh_flagB10 : 1;
|
||||
uint8 m_veh_flagB20 : 1;
|
||||
uint8 m_veh_flagB40 : 1;
|
||||
uint8 m_veh_flagB80 : 1;
|
||||
|
||||
uint8 m_veh_flagC1 : 1;
|
||||
uint8 m_veh_flagC2 : 1;
|
||||
uint8 m_veh_flagC4 : 1;
|
||||
@ -73,6 +129,7 @@ public:
|
||||
uint8 m_veh_flagC20 : 1;
|
||||
uint8 m_veh_flagC40 : 1;
|
||||
uint8 m_veh_flagC80 : 1;
|
||||
|
||||
uint8 m_veh_flagD1 : 1;
|
||||
uint8 m_veh_flagD2 : 1;
|
||||
uint8 m_veh_flagD4 : 1;
|
||||
@ -81,8 +138,9 @@ public:
|
||||
uint8 m_veh_flagD20 : 1;
|
||||
uint8 m_veh_flagD40 : 1;
|
||||
uint8 m_veh_flagD80 : 1;
|
||||
|
||||
int8 field_1F9;
|
||||
uint8 m_nAmmoInClip[1]; // Used to make the guns on boat do a reload (20 by default)
|
||||
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
|
||||
int8 field_1FB;
|
||||
int8 field_1FC[4];
|
||||
float m_fHealth; // 1000.0f = full health. 0 -> explode
|
||||
@ -105,6 +163,7 @@ public:
|
||||
int8 field_22D;
|
||||
uint8 m_nSirenOrAlarm;
|
||||
int8 field_22F;
|
||||
// TODO: this is an array
|
||||
CStoredCollPoly m_frontCollPoly; // poly which is under front part of car
|
||||
CStoredCollPoly m_rearCollPoly; // poly which is under rear part of car
|
||||
float m_fSteerRatio;
|
||||
@ -116,8 +175,29 @@ public:
|
||||
static void operator delete(void*, int);
|
||||
|
||||
~CVehicle(void);
|
||||
// from CEntity
|
||||
void SetModelIndex(uint32 i);
|
||||
bool SetupLighting(void);
|
||||
void RemoveLighting(bool);
|
||||
void FlagToDestroyWhenNextProcessed(void) {}
|
||||
|
||||
void dtor(void) { this->CVehicle::~CVehicle(); }
|
||||
virtual void ProcessControlInputs(uint8) {}
|
||||
virtual void GetComponentWorldPosition(int32 component, CVector &pos) {}
|
||||
virtual bool IsComponentPresent(int32 component) { return false; }
|
||||
virtual void SetComponentRotation(int32 component, CVector rotation) {}
|
||||
virtual void OpenDoor(int32, eDoors door, float) {}
|
||||
virtual void ProcessOpenDoor(uint32, uint32, float) {}
|
||||
virtual bool IsDoorReady(eDoors door) { return false; }
|
||||
virtual bool IsDoorFullyOpen(eDoors door) { return false; }
|
||||
virtual bool IsDoorClosed(eDoors door) { return false; }
|
||||
virtual bool IsDoorMissing(eDoors door) { return false; }
|
||||
virtual void RemoveRefsToVehicle(CEntity *ent) {}
|
||||
virtual void BlowUpCar(CEntity *ent) {}
|
||||
virtual bool SetUpWheelColModel(CColModel *colModel) { return false; }
|
||||
virtual void BurstTyre(uint8 tyre) {}
|
||||
virtual bool IsRoomForPedToLeaveCar(uint32, CVector *) { return false;}
|
||||
virtual float GetHeightAboveRoad(void);
|
||||
virtual void PlayCarHorn(void) {}
|
||||
|
||||
bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; }
|
||||
bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; }
|
||||
@ -125,10 +205,26 @@ public:
|
||||
bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }
|
||||
bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }
|
||||
bool IsLawEnforcementVehicle(void);
|
||||
void ChangeLawEnforcerState(bool enable);
|
||||
void RemovePassenger(CPed *);
|
||||
void RemoveDriver(void);
|
||||
void ChangeLawEnforcerState(uint8 enable);
|
||||
bool UsesSiren(uint32 id);
|
||||
bool IsVehicleNormal(void);
|
||||
bool CarHasRoof(void);
|
||||
bool IsUpsideDown(void);
|
||||
bool IsOnItsSide(void);
|
||||
bool CanBeDeleted(void);
|
||||
bool CanPedOpenLocks(CPed *ped);
|
||||
bool CanPedEnterCar(void);
|
||||
bool CanPedExitCar(void);
|
||||
// do these two actually return something?
|
||||
CPed *SetUpDriver(void);
|
||||
CPed *SetupPassenger(int n);
|
||||
void SetDriver(CPed *driver);
|
||||
bool AddPassenger(CPed *passenger);
|
||||
bool AddPassenger(CPed *passenger, uint8 n);
|
||||
void RemovePassenger(CPed *passenger);
|
||||
void RemoveDriver(void);
|
||||
void ProcessCarAlarm(void);
|
||||
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
|
||||
|
||||
static bool &bWheelsOnlyCheat;
|
||||
static bool &bAllDodosCheat;
|
||||
@ -136,8 +232,16 @@ public:
|
||||
static bool &bCheat4;
|
||||
static bool &bCheat5;
|
||||
static bool &m_bDisableMouseSteering;
|
||||
|
||||
|
||||
void dtor(void) { CVehicle::~CVehicle(); }
|
||||
void SetModelIndex_(uint32 id) { CVehicle::SetModelIndex(id); }
|
||||
bool SetupLighting_(void) { return CVehicle::SetupLighting(); }
|
||||
void RemoveLighting_(bool reset) { CVehicle::RemoveLighting(reset); }
|
||||
float GetHeightAboveRoad_(void) { return CVehicle::GetHeightAboveRoad(); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error");
|
||||
static_assert(offsetof(CVehicle, m_pCurSurface) == 0x1E0, "CVehicle: error");
|
||||
static_assert(offsetof(CVehicle, m_nAlarmState) == 0x1A0, "CVehicle: error");
|
||||
static_assert(offsetof(CVehicle, m_nLastWeaponDamage) == 0x228, "CVehicle: error");
|
||||
|
@ -250,10 +250,9 @@ enum
|
||||
MI_BUSKER2,
|
||||
MI_BUSKER3,
|
||||
MI_BUSKER4,
|
||||
MI_PED87,
|
||||
MI_PED88,
|
||||
MI_PED89,
|
||||
MI_LANDSTAL,
|
||||
// three more peds possible
|
||||
|
||||
MI_LANDSTAL = 90,
|
||||
MI_IDAHO,
|
||||
MI_STINGER,
|
||||
MI_LINERUN,
|
||||
|
@ -23,34 +23,6 @@ RwTexture **CVehicleModelInfo::ms_colourTextureTable = (RwTexture**)0x711C40;
|
||||
RwTexture *&gpWhiteTexture = *(RwTexture**)0x64C4F8;
|
||||
RwFrame *&pMatFxIdentityFrame = *(RwFrame**)0x64C510;
|
||||
|
||||
enum {
|
||||
CAR_WHEEL_RF = 1,
|
||||
CAR_WHEEL_RM = 2,
|
||||
CAR_WHEEL_RB = 3,
|
||||
CAR_WHEEL_LF = 4,
|
||||
CAR_WHEEL_LM = 5,
|
||||
CAR_WHEEL_LB = 6,
|
||||
CAR_BUMP_FRONT = 7,
|
||||
CAR_BUMP_REAR = 8,
|
||||
CAR_WING_RF = 9,
|
||||
CAR_WING_RR = 10,
|
||||
CAR_DOOR_RF = 11,
|
||||
CAR_DOOR_RR = 12,
|
||||
CAR_WING_LF = 13,
|
||||
CAR_WING_LR = 14,
|
||||
CAR_DOOR_LF = 15,
|
||||
CAR_DOOR_LR = 16,
|
||||
CAR_BONNET = 17,
|
||||
CAR_BOOT = 18,
|
||||
CAR_WINDSCREEN = 19,
|
||||
|
||||
CAR_POS_HEADLIGHTS = 0,
|
||||
CAR_POS_TAILLIGHTS = 1,
|
||||
CAR_POS_FRONTSEAT = 2,
|
||||
CAR_POS_BACKSEAT = 3,
|
||||
CAR_POS_EXHAUST = 9,
|
||||
};
|
||||
|
||||
enum {
|
||||
VEHICLE_FLAG_COLLAPSE = 0x2,
|
||||
VEHICLE_FLAG_ADD_WHEEL = 0x4,
|
||||
|
@ -40,6 +40,16 @@ CClouds::Init(void)
|
||||
CloudRotation = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
CClouds::Shutdown(void)
|
||||
{
|
||||
RwTextureDestroy(gpCloudTex[0]);
|
||||
RwTextureDestroy(gpCloudTex[1]);
|
||||
RwTextureDestroy(gpCloudTex[2]);
|
||||
RwTextureDestroy(gpCloudTex[3]);
|
||||
RwTextureDestroy(gpCloudTex[4]);
|
||||
}
|
||||
|
||||
void
|
||||
CClouds::Update(void)
|
||||
{
|
||||
@ -48,7 +58,6 @@ CClouds::Update(void)
|
||||
IndividualRotation += (CWeather::Wind*CTimer::GetTimeStep() + 0.3f) * 60.0f;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CClouds::Render(void)
|
||||
{
|
||||
@ -424,6 +433,7 @@ CClouds::RenderHorizon(void)
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4F6C10, CClouds::Init, PATCH_JUMP);
|
||||
InjectHook(0x4F6CA0, CClouds::Shutdown, PATCH_JUMP);
|
||||
InjectHook(0x4F6CE0, CClouds::Update, PATCH_JUMP);
|
||||
InjectHook(0x4F6D90, CClouds::Render, PATCH_JUMP);
|
||||
InjectHook(0x4F7F00, CClouds::RenderBackground, PATCH_JUMP);
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
static CRGBA &ms_colourBottom;
|
||||
|
||||
static void Init(void);
|
||||
static void Shutdown(void);
|
||||
static void Update(void);
|
||||
static void Render(void);
|
||||
static void RenderBackground(int16 topred, int16 topgreen, int16 topblue,
|
||||
|
@ -53,6 +53,12 @@ CRenderer::Init(void)
|
||||
SortBIGBuildings();
|
||||
}
|
||||
|
||||
void
|
||||
CRenderer::Shutdown(void)
|
||||
{
|
||||
gSortedVehiclesAndPeds.Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
CRenderer::PreRender(void)
|
||||
{
|
||||
@ -1170,6 +1176,7 @@ CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset)
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4A7680, CRenderer::Init, PATCH_JUMP);
|
||||
InjectHook(0x4A76A0, CRenderer::Shutdown, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x4A7B90, CRenderer::RenderOneRoad, PATCH_JUMP);
|
||||
InjectHook(0x4A7BA0, CRenderer::RenderOneNonRoad, PATCH_JUMP);
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
static bool &m_loadingPriority;
|
||||
|
||||
static void Init(void);
|
||||
static void Shutdown(void);
|
||||
static void PreRender(void);
|
||||
|
||||
static void RenderRoads(void);
|
||||
|
@ -35,6 +35,12 @@ CWeapon::Reload(void)
|
||||
m_nAmmoInClip = m_nAmmoTotal;
|
||||
}
|
||||
|
||||
bool
|
||||
CWeapon::IsTypeMelee(void)
|
||||
{
|
||||
return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP);
|
||||
|
@ -64,5 +64,6 @@ public:
|
||||
void Reload(void);
|
||||
bool Fire(CEntity*, CVector*);
|
||||
void AddGunshell(CEntity*, CVector const&, CVector2D const&, float);
|
||||
bool IsTypeMelee(void);
|
||||
};
|
||||
static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error");
|
||||
|
Loading…
Reference in New Issue
Block a user