CEmergencyPed done
This commit is contained in:
parent
790f4863c6
commit
04499bfbb6
@ -8,7 +8,8 @@ CAccidentManager& gAccidentManager = *(CAccidentManager*)0x87FD10;
|
|||||||
|
|
||||||
WRAPPER void CAccidentManager::Update(void) { EAXJMP(0x456710); }
|
WRAPPER void CAccidentManager::Update(void) { EAXJMP(0x456710); }
|
||||||
|
|
||||||
uint16 CAccidentManager::CountActiveAccidents()
|
uint16
|
||||||
|
CAccidentManager::CountActiveAccidents()
|
||||||
{
|
{
|
||||||
uint16 accidents = 0;
|
uint16 accidents = 0;
|
||||||
for (int i = 0; i < NUM_ACCIDENTS; i++){
|
for (int i = 0; i < NUM_ACCIDENTS; i++){
|
||||||
@ -18,7 +19,8 @@ uint16 CAccidentManager::CountActiveAccidents()
|
|||||||
return accidents;
|
return accidents;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAccident* CAccidentManager::FindNearestAccident(CVector vecPos, float* pDistance)
|
CAccident*
|
||||||
|
CAccidentManager::FindNearestAccident(CVector vecPos, float* pDistance)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_MEDICS_TO_ATTEND_ACCIDENT; i++){
|
for (int i = 0; i < MAX_MEDICS_TO_ATTEND_ACCIDENT; i++){
|
||||||
int accidentId = -1;
|
int accidentId = -1;
|
||||||
@ -45,3 +47,13 @@ CAccident* CAccidentManager::FindNearestAccident(CVector vecPos, float* pDistanc
|
|||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CAccidentManager::UnattendedAccidents(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_ACCIDENTS; i++) {
|
||||||
|
if (m_aAccidents[i].m_pVictim && m_aAccidents[i].m_nMedicsAttending == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -21,6 +21,7 @@ class CAccidentManager
|
|||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
uint16 CountActiveAccidents();
|
uint16 CountActiveAccidents();
|
||||||
|
bool UnattendedAccidents();
|
||||||
CAccident* FindNearestAccident(CVector, float*);
|
CAccident* FindNearestAccident(CVector, float*);
|
||||||
void Update(void);
|
void Update(void);
|
||||||
};
|
};
|
||||||
|
@ -2,15 +2,11 @@
|
|||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "EmergencyPed.h"
|
#include "EmergencyPed.h"
|
||||||
#include "ModelIndices.h"
|
#include "ModelIndices.h"
|
||||||
|
#include "Vehicle.h"
|
||||||
class CEmergencyPed_ : public CEmergencyPed
|
#include "Fire.h"
|
||||||
{
|
#include "General.h"
|
||||||
public:
|
#include "CarCtrl.h"
|
||||||
CEmergencyPed *ctor(int pedtype) { return ::new (this) CEmergencyPed(pedtype); };
|
#include "AccidentManager.h"
|
||||||
void dtor(void) { CEmergencyPed::~CEmergencyPed(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
WRAPPER void CEmergencyPed::ProcessControl(void) { EAXJMP(0x4C2F10); }
|
|
||||||
|
|
||||||
CEmergencyPed::CEmergencyPed(uint32 type) : CPed(type)
|
CEmergencyPed::CEmergencyPed(uint32 type) : CPed(type)
|
||||||
{
|
{
|
||||||
@ -27,12 +23,408 @@ CEmergencyPed::CEmergencyPed(uint32 type) : CPed(type)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_nEmergencyPedState = 0;
|
m_nEmergencyPedState = EMERGENCY_PED_READY;
|
||||||
m_pAttendedAccident = nil;
|
m_pAttendedAccident = nil;
|
||||||
field_1356 = 0;
|
m_bStartedToCPR = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CEmergencyPed::InRange(CPed *victim)
|
||||||
|
{
|
||||||
|
if (!m_pMyVehicle)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((m_pMyVehicle->GetPosition() - victim->GetPosition()).Magnitude() > 30.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CEmergencyPed::ProcessControl(void)
|
||||||
|
{
|
||||||
|
if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CPed::ProcessControl();
|
||||||
|
if (bWasPostponed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!DyingOrDead()) {
|
||||||
|
GetWeapon()->Update(m_audioEntityId);
|
||||||
|
|
||||||
|
if (IsPedInControl() && m_moved.Magnitude() > 0.0f)
|
||||||
|
Avoid();
|
||||||
|
|
||||||
|
switch (m_nPedState) {
|
||||||
|
case PED_SEEK_POS:
|
||||||
|
Seek();
|
||||||
|
break;
|
||||||
|
case PED_SEEK_ENTITY:
|
||||||
|
if (m_pSeekTarget) {
|
||||||
|
m_vecSeekPos = m_pSeekTarget->GetPosition();
|
||||||
|
Seek();
|
||||||
|
} else {
|
||||||
|
ClearSeek();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_nPedType) {
|
||||||
|
case PEDTYPE_EMERGENCY:
|
||||||
|
if (IsPedInControl() || m_nPedState == PED_DRIVING)
|
||||||
|
MedicAI();
|
||||||
|
break;
|
||||||
|
case PEDTYPE_FIREMAN:
|
||||||
|
if (IsPedInControl())
|
||||||
|
FiremanAI();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function was buggy and incomplete in both III and VC, firemen had to be in 5.0m range of fire etc. etc.
|
||||||
|
// Copied some code from MedicAI to make it work.
|
||||||
|
void
|
||||||
|
CEmergencyPed::FiremanAI(void)
|
||||||
|
{
|
||||||
|
float fireDist;
|
||||||
|
CFire *nearestFire;
|
||||||
|
|
||||||
|
switch (m_nEmergencyPedState) {
|
||||||
|
case EMERGENCY_PED_READY:
|
||||||
|
nearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);
|
||||||
|
if (nearestFire) {
|
||||||
|
m_nPedState = PED_NONE;
|
||||||
|
SetSeek(nearestFire->m_vecPos, 1.0f);
|
||||||
|
SetMoveState(PEDMOVE_RUN);
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
m_pAttendedFire = nearestFire;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
bIsRunning = true;
|
||||||
|
++nearestFire->m_nFiremenPuttingOut;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_DETERMINE_NEXT_STATE:
|
||||||
|
nearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);
|
||||||
|
if (nearestFire && nearestFire != m_pAttendedFire) {
|
||||||
|
m_nPedState = PED_NONE;
|
||||||
|
SetSeek(nearestFire->m_vecPos, 1.0f);
|
||||||
|
SetMoveState(PEDMOVE_RUN);
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
bIsRunning = true;
|
||||||
|
if (m_pAttendedFire) {
|
||||||
|
--m_pAttendedFire->m_nFiremenPuttingOut;
|
||||||
|
}
|
||||||
|
++nearestFire->m_nFiremenPuttingOut;
|
||||||
|
m_pAttendedFire = nearestFire;
|
||||||
|
} else if (!nearestFire) {
|
||||||
|
#else
|
||||||
|
m_pAttendedFire = nearestFire;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Extinguish" the fire (Will overwrite the stop decision above if the attended and nearest fires are same)
|
||||||
|
if (fireDist < 5.0f) {
|
||||||
|
SetIdle();
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STAND_STILL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_STAND_STILL:
|
||||||
|
if (!m_pAttendedFire->m_bIsOngoing)
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP;
|
||||||
|
|
||||||
|
// Leftover
|
||||||
|
// fireDist = 30.0f;
|
||||||
|
nearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);
|
||||||
|
if (nearestFire) {
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
if(nearestFire != m_pAttendedFire && (nearestFire->m_vecPos - GetPosition()).Magnitude() < 30.0f)
|
||||||
|
#endif
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
}
|
||||||
|
Say(SOUND_PED_EXTINGUISHING_FIRE);
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_STOP:
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
bIsRunning = false;
|
||||||
|
if (m_pAttendedFire)
|
||||||
|
#endif
|
||||||
|
--m_pAttendedFire->m_nFiremenPuttingOut;
|
||||||
|
|
||||||
|
m_nPedState = PED_NONE;
|
||||||
|
SetWanderPath(CGeneral::GetRandomNumber() & 7);
|
||||||
|
m_pAttendedFire = nil;
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_READY;
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CEmergencyPed::MedicAI(void)
|
||||||
|
{
|
||||||
|
float distToEmergency;
|
||||||
|
if (!bInVehicle && IsPedInControl()) {
|
||||||
|
ScanForThreats();
|
||||||
|
if (m_threatEntity && m_threatEntity->IsPed() && ((CPed*)m_threatEntity)->IsPlayer()) {
|
||||||
|
if (((CPed*)m_threatEntity)->GetWeapon()->IsTypeMelee()) {
|
||||||
|
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
|
||||||
|
} else {
|
||||||
|
SetFlee(m_threatEntity, 6000);
|
||||||
|
Say(SOUND_PED_FLEE_SPRINT);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InVehicle()) {
|
||||||
|
if (m_pMyVehicle->IsCar() && m_objective != OBJECTIVE_LEAVE_VEHICLE) {
|
||||||
|
if (gAccidentManager.FindNearestAccident(m_pMyVehicle->GetPosition(), &distToEmergency)
|
||||||
|
&& distToEmergency < 25.0f && m_pMyVehicle->m_vecMoveSpeed.Magnitude() < 0.01f) {
|
||||||
|
|
||||||
|
m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
|
||||||
|
SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
|
||||||
|
Say(SOUND_PED_LEAVE_VEHICLE);
|
||||||
|
} else if (m_pMyVehicle->pDriver == this && m_nPedState == PED_DRIVING
|
||||||
|
&& m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE && !(CGeneral::GetRandomNumber() & 31)) {
|
||||||
|
|
||||||
|
bool waitUntilMedicEntersCar = false;
|
||||||
|
for (int i = 0; i < m_numNearPeds; ++i) {
|
||||||
|
CPed *nearPed = m_nearPeds[i];
|
||||||
|
if (nearPed->m_nPedType == PEDTYPE_EMERGENCY) {
|
||||||
|
if ((nearPed->m_nPedState == PED_SEEK_CAR || nearPed->m_nPedState == PED_ENTER_CAR)
|
||||||
|
&& nearPed->m_pMyVehicle == m_pMyVehicle) {
|
||||||
|
waitUntilMedicEntersCar = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!waitUntilMedicEntersCar) {
|
||||||
|
CCarCtrl::JoinCarWithRoadSystem(m_pMyVehicle);
|
||||||
|
m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
|
||||||
|
m_pMyVehicle->m_bSirenOrAlarm = 0;
|
||||||
|
m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 12;
|
||||||
|
m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;
|
||||||
|
if (m_pMyVehicle->bIsAmbulanceOnDuty) {
|
||||||
|
m_pMyVehicle->bIsAmbulanceOnDuty = false;
|
||||||
|
--CCarCtrl::NumAmbulancesOnDuty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector headPos, midPos;
|
||||||
|
CAccident *nearestAccident;
|
||||||
|
if (IsPedInControl()) {
|
||||||
|
switch (m_nEmergencyPedState) {
|
||||||
|
case EMERGENCY_PED_READY:
|
||||||
|
nearestAccident = gAccidentManager.FindNearestAccident(GetPosition(), &distToEmergency);
|
||||||
|
field_1360 = 0;
|
||||||
|
if (nearestAccident) {
|
||||||
|
m_pRevivedPed = nearestAccident->m_pVictim;
|
||||||
|
m_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed);
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID);
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD);
|
||||||
|
SetSeek((headPos + midPos) * 0.5f, 1.0f);
|
||||||
|
SetObjective(OBJECTIVE_NONE);
|
||||||
|
bIsRunning = true;
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
m_pAttendedAccident = nearestAccident;
|
||||||
|
++m_pAttendedAccident->m_nMedicsAttending;
|
||||||
|
} else {
|
||||||
|
if (m_pMyVehicle) {
|
||||||
|
if (!bInVehicle) {
|
||||||
|
if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_pMyVehicle->pDriver || m_pMyVehicle->m_nGettingInFlags) {
|
||||||
|
|
||||||
|
CPed* driver = m_pMyVehicle->pDriver;
|
||||||
|
if (driver && driver->m_nPedType != PEDTYPE_EMERGENCY && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
|
||||||
|
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);
|
||||||
|
} else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER
|
||||||
|
&& m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER
|
||||||
|
&& m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
|
||||||
|
SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m_nPedState != PED_WANDER_PATH) {
|
||||||
|
SetWanderPath(CGeneral::GetRandomNumber() & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_DETERMINE_NEXT_STATE:
|
||||||
|
nearestAccident = gAccidentManager.FindNearestAccident(GetPosition(), &distToEmergency);
|
||||||
|
if (nearestAccident) {
|
||||||
|
if (nearestAccident != m_pAttendedAccident || m_nPedState != PED_SEEK_POS) {
|
||||||
|
m_pRevivedPed = nearestAccident->m_pVictim;
|
||||||
|
m_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed);
|
||||||
|
if (!InRange(m_pRevivedPed)) {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID);
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD);
|
||||||
|
SetSeek((headPos + midPos) * 0.5f, nearestAccident->m_nMedicsPerformingCPR * 0.5f + 1.0f);
|
||||||
|
SetObjective(OBJECTIVE_NONE);
|
||||||
|
bIsRunning = true;
|
||||||
|
--m_pAttendedAccident->m_nMedicsAttending;
|
||||||
|
++nearestAccident->m_nMedicsAttending;
|
||||||
|
m_pAttendedAccident = nearestAccident;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP;
|
||||||
|
bIsRunning = false;
|
||||||
|
}
|
||||||
|
if (distToEmergency < 5.0f) {
|
||||||
|
if (m_pRevivedPed->m_pFire) {
|
||||||
|
bIsRunning = false;
|
||||||
|
SetMoveState(PEDMOVE_STILL);
|
||||||
|
} else if (distToEmergency < 4.5f) {
|
||||||
|
bIsRunning = false;
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
if (distToEmergency < 1.0f
|
||||||
|
|| distToEmergency < 4.5f && m_pAttendedAccident->m_nMedicsPerformingCPR) {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_START_CPR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_START_CPR:
|
||||||
|
if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f || m_pRevivedPed->bFadeOut) {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
} else {
|
||||||
|
m_pRevivedPed->m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds();
|
||||||
|
SetMoveState(PEDMOVE_STILL);
|
||||||
|
m_nPedState = PED_CPR;
|
||||||
|
m_nLastPedState = PED_CPR;
|
||||||
|
SetLookFlag(m_pRevivedPed, 0);
|
||||||
|
SetLookTimer(500);
|
||||||
|
Say(SOUND_PED_HEALING);
|
||||||
|
if (m_pAttendedAccident->m_nMedicsPerformingCPR) {
|
||||||
|
SetIdle();
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STAND_STILL;
|
||||||
|
} else {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_FACE_TO_PATIENT;
|
||||||
|
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CPR, 4.0f);
|
||||||
|
bIsDucking = true;
|
||||||
|
}
|
||||||
|
SetLookTimer(2000);
|
||||||
|
++m_pAttendedAccident->m_nMedicsPerformingCPR;
|
||||||
|
m_bStartedToCPR = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_FACE_TO_PATIENT:
|
||||||
|
if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f)
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
else {
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID);
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD);
|
||||||
|
midPos = (headPos + midPos) * 0.5f;
|
||||||
|
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
|
||||||
|
midPos.x, midPos.y,
|
||||||
|
GetPosition().x, GetPosition().y);
|
||||||
|
m_fRotationDest = CGeneral::LimitAngle(m_fRotationDest);
|
||||||
|
m_pLookTarget = m_pRevivedPed;
|
||||||
|
m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
|
||||||
|
TurnBody();
|
||||||
|
|
||||||
|
if (Abs(m_fRotationCur - m_fRotationDest) < DEGTORAD(45.0f))
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_PERFORM_CPR;
|
||||||
|
else
|
||||||
|
m_fRotationCur = (m_fRotationCur + m_fRotationDest) * 0.5f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_PERFORM_CPR:
|
||||||
|
m_pRevivedPed = m_pRevivedPed;
|
||||||
|
if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f) {
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&midPos, PED_MID);
|
||||||
|
m_pRevivedPed->m_pedIK.GetComponentPosition((RwV3d*)&headPos, PED_HEAD);
|
||||||
|
midPos = (headPos + midPos) * 0.5f;
|
||||||
|
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
|
||||||
|
midPos.x, midPos.y,
|
||||||
|
GetPosition().x, GetPosition().y);
|
||||||
|
m_fRotationDest = CGeneral::LimitAngle(m_fRotationDest);
|
||||||
|
m_pLookTarget = m_pRevivedPed;
|
||||||
|
m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
|
||||||
|
TurnBody();
|
||||||
|
if (CTimer::GetTimeInMilliseconds() <= m_lookTimer) {
|
||||||
|
SetMoveState(PEDMOVE_STILL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP_CPR;
|
||||||
|
m_nPedState = PED_NONE;
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
m_pVehicleAnim = nil;
|
||||||
|
if (!m_pRevivedPed->bBodyPartJustCameOff) {
|
||||||
|
m_pRevivedPed->m_fHealth = 100.0f;
|
||||||
|
m_pRevivedPed->m_nPedState = PED_NONE;
|
||||||
|
m_pRevivedPed->m_nLastPedState = PED_WANDER_PATH;
|
||||||
|
m_pRevivedPed->SetGetUp();
|
||||||
|
m_pRevivedPed->bUsesCollision = true;
|
||||||
|
m_pRevivedPed->SetMoveState(PEDMOVE_WALK);
|
||||||
|
m_pRevivedPed->RestartNonPartialAnims();
|
||||||
|
m_pRevivedPed->bIsPedDieAnimPlaying = false;
|
||||||
|
m_pRevivedPed->m_ped_flagH1 = false;
|
||||||
|
m_pRevivedPed->m_pCollidingEntity = nil;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_STOP_CPR:
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_STOP;
|
||||||
|
bIsDucking = true;
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_STAND_STILL:
|
||||||
|
if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f)
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
else {
|
||||||
|
if (!m_pAttendedAccident->m_pVictim)
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
if (!m_pAttendedAccident->m_nMedicsPerformingCPR)
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
if (gAccidentManager.UnattendedAccidents())
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EMERGENCY_PED_STOP:
|
||||||
|
m_bStartedToCPR = false;
|
||||||
|
m_nPedState = PED_NONE;
|
||||||
|
if (m_pAttendedAccident) {
|
||||||
|
m_pAttendedAccident->m_pVictim = nil;
|
||||||
|
--m_pAttendedAccident->m_nMedicsAttending;
|
||||||
|
m_pAttendedAccident = nil;
|
||||||
|
}
|
||||||
|
SetWanderPath(CGeneral::GetRandomNumber() & 7);
|
||||||
|
m_pRevivedPed = nil;
|
||||||
|
m_nEmergencyPedState = EMERGENCY_PED_READY;
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CEmergencyPed_ : public CEmergencyPed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEmergencyPed* ctor(int pedtype) { return ::new (this) CEmergencyPed(pedtype); };
|
||||||
|
void dtor(void) { CEmergencyPed::~CEmergencyPed(); }
|
||||||
|
void ProcessControl_(void) { CEmergencyPed::ProcessControl(); }
|
||||||
|
};
|
||||||
|
|
||||||
STARTPATCHES
|
STARTPATCHES
|
||||||
InjectHook(0x4C2E40, &CEmergencyPed_::ctor, PATCH_JUMP);
|
InjectHook(0x4C2E40, &CEmergencyPed_::ctor, PATCH_JUMP);
|
||||||
InjectHook(0x4C2EF0, &CEmergencyPed_::dtor, PATCH_JUMP);
|
InjectHook(0x4C2EF0, &CEmergencyPed_::dtor, PATCH_JUMP);
|
||||||
|
InjectHook(0x4C2F10, &CEmergencyPed_::ProcessControl_, PATCH_JUMP);
|
||||||
|
InjectHook(0x4C3EC0, &CEmergencyPed::InRange, PATCH_JUMP);
|
||||||
ENDPATCHES
|
ENDPATCHES
|
||||||
|
@ -1,20 +1,40 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Fire.h"
|
|
||||||
#include "Ped.h"
|
#include "Ped.h"
|
||||||
|
|
||||||
|
class CAccident;
|
||||||
|
class CFire;
|
||||||
|
|
||||||
|
enum EmergencyPedState
|
||||||
|
{
|
||||||
|
EMERGENCY_PED_READY = 0x0,
|
||||||
|
EMERGENCY_PED_DETERMINE_NEXT_STATE = 0x1, // you can set that anytime you want
|
||||||
|
EMERGENCY_PED_START_CPR = 0x2,
|
||||||
|
EMERGENCY_PED_FLAG_4 = 0x4, // unused
|
||||||
|
EMERGENCY_PED_FLAG_8 = 0x8, // unused
|
||||||
|
EMERGENCY_PED_FACE_TO_PATIENT = 0x10, // for CPR
|
||||||
|
EMERGENCY_PED_PERFORM_CPR = 0x20,
|
||||||
|
EMERGENCY_PED_STOP_CPR = 0x40,
|
||||||
|
EMERGENCY_PED_STAND_STILL = 0x80, // waiting colleagues for medics, "extinguishing" fire for firemen
|
||||||
|
EMERGENCY_PED_STOP = 0x100,
|
||||||
|
};
|
||||||
|
|
||||||
class CEmergencyPed : public CPed
|
class CEmergencyPed : public CPed
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// 0x53C
|
// 0x53C
|
||||||
CPed* m_pRevivedPed;
|
CPed *m_pRevivedPed;
|
||||||
int32 m_nEmergencyPedState; // looks like flags
|
EmergencyPedState m_nEmergencyPedState;
|
||||||
void* m_pAttendedAccident; //TODO: CAccident*
|
CAccident *m_pAttendedAccident;
|
||||||
CFire* m_pAttendedFire;
|
CFire *m_pAttendedFire;
|
||||||
int8 field_1356;
|
bool m_bStartedToCPR; // set but unused(?)
|
||||||
int32 field_1360;
|
int32 field_1360; // also something for medics, unused(?)
|
||||||
|
|
||||||
CEmergencyPed(uint32);
|
CEmergencyPed(uint32);
|
||||||
|
~CEmergencyPed() { }
|
||||||
|
bool InRange(CPed*);
|
||||||
void ProcessControl(void);
|
void ProcessControl(void);
|
||||||
|
void FiremanAI(void);
|
||||||
|
void MedicAI(void);
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CEmergencyPed) == 0x554, "CEmergencyPed: error");
|
static_assert(sizeof(CEmergencyPed) == 0x554, "CEmergencyPed: error");
|
||||||
|
Loading…
Reference in New Issue
Block a user