mirror of
https://git.rip/DMCA_FUCKER/re3.git
synced 2024-12-23 19:40:00 +00:00
commit
81e711517d
|
@ -17,6 +17,7 @@
|
||||||
#include "ModelInfo.h"
|
#include "ModelInfo.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Pad.h"
|
#include "Pad.h"
|
||||||
|
#include "PedAttractor.h"
|
||||||
#include "Phones.h"
|
#include "Phones.h"
|
||||||
#include "Pickups.h"
|
#include "Pickups.h"
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
|
@ -1116,6 +1117,14 @@ void CReplay::StoreStuffInMem(void)
|
||||||
for (int i = 0; i < NUMPLAYERS; i++)
|
for (int i = 0; i < NUMPLAYERS; i++)
|
||||||
nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed);
|
nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed);
|
||||||
#endif
|
#endif
|
||||||
|
int i = CPools::GetPedPool()->GetSize();
|
||||||
|
while (--i >= 0) {
|
||||||
|
CPed* ped = CPools::GetPedPool()->GetSlot(i);
|
||||||
|
if (!ped)
|
||||||
|
continue;
|
||||||
|
if (ped->m_attractor)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(ped, ped->m_attractor);
|
||||||
|
}
|
||||||
CPools::GetVehiclePool()->Store(pBuf0, pBuf1);
|
CPools::GetVehiclePool()->Store(pBuf0, pBuf1);
|
||||||
CPools::GetPedPool()->Store(pBuf2, pBuf3);
|
CPools::GetPedPool()->Store(pBuf2, pBuf3);
|
||||||
CPools::GetObjectPool()->Store(pBuf4, pBuf5);
|
CPools::GetObjectPool()->Store(pBuf4, pBuf5);
|
||||||
|
|
|
@ -5248,12 +5248,8 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
|
||||||
ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true);
|
ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_STORE_WEATHER:
|
//case COMMAND_STORE_WEATHER:
|
||||||
CWeather::StoreWeatherState();
|
//case COMMAND_RESTORE_WEATHER:
|
||||||
return 0;
|
|
||||||
case COMMAND_RESTORE_WEATHER:
|
|
||||||
CWeather::RestoreWeatherState();
|
|
||||||
return 0;
|
|
||||||
case COMMAND_STORE_CLOCK:
|
case COMMAND_STORE_CLOCK:
|
||||||
CClock::StoreClock();
|
CClock::StoreClock();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -956,7 +956,7 @@ CFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath)
|
||||||
void
|
void
|
||||||
CFileLoader::Load2dEffect(const char *line)
|
CFileLoader::Load2dEffect(const char *line)
|
||||||
{
|
{
|
||||||
int id, r, g, b, a, type;
|
int id, r, g, b, a, type, ptype;
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
char corona[32], shadow[32];
|
char corona[32], shadow[32];
|
||||||
int shadowIntens, lightType, roadReflection, flare, flags, probability;
|
int shadowIntens, lightType, roadReflection, flare, flags, probability;
|
||||||
|
@ -1029,6 +1029,18 @@ CFileLoader::Load2dEffect(const char *line)
|
||||||
effect->attractor.flags = flags;
|
effect->attractor.flags = flags;
|
||||||
effect->attractor.probability = probability;
|
effect->attractor.probability = probability;
|
||||||
break;
|
break;
|
||||||
|
case EFFECT_PED_ATTRACTOR:
|
||||||
|
sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f",
|
||||||
|
&id, &x, &y, &z, &r, &g, &b, &a, &type,
|
||||||
|
&ptype,
|
||||||
|
&effect->pedattr.queueDir.x,
|
||||||
|
&effect->pedattr.queueDir.y,
|
||||||
|
&effect->pedattr.queueDir.z,
|
||||||
|
&effect->pedattr.useDir.x,
|
||||||
|
&effect->pedattr.useDir.y,
|
||||||
|
&effect->pedattr.useDir.z);
|
||||||
|
effect->pedattr.type = ptype;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTxdStore::PopCurrentTxd();
|
CTxdStore::PopCurrentTxd();
|
||||||
|
|
|
@ -60,6 +60,7 @@ int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];
|
||||||
|
|
||||||
int32 CStats::Sprayings;
|
int32 CStats::Sprayings;
|
||||||
float CStats::AutoPaintingBudget;
|
float CStats::AutoPaintingBudget;
|
||||||
|
int32 CStats::NoMoreHurricanes;
|
||||||
|
|
||||||
void CStats::Init()
|
void CStats::Init()
|
||||||
{
|
{
|
||||||
|
@ -119,6 +120,7 @@ void CStats::Init()
|
||||||
|
|
||||||
Sprayings = 0;
|
Sprayings = 0;
|
||||||
AutoPaintingBudget = 0.0f;
|
AutoPaintingBudget = 0.0f;
|
||||||
|
NoMoreHurricanes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStats::RegisterFastestTime(int32 index, int32 time)
|
void CStats::RegisterFastestTime(int32 index, int32 time)
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
static int32 HighestScores[TOTAL_HIGHEST_SCORES];
|
static int32 HighestScores[TOTAL_HIGHEST_SCORES];
|
||||||
static int32 Sprayings;
|
static int32 Sprayings;
|
||||||
static float AutoPaintingBudget;
|
static float AutoPaintingBudget;
|
||||||
|
static int32 NoMoreHurricanes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init(void);
|
static void Init(void);
|
||||||
|
|
|
@ -2240,3 +2240,58 @@ CWorld::UseDetonator(CEntity *pEntity)
|
||||||
}
|
}
|
||||||
CProjectileInfo::RemoveDetonatorProjectiles();
|
CProjectileInfo::RemoveDetonatorProjectiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps)
|
||||||
|
{
|
||||||
|
if (Abs(point1.z - point2.z) > distance)
|
||||||
|
return false;
|
||||||
|
if (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false))
|
||||||
|
return false;
|
||||||
|
CVector vecBetween = point2 - point1;
|
||||||
|
uint32 nSteps = Max(vecBetween.Magnitude(), maxSteps);
|
||||||
|
if (nSteps == 0)
|
||||||
|
return true;
|
||||||
|
vecBetween.Normalise();
|
||||||
|
uint32 step = 1;
|
||||||
|
for (step = 1; step < nSteps; step++) {
|
||||||
|
CVector posThisStep = point1 + vecBetween * step;
|
||||||
|
float level;
|
||||||
|
if (!CWaterLevel::GetWaterLevel(posThisStep, &level, false))
|
||||||
|
continue;
|
||||||
|
posThisStep.z = level;
|
||||||
|
AdvanceCurrentScanCode();
|
||||||
|
|
||||||
|
CVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z));
|
||||||
|
CColPoint colpoint;
|
||||||
|
CEntity* entity;
|
||||||
|
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
|
||||||
|
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector posThisStep = point1;
|
||||||
|
AdvanceCurrentScanCode();
|
||||||
|
CVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f);
|
||||||
|
|
||||||
|
CColPoint colpoint;
|
||||||
|
CEntity* entity;
|
||||||
|
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
|
||||||
|
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float heightNextStep = colpoint.point.z + 0.5f;
|
||||||
|
for (step = 1; step < nSteps; step++) {
|
||||||
|
CVector posThisStep = point1 + vecBetween * step;
|
||||||
|
posThisStep.z = heightNextStep;
|
||||||
|
AdvanceCurrentScanCode();
|
||||||
|
CVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f);
|
||||||
|
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
|
||||||
|
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
|
||||||
|
return false;
|
||||||
|
if (Abs(colpoint.point.z - heightNextStep) > 1.0f)
|
||||||
|
return false;
|
||||||
|
heightNextStep = colpoint.point.z + 0.5f;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -125,6 +125,8 @@ public:
|
||||||
static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY);
|
static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY);
|
||||||
static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2);
|
static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2);
|
||||||
|
|
||||||
|
static bool IsWanderPathClear(CVector const&, CVector const&, float, int);
|
||||||
|
|
||||||
static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }
|
static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }
|
||||||
static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }
|
static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }
|
||||||
static int GetSectorIndexX(float f) { return (int)GetSectorX(f); }
|
static int GetSectorIndexX(float f) { return (int)GetSectorX(f); }
|
||||||
|
|
|
@ -78,7 +78,8 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector &GetPosition(void){ return *(CVector*)&m_matrix.pos; }
|
const CVector &GetPosition(void) const { return *(CVector*)&m_matrix.pos; }
|
||||||
|
CVector& GetPosition(void) { return *(CVector*)&m_matrix.pos; }
|
||||||
CVector &GetRight(void) { return *(CVector*)&m_matrix.right; }
|
CVector &GetRight(void) { return *(CVector*)&m_matrix.right; }
|
||||||
CVector &GetForward(void) { return *(CVector*)&m_matrix.up; }
|
CVector &GetForward(void) { return *(CVector*)&m_matrix.up; }
|
||||||
CVector &GetUp(void) { return *(CVector*)&m_matrix.at; }
|
CVector &GetUp(void) { return *(CVector*)&m_matrix.at; }
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "Vehicle.h"
|
#include "Vehicle.h"
|
||||||
#include "SurfaceTable.h"
|
#include "SurfaceTable.h"
|
||||||
|
#include "Weather.h"
|
||||||
|
#include "PedAttractor.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
|
CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +19,8 @@ CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
|
||||||
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
|
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
|
||||||
m_nearPeds[i] = nil;
|
m_nearPeds[i] = nil;
|
||||||
}
|
}
|
||||||
|
m_nAttractorCycleState = 0;
|
||||||
|
m_bAttractorUnk = (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 1.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -212,7 +217,7 @@ CCivilianPed::ProcessControl(void)
|
||||||
// fall through
|
// fall through
|
||||||
case PED_SEEK_POS:
|
case PED_SEEK_POS:
|
||||||
if (Seek()) {
|
if (Seek()) {
|
||||||
if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) {
|
if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) && m_pNextPathNode) {
|
||||||
m_pNextPathNode = nil;
|
m_pNextPathNode = nil;
|
||||||
#ifdef TOGGLEABLE_BETA_FEATURES
|
#ifdef TOGGLEABLE_BETA_FEATURES
|
||||||
} else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) {
|
} else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) {
|
||||||
|
@ -244,7 +249,7 @@ CCivilianPed::ProcessControl(void)
|
||||||
} else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT
|
} else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT
|
||||||
&& m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) {
|
&& m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) {
|
||||||
SetMoveState(m_pedInObjective->m_nMoveState);
|
SetMoveState(m_pedInObjective->m_nMoveState);
|
||||||
} else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) {
|
} else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) {
|
||||||
SetIdle();
|
SetIdle();
|
||||||
} else {
|
} else {
|
||||||
RestorePreviousState();
|
RestorePreviousState();
|
||||||
|
@ -365,6 +370,10 @@ CCivilianPed::ProcessControl(void)
|
||||||
if (IsPedInControl())
|
if (IsPedInControl())
|
||||||
CivilianAI();
|
CivilianAI();
|
||||||
|
|
||||||
|
if (CharCreatedBy == RANDOM_CHAR) {
|
||||||
|
UseNearbyAttractors();
|
||||||
|
}
|
||||||
|
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_timerUnused) {
|
if (CTimer::GetTimeInMilliseconds() > m_timerUnused) {
|
||||||
m_stateUnused = 0;
|
m_stateUnused = 0;
|
||||||
m_timerUnused = 0;
|
m_timerUnused = 0;
|
||||||
|
@ -373,3 +382,90 @@ CCivilianPed::ProcessControl(void)
|
||||||
if (m_moved.Magnitude() > 0.0f)
|
if (m_moved.Magnitude() > 0.0f)
|
||||||
Avoid();
|
Avoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int32 gFrequencyOfAttractorAttempt = 11;
|
||||||
|
const float gDistanceToSeekAttractors = 50.0f;
|
||||||
|
const float gMaxDistanceToAttract = 10.0f;
|
||||||
|
|
||||||
|
/* Probably this was inlined */
|
||||||
|
void CCivilianPed::FindNearbyAttractorsSectorList(CPtrList& list, float& minDistance, C2dEffect*& pClosestAttractor, CEntity*& pAttractorEntity)
|
||||||
|
{
|
||||||
|
for (CPtrNode* pNode = list.first; pNode != nil; pNode = pNode->next) {
|
||||||
|
CEntity* pEntity = (CEntity*)pNode->item;
|
||||||
|
if (pEntity->IsObject() && (!pEntity->IsStatic() || ((CObject*)pEntity)->bHasBeenDamaged))
|
||||||
|
continue;
|
||||||
|
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex());
|
||||||
|
for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) {
|
||||||
|
C2dEffect* pEffect = pModelInfo->Get2dEffect(i);
|
||||||
|
if (pEffect->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
continue;
|
||||||
|
if (!IsAttractedTo(pEffect->pedattr.type))
|
||||||
|
continue;
|
||||||
|
CVector pos;
|
||||||
|
CPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos);
|
||||||
|
if ((pos - GetPosition()).MagnitudeSqr() < minDistance) {
|
||||||
|
CPedAttractorManager* pManager = GetPedAttractorManager();
|
||||||
|
if (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) {
|
||||||
|
pClosestAttractor = pEffect;
|
||||||
|
pAttractorEntity = pEntity;
|
||||||
|
minDistance = (pos - GetPosition()).MagnitudeSqr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCivilianPed::UseNearbyAttractors()
|
||||||
|
{
|
||||||
|
if (CWeather::Rain < 0.2f && !m_bAttractorUnk)
|
||||||
|
return;
|
||||||
|
if (HasAttractor())
|
||||||
|
return;
|
||||||
|
if (m_nAttractorCycleState != gFrequencyOfAttractorAttempt) {
|
||||||
|
m_nAttractorCycleState++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_nAttractorCycleState = 0;
|
||||||
|
if (!IsPedInControl())
|
||||||
|
return;
|
||||||
|
if (m_nPedState == PED_FLEE_ENTITY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float left = GetPosition().x - gDistanceToSeekAttractors;
|
||||||
|
float right = GetPosition().x + gDistanceToSeekAttractors;
|
||||||
|
float top = GetPosition().y - gDistanceToSeekAttractors;
|
||||||
|
float bottom = GetPosition().y + gDistanceToSeekAttractors;
|
||||||
|
int xstart = Max(0, CWorld::GetSectorIndexX(left));
|
||||||
|
int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
|
||||||
|
int ystart = Max(0, CWorld::GetSectorIndexY(top));
|
||||||
|
int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
|
||||||
|
assert(xstart <= xend);
|
||||||
|
assert(ystart <= yend);
|
||||||
|
|
||||||
|
float minDistance = SQR(gMaxDistanceToAttract);
|
||||||
|
C2dEffect* pClosestAttractor = nil;
|
||||||
|
CEntity* pAttractorEntity = nil;
|
||||||
|
|
||||||
|
for (int y = ystart; y <= yend; y++) {
|
||||||
|
for (int x = xstart; x <= xend; x++) {
|
||||||
|
CSector* s = CWorld::GetSector(x, y);
|
||||||
|
FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_BUILDINGS], minDistance, pClosestAttractor, pAttractorEntity);
|
||||||
|
FindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_OBJECTS], minDistance, pClosestAttractor, pAttractorEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pClosestAttractor)
|
||||||
|
GetPedAttractorManager()->RegisterPedWithAttractor(this, pClosestAttractor, pAttractorEntity->GetMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCivilianPed::IsAttractedTo(int8 type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ATTRACTOR_ATM: return true;
|
||||||
|
case ATTRACTOR_SEAT: return true;
|
||||||
|
case ATTRACTOR_STOP: return true;
|
||||||
|
case ATTRACTOR_PIZZA: return true;
|
||||||
|
case ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f;
|
||||||
|
case ATTRACTOR_ICECREAM: return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,17 @@
|
||||||
|
|
||||||
class CCivilianPed : public CPed
|
class CCivilianPed : public CPed
|
||||||
{
|
{
|
||||||
|
bool m_bAttractorUnk;
|
||||||
|
int32 m_nAttractorCycleState;
|
||||||
public:
|
public:
|
||||||
CCivilianPed(ePedType, uint32);
|
CCivilianPed(ePedType, uint32);
|
||||||
~CCivilianPed(void) { }
|
~CCivilianPed(void) { }
|
||||||
|
|
||||||
void CivilianAI(void);
|
void CivilianAI(void);
|
||||||
void ProcessControl(void);
|
void ProcessControl(void);
|
||||||
|
void UseNearbyAttractors(void);
|
||||||
|
void FindNearbyAttractorsSectorList(CPtrList&, float&, C2dEffect*&, CEntity*&);
|
||||||
|
bool IsAttractedTo(int8);
|
||||||
};
|
};
|
||||||
#ifndef PED_SKIN
|
#ifndef PED_SKIN
|
||||||
VALIDATE_SIZE(CCivilianPed, 0x53C);
|
VALIDATE_SIZE(CCivilianPed, 0x53C);
|
||||||
|
|
439
src/peds/Ped.cpp
439
src/peds/Ped.cpp
|
@ -58,6 +58,7 @@
|
||||||
#include "ParticleObject.h"
|
#include "ParticleObject.h"
|
||||||
#include "Floater.h"
|
#include "Floater.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
|
#include "PedAttractor.h"
|
||||||
|
|
||||||
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
|
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
|
||||||
|
|
||||||
|
@ -385,6 +386,8 @@ CPed::DebugRenderOnePedText(void)
|
||||||
CPed::~CPed(void)
|
CPed::~CPed(void)
|
||||||
{
|
{
|
||||||
CWorld::Remove(this);
|
CWorld::Remove(this);
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
|
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
|
||||||
if (InVehicle()){
|
if (InVehicle()){
|
||||||
uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
|
uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
|
||||||
|
@ -453,13 +456,17 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||||
CharCreatedBy = RANDOM_CHAR;
|
CharCreatedBy = RANDOM_CHAR;
|
||||||
m_leader = nil;
|
m_leader = nil;
|
||||||
m_pedInObjective = nil;
|
m_pedInObjective = nil;
|
||||||
|
m_attractorHeading = 0.0f;
|
||||||
m_carInObjective = nil;
|
m_carInObjective = nil;
|
||||||
|
m_attractorHeading = 0.0f;
|
||||||
bInVehicle = false;
|
bInVehicle = false;
|
||||||
m_pMyVehicle = nil;
|
m_pMyVehicle = nil;
|
||||||
m_pVehicleAnim = nil;
|
m_pVehicleAnim = nil;
|
||||||
m_vecOffsetSeek.x = 0.0f;
|
m_vecOffsetSeek.x = 0.0f;
|
||||||
m_vecOffsetSeek.y = 0.0f;
|
m_vecOffsetSeek.y = 0.0f;
|
||||||
m_vecOffsetSeek.z = 0.0f;
|
m_vecOffsetSeek.z = 0.0f;
|
||||||
|
m_attractor = nil;
|
||||||
|
m_positionInQueue = -1;
|
||||||
m_pedFormation = FORMATION_UNDEFINED;
|
m_pedFormation = FORMATION_UNDEFINED;
|
||||||
m_collidingThingTimer = 0;
|
m_collidingThingTimer = 0;
|
||||||
m_nPedStateTimer = 0;
|
m_nPedStateTimer = 0;
|
||||||
|
@ -488,6 +495,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||||
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
|
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
|
||||||
m_wepSkills = 0;
|
m_wepSkills = 0;
|
||||||
m_distanceToCountSeekDone = 1.0f;
|
m_distanceToCountSeekDone = 1.0f;
|
||||||
|
m_acceptableHeadingOffset = 0.1f;
|
||||||
bRunningToPhone = false;
|
bRunningToPhone = false;
|
||||||
m_phoneId = -1;
|
m_phoneId = -1;
|
||||||
m_lastAccident = 0;
|
m_lastAccident = 0;
|
||||||
|
@ -610,6 +618,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
||||||
bSomeVCflag1 = false;
|
bSomeVCflag1 = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bReachedAttractorHeadingTarget = false;
|
||||||
|
bTurnedAroundOnAttractor = false;
|
||||||
bCarPassenger = false;
|
bCarPassenger = false;
|
||||||
bMiamiViceCop = false;
|
bMiamiViceCop = false;
|
||||||
bDeadPedInFrontOfCar = false;
|
bDeadPedInFrontOfCar = false;
|
||||||
|
@ -3927,6 +3937,8 @@ CPed::SetStoredState(void)
|
||||||
void
|
void
|
||||||
CPed::SetDie(AnimationId animId, float delta, float speed)
|
CPed::SetDie(AnimationId animId, float delta, float speed)
|
||||||
{
|
{
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
CPlayerPed *player = FindPlayerPed();
|
CPlayerPed *player = FindPlayerPed();
|
||||||
if (player == this) {
|
if (player == this) {
|
||||||
if (!player->m_bCanBeDamaged)
|
if (!player->m_bCanBeDamaged)
|
||||||
|
@ -5846,8 +5858,45 @@ CPed::SetWaitState(eWaitState state, void *time)
|
||||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
||||||
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
|
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
|
||||||
break;
|
break;
|
||||||
|
case WAITSTATE_SIT_DOWN:
|
||||||
|
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_DOWN, 4.0f);
|
||||||
|
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000;
|
||||||
|
break;
|
||||||
|
case WAITSTATE_SIT_UP:
|
||||||
|
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_UP, 4.0f);
|
||||||
|
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;
|
||||||
|
break;
|
||||||
|
case WAITSTATE_SIT_IDLE:
|
||||||
|
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_SEAT_IDLE, 5000.0f);
|
||||||
|
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||||
|
if (time)
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
|
||||||
|
else
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000);
|
||||||
|
break;
|
||||||
|
case WAITSTATE_USE_ATM:
|
||||||
|
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ATM, 5000.0f);
|
||||||
|
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||||
|
if (time)
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
|
||||||
|
else
|
||||||
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;
|
||||||
|
break;
|
||||||
|
case WAITSTATE_SUN_BATHE_PRE:
|
||||||
|
case WAITSTATE_SUN_BATHE_DOWN:
|
||||||
|
case WAITSTATE_SUN_BATHE_IDLE:
|
||||||
|
case WAITSTATE_RIOT:
|
||||||
|
case WAITSTATE_FAST_FALL:
|
||||||
|
case WAITSTATE_BOMBER:
|
||||||
|
case WAITSTATE_STRIPPER:
|
||||||
|
case WAITSTATE_GROUND_ATTACK:
|
||||||
|
case WAITSTATE_LANCESITTING:
|
||||||
|
case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
|
||||||
|
assert(0);
|
||||||
default:
|
default:
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
RestoreHeadingRate();
|
RestoreHeadingRate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7552,7 +7601,7 @@ CPed::Wait(void)
|
||||||
CPed *pedWeLook;
|
CPed *pedWeLook;
|
||||||
|
|
||||||
if (DyingOrDead()) {
|
if (DyingOrDead()) {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
RestoreHeadingRate();
|
RestoreHeadingRate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7562,7 +7611,7 @@ CPed::Wait(void)
|
||||||
case WAITSTATE_TRAFFIC_LIGHTS:
|
case WAITSTATE_TRAFFIC_LIGHTS:
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
|
if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
SetMoveState(PEDMOVE_WALK);
|
SetMoveState(PEDMOVE_WALK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7571,7 +7620,7 @@ CPed::Wait(void)
|
||||||
case WAITSTATE_CROSS_ROAD:
|
case WAITSTATE_CROSS_ROAD:
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
|
if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
else
|
else
|
||||||
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
|
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
|
||||||
|
|
||||||
|
@ -7585,7 +7634,7 @@ CPed::Wait(void)
|
||||||
|
|
||||||
case WAITSTATE_CROSS_ROAD_LOOK:
|
case WAITSTATE_CROSS_ROAD_LOOK:
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
|
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
|
||||||
if (animAssoc) {
|
if (animAssoc) {
|
||||||
animAssoc->blendDelta = -8.0f;
|
animAssoc->blendDelta = -8.0f;
|
||||||
|
@ -7602,7 +7651,7 @@ CPed::Wait(void)
|
||||||
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
|
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
SetMoveState(PEDMOVE_WALK);
|
SetMoveState(PEDMOVE_WALK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -7613,13 +7662,13 @@ CPed::Wait(void)
|
||||||
m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WAITSTATE_TURN180:
|
case WAITSTATE_TURN180:
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
SetMoveState(PEDMOVE_WALK);
|
SetMoveState(PEDMOVE_WALK);
|
||||||
m_fRotationCur = m_fRotationCur + PI;
|
m_fRotationCur = m_fRotationCur + PI;
|
||||||
if (m_nPedState == PED_INVESTIGATE)
|
if (m_nPedState == PED_INVESTIGATE)
|
||||||
|
@ -7638,7 +7687,7 @@ CPed::Wait(void)
|
||||||
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
|
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
|
||||||
} else {
|
} else {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -7667,7 +7716,7 @@ CPed::Wait(void)
|
||||||
|
|
||||||
if (animAssoc->animId == ANIM_TURN_180) {
|
if (animAssoc->animId == ANIM_TURN_180) {
|
||||||
m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
|
m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
SetMoveState(PEDMOVE_WALK);
|
SetMoveState(PEDMOVE_WALK);
|
||||||
m_nStoredMoveState = PEDMOVE_NONE;
|
m_nStoredMoveState = PEDMOVE_NONE;
|
||||||
m_panicCounter = 0;
|
m_panicCounter = 0;
|
||||||
|
@ -7704,7 +7753,7 @@ CPed::Wait(void)
|
||||||
|
|
||||||
case WAITSTATE_LOOK_ABOUT:
|
case WAITSTATE_LOOK_ABOUT:
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
|
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
|
||||||
if (animAssoc) {
|
if (animAssoc) {
|
||||||
animAssoc->blendDelta = -8.0f;
|
animAssoc->blendDelta = -8.0f;
|
||||||
|
@ -7731,7 +7780,7 @@ CPed::Wait(void)
|
||||||
|
|
||||||
TurnBody();
|
TurnBody();
|
||||||
} else {
|
} else {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
m_nWaitTimer = 0;
|
m_nWaitTimer = 0;
|
||||||
if (m_pLookTarget && m_pLookTarget->IsPed()) {
|
if (m_pLookTarget && m_pLookTarget->IsPed()) {
|
||||||
|
|
||||||
|
@ -7806,7 +7855,7 @@ CPed::Wait(void)
|
||||||
animAssoc->blendDelta = -4.0f;
|
animAssoc->blendDelta = -4.0f;
|
||||||
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
||||||
}
|
}
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
}
|
}
|
||||||
#ifdef VC_PED_PORTS
|
#ifdef VC_PED_PORTS
|
||||||
else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
|
else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
|
||||||
|
@ -7830,13 +7879,59 @@ CPed::Wait(void)
|
||||||
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
||||||
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
|
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
|
||||||
int timer = 2000;
|
int timer = 2000;
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
|
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_nWaitState = WAITSTATE_FALSE;
|
ClearWaitState();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WAITSTATE_SIT_DOWN:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
|
ClearWaitState();
|
||||||
|
SetWaitState(WAITSTATE_SIT_IDLE, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
//case WAITSTATE_SIT_DOWN_RVRS:
|
||||||
|
case WAITSTATE_SIT_UP:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
|
||||||
|
ClearWaitState();
|
||||||
|
//TODO(MIAMI): scan for threats!
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WAITSTATE_SIT_IDLE:
|
||||||
|
if (bTurnedAroundOnAttractor) {
|
||||||
|
m_fRotationCur += PI;
|
||||||
|
m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
|
||||||
|
m_fRotationDest = m_fRotationCur;
|
||||||
|
bTurnedAroundOnAttractor = false;
|
||||||
|
}
|
||||||
|
// TODO(MIAMI): scan for threats!
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
|
ClearWaitState();
|
||||||
|
SetWaitState(WAITSTATE_SIT_UP, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WAITSTATE_USE_ATM:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
|
||||||
|
ClearWaitState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WAITSTATE_SUN_BATHE_PRE:
|
||||||
|
case WAITSTATE_SUN_BATHE_DOWN:
|
||||||
|
case WAITSTATE_SUN_BATHE_IDLE:
|
||||||
|
case WAITSTATE_RIOT:
|
||||||
|
case WAITSTATE_FAST_FALL:
|
||||||
|
case WAITSTATE_BOMBER:
|
||||||
|
case WAITSTATE_STRIPPER:
|
||||||
|
case WAITSTATE_GROUND_ATTACK:
|
||||||
|
case WAITSTATE_LANCESITTING:
|
||||||
|
case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
|
||||||
|
assert(0);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9837,7 +9932,7 @@ CPed::ProcessControl(void)
|
||||||
} else if (m_nPedStateTimer < 1001) {
|
} else if (m_nPedStateTimer < 1001) {
|
||||||
m_nPedStateTimer = 0;
|
m_nPedStateTimer = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!GetPedAttractorManager()->IsInQueue(this, m_attractor)) {
|
||||||
if (m_panicCounter == 50 && IsPedInControl()) {
|
if (m_panicCounter == 50 && IsPedInControl()) {
|
||||||
SetWaitState(WAITSTATE_STUCK, nil);
|
SetWaitState(WAITSTATE_STUCK, nil);
|
||||||
// Leftover
|
// Leftover
|
||||||
|
@ -13015,14 +13110,26 @@ CPed::ProcessObjective(void)
|
||||||
case OBJECTIVE_FOLLOW_CAR_IN_CAR:
|
case OBJECTIVE_FOLLOW_CAR_IN_CAR:
|
||||||
case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE:
|
case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE:
|
||||||
case OBJECTIVE_DESTROY_OBJ:
|
case OBJECTIVE_DESTROY_OBJ:
|
||||||
case OBJECTIVE_23:
|
case OBJECTIVE_26:
|
||||||
case OBJECTIVE_24:
|
case OBJECTIVE_27:
|
||||||
case OBJECTIVE_SET_LEADER:
|
case OBJECTIVE_SET_LEADER:
|
||||||
break;
|
break;
|
||||||
case OBJECTIVE_IDLE:
|
case OBJECTIVE_IDLE:
|
||||||
|
if (GetPedState() == PED_DRIVING)
|
||||||
|
m_objective = OBJECTIVE_NONE;
|
||||||
|
else {
|
||||||
SetIdle();
|
SetIdle();
|
||||||
|
if (m_attractor) {
|
||||||
|
if (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||||
|
GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
|
||||||
|
m_objectiveTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
m_objective = OBJECTIVE_NONE;
|
m_objective = OBJECTIVE_NONE;
|
||||||
SetMoveState(PEDMOVE_STILL);
|
SetMoveState(PEDMOVE_STILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECTIVE_FLEE_TILL_SAFE:
|
case OBJECTIVE_FLEE_TILL_SAFE:
|
||||||
if (InVehicle()) {
|
if (InVehicle()) {
|
||||||
|
@ -14201,6 +14308,187 @@ CPed::ProcessObjective(void)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OBJECTIVE_USE_SEAT_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ATM_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_STOP_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_PIZZA_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_SHELTER_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
|
||||||
|
m_objectiveTimer = 0;
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CVector distance = m_nextRoutePointPos - GetPosition();
|
||||||
|
distance.z = 0.0f;
|
||||||
|
if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) {
|
||||||
|
if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(2.0f)) {
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
bIsRunning = false;
|
||||||
|
}
|
||||||
|
else if (CWeather::Rain < 0.2f && m_attractor) {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) {
|
||||||
|
if (m_nMoveState == PEDMOVE_SPRINT && distance.Magnitude() < SQR(4.0f)) {
|
||||||
|
SetMoveState(PEDMOVE_WALK);
|
||||||
|
bIsRunning = false;
|
||||||
|
}
|
||||||
|
CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());
|
||||||
|
if (0.01f * CTimer::GetTimeStep() * 5.0f < pIceCreamVan->m_fDistanceTravelled) {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pIceCreamVan->pDriver ||
|
||||||
|
!pIceCreamVan->pDriver->IsPlayer() ||
|
||||||
|
pIceCreamVan->pDriver->GetPedState() == PED_ARRESTED ||
|
||||||
|
pIceCreamVan->pDriver->GetPedState() == PED_DEAD) {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pIceCreamVan->m_bSirenOrAlarm) {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pIceCreamVan->GetStatus() == STATUS_WRECKED) {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sq(m_distanceToCountSeekDone) < distance.MagnitudeSqr()) {
|
||||||
|
if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || GetPedState() != PED_SEEK_POS)
|
||||||
|
SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!bReachedAttractorHeadingTarget) {
|
||||||
|
float fHeadingDistance = m_fRotationCur - m_attractorHeading;
|
||||||
|
float fSinHeading = Sin(fHeadingDistance);
|
||||||
|
float fCosHeading = Cos(fHeadingDistance);
|
||||||
|
if (fSinHeading > 0.0f) {
|
||||||
|
if (fCosHeading > 0.0f)
|
||||||
|
m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
|
||||||
|
else
|
||||||
|
m_attractorHeading = m_fRotationCur - Acos(fCosHeading);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fCosHeading > 0.0f)
|
||||||
|
m_attractorHeading = m_fRotationCur - Asin(fSinHeading);
|
||||||
|
else
|
||||||
|
m_attractorHeading = m_fRotationCur + Acos(fCosHeading);
|
||||||
|
}
|
||||||
|
m_fRotationDest = m_attractorHeading;
|
||||||
|
m_headingRate = 3.5f;
|
||||||
|
bReachedAttractorHeadingTarget = true;
|
||||||
|
bTurnedAroundOnAttractor = false;
|
||||||
|
}
|
||||||
|
if (Abs(m_fRotationCur - m_attractorHeading) >= m_acceptableHeadingOffset &&
|
||||||
|
Abs(m_fRotationCur - m_attractorHeading + TWOPI) >= m_acceptableHeadingOffset &&
|
||||||
|
Abs(m_fRotationCur - m_attractorHeading - TWOPI) >= m_acceptableHeadingOffset)
|
||||||
|
SetMoveState(PEDMOVE_STILL);
|
||||||
|
else {
|
||||||
|
m_fRotationDest = m_fRotationCur;
|
||||||
|
bReachedAttractorHeadingTarget = false;
|
||||||
|
bObjectiveCompleted = true;
|
||||||
|
bScriptObjectiveCompleted = true;
|
||||||
|
RestoreHeadingRate();
|
||||||
|
GetPedAttractorManager()->BroadcastArrival(this, m_attractor);
|
||||||
|
if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) {
|
||||||
|
switch (m_objective) {
|
||||||
|
case OBJECTIVE_USE_SEAT_ATTRACTOR:
|
||||||
|
if (!bTurnedAroundOnAttractor) {
|
||||||
|
ClearObjective();
|
||||||
|
SetWaitState(WAITSTATE_SIT_DOWN, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ClearObjective();
|
||||||
|
SetWaitState(WAITSTATE_SIT_DOWN_RVRS, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_USE_ATM_ATTRACTOR:
|
||||||
|
ClearObjective();
|
||||||
|
SetWaitState(WAITSTATE_USE_ATM, 0);
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_USE_STOP_ATTRACTOR:
|
||||||
|
ClearObjective();
|
||||||
|
SetObjective(OBJECTIVE_WAIT_FOR_BUS);
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_USE_PIZZA_ATTRACTOR:
|
||||||
|
ClearObjective();
|
||||||
|
m_prevObjective = OBJECTIVE_NONE;
|
||||||
|
SetObjective(OBJECTIVE_IDLE);
|
||||||
|
m_objectiveTimer = CTimer::GetTimeInMilliseconds() + m_attractor->GetHeadOfQueueWaitTime();
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_USE_SHELTER_ATTRACTOR:
|
||||||
|
m_prevObjective = OBJECTIVE_NONE;
|
||||||
|
SetObjective(OBJECTIVE_WAIT_FOR_RAIN_TO_END);
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
|
||||||
|
m_prevObjective = OBJECTIVE_NONE;
|
||||||
|
SetObjective(OBJECTIVE_PURCHASE_ICECREAM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case OBJECTIVE_WAIT_FOR_RAIN_TO_END:
|
||||||
|
SetIdle();
|
||||||
|
if (m_attractor && CWeather::Rain < 0.2f)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
break;
|
||||||
|
case OBJECTIVE_WAIT_FOR_BUS:
|
||||||
|
SetIdle();
|
||||||
|
if (m_attractor) {
|
||||||
|
float left = GetPosition().x - 10.0f;
|
||||||
|
float right = GetPosition().x + 10.0f;
|
||||||
|
float top = GetPosition().y - 10.0f;
|
||||||
|
float bottom = GetPosition().y + 10.0f;
|
||||||
|
int xstart = Max(0, CWorld::GetSectorIndexX(left));
|
||||||
|
int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
|
||||||
|
int ystart = Max(0, CWorld::GetSectorIndexY(top));
|
||||||
|
int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
|
||||||
|
assert(xstart <= xend);
|
||||||
|
assert(ystart <= yend);
|
||||||
|
|
||||||
|
float minDistance = SQR(10.0f);
|
||||||
|
CVehicle* pBus = nil;
|
||||||
|
|
||||||
|
for (int y = ystart; y <= yend; y++) {
|
||||||
|
for (int x = xstart; x <= xend; x++) {
|
||||||
|
CSector* s = CWorld::GetSector(x, y);
|
||||||
|
for (CPtrNode* pNode = s->m_lists[ENTITYLIST_VEHICLES].first; pNode != nil; pNode = pNode->next) {
|
||||||
|
CEntity* pEntity = (CEntity*)pNode->item;
|
||||||
|
if (!pEntity->IsVehicle())
|
||||||
|
continue;
|
||||||
|
CVehicle* pVehicle = (CVehicle*)pEntity;
|
||||||
|
if (!pVehicle->bIsBus)
|
||||||
|
continue;
|
||||||
|
if (pVehicle->GetMoveSpeed().MagnitudeSqr() >= SQR(0.005f))
|
||||||
|
continue;
|
||||||
|
float distanceSq = (GetPosition() - pVehicle->GetPosition()).MagnitudeSqr();
|
||||||
|
if (distanceSq < minDistance) {
|
||||||
|
minDistance = distanceSq;
|
||||||
|
pBus = pVehicle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pBus) {
|
||||||
|
if (pBus->m_nNumPassengers >= pBus->m_nNumMaxPassengers - 1)
|
||||||
|
SetObjective(OBJECTIVE_IDLE);
|
||||||
|
else {
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus);
|
||||||
|
bDontDragMeOutCar = true; // TODO(MIAMI): check, add more flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (bObjectiveCompleted
|
if (bObjectiveCompleted
|
||||||
|
@ -17278,6 +17566,22 @@ CPed::WarpPedIntoCar(CVehicle *car)
|
||||||
bChangedSeat = true;
|
bChangedSeat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPed::SetObjective(eObjective newObj, float heading, const CVector& pos)
|
||||||
|
{
|
||||||
|
switch (newObj) {
|
||||||
|
case OBJECTIVE_USE_SEAT_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ATM_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_STOP_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_PIZZA_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_SHELTER_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
|
||||||
|
ClearPointGunAt();
|
||||||
|
SetObjective(newObj, pos);
|
||||||
|
m_attractorHeading = heading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPed::SetObjective(eObjective newObj, CVector dest)
|
CPed::SetObjective(eObjective newObj, CVector dest)
|
||||||
{
|
{
|
||||||
|
@ -17327,14 +17631,50 @@ CPed::SetObjective(eObjective newObj, CVector dest)
|
||||||
break;
|
break;
|
||||||
case OBJECTIVE_GOTO_AREA_ANY_MEANS:
|
case OBJECTIVE_GOTO_AREA_ANY_MEANS:
|
||||||
case OBJECTIVE_GOTO_AREA_ON_FOOT:
|
case OBJECTIVE_GOTO_AREA_ON_FOOT:
|
||||||
|
case OBJECTIVE_USE_SEAT_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ATM_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_STOP_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_PIZZA_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_SHELTER_ATTRACTOR:
|
||||||
|
case OBJECTIVE_USE_ICECREAM_ATTRACTOR:
|
||||||
bIsRunning = false;
|
bIsRunning = false;
|
||||||
m_pNextPathNode = nil;
|
m_pNextPathNode = nil;
|
||||||
m_nextRoutePointPos = dest;
|
m_nextRoutePointPos = dest;
|
||||||
m_vecSeekPos = m_nextRoutePointPos;
|
m_vecSeekPos = m_nextRoutePointPos;
|
||||||
m_distanceToCountSeekDone = 0.5f;
|
m_distanceToCountSeekDone = 0.5f;
|
||||||
bUsePedNodeSeek = true;
|
if (m_objective == OBJECTIVE_USE_ATM_ATTRACTOR) {
|
||||||
if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D())
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
if (m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR) {
|
||||||
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
if (m_objective == OBJECTIVE_USE_STOP_ATTRACTOR) {
|
||||||
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
if (m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR) {
|
||||||
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
if (m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR) {
|
||||||
|
bIsRunning = true;
|
||||||
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
if (m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR) {
|
||||||
|
bIsRunning = true;
|
||||||
|
m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();
|
||||||
|
m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();
|
||||||
|
}
|
||||||
|
bUsePedNodeSeek = false;
|
||||||
|
if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) {
|
||||||
|
if (!IsUseAttractorObjective(m_objective))
|
||||||
return;
|
return;
|
||||||
|
if (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset)
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECTIVE_RUN_TO_AREA:
|
case OBJECTIVE_RUN_TO_AREA:
|
||||||
bIsRunning = true;
|
bIsRunning = true;
|
||||||
|
@ -17961,6 +18301,65 @@ CPed::SetExitBoat(CVehicle *boat)
|
||||||
CWaterLevel::FreeBoatWakeArray();
|
CWaterLevel::FreeBoatWakeArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPed::SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float heading, float time, int32 qid)
|
||||||
|
{
|
||||||
|
if (!m_attractor)
|
||||||
|
m_attractor = pAttractor;
|
||||||
|
if (m_attractor != pAttractor)
|
||||||
|
return;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: SetObjective(OBJECTIVE_USE_ATM_ATTRACTOR, heading, pos); break;
|
||||||
|
case ATTRACTOR_SEAT: SetObjective(OBJECTIVE_USE_SEAT_ATTRACTOR, heading, pos); break;
|
||||||
|
case ATTRACTOR_STOP: SetObjective(OBJECTIVE_USE_STOP_ATTRACTOR, heading, pos); break;
|
||||||
|
case ATTRACTOR_PIZZA: SetObjective(OBJECTIVE_USE_PIZZA_ATTRACTOR, heading, pos); break;
|
||||||
|
case ATTRACTOR_SHELTER: SetObjective(OBJECTIVE_USE_SHELTER_ATTRACTOR, heading, pos); break;
|
||||||
|
case ATTRACTOR_ICECREAM: SetObjective(OBJECTIVE_USE_ICECREAM_ATTRACTOR, heading, pos); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
SetObjectiveTimer(time);
|
||||||
|
m_positionInQueue = qid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPed::ClearWaitState(void)
|
||||||
|
{
|
||||||
|
switch (m_nWaitState) {
|
||||||
|
case WAITSTATE_PLAYANIM_CHAT:
|
||||||
|
case WAITSTATE_SIT_DOWN:
|
||||||
|
case WAITSTATE_SIT_DOWN_RVRS:
|
||||||
|
case WAITSTATE_SIT_UP:
|
||||||
|
case WAITSTATE_SIT_IDLE:
|
||||||
|
case WAITSTATE_USE_ATM:
|
||||||
|
if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
|
||||||
|
AnimationId id;
|
||||||
|
switch (m_nWaitState) { // TODO(MIAMI): actual!
|
||||||
|
case WAITSTATE_PLAYANIM_CHAT: id = ANIM_IDLE_CHAT; break;
|
||||||
|
case WAITSTATE_SIT_DOWN: id = ANIM_SEAT_DOWN; break;
|
||||||
|
case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_SEAT_DOWN2; break;
|
||||||
|
case WAITSTATE_SIT_UP: id = ANIM_SEAT_UP; break;
|
||||||
|
case WAITSTATE_SIT_IDLE: id = ANIM_SEAT_IDLE; break;
|
||||||
|
case WAITSTATE_USE_ATM: id = ANIM_ATM; break;
|
||||||
|
}
|
||||||
|
CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id);
|
||||||
|
if (pAssoc)
|
||||||
|
pAssoc->blendDelta = -8.0f;
|
||||||
|
if (m_attractor)
|
||||||
|
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WAITSTATE_RIOT:
|
||||||
|
case WAITSTATE_FAST_FALL:
|
||||||
|
case WAITSTATE_BOMBER:
|
||||||
|
case WAITSTATE_STRIPPER:
|
||||||
|
case WAITSTATE_GROUND_ATTACK:
|
||||||
|
case WAITSTATE_LANCESITTING:
|
||||||
|
case WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
m_nWaitState = WAITSTATE_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef COMPATIBLE_SAVES
|
#ifdef COMPATIBLE_SAVES
|
||||||
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
|
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
|
||||||
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
|
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
|
||||||
|
|
|
@ -19,6 +19,7 @@ class CObject;
|
||||||
class CFire;
|
class CFire;
|
||||||
struct AnimBlendFrameData;
|
struct AnimBlendFrameData;
|
||||||
class CAnimBlendAssociation;
|
class CAnimBlendAssociation;
|
||||||
|
class CPedAttractor;
|
||||||
|
|
||||||
struct PedAudioData
|
struct PedAudioData
|
||||||
{
|
{
|
||||||
|
@ -148,12 +149,28 @@ enum eWaitState {
|
||||||
WAITSTATE_PLAYANIM_HANDSUP,
|
WAITSTATE_PLAYANIM_HANDSUP,
|
||||||
WAITSTATE_PLAYANIM_HANDSCOWER,
|
WAITSTATE_PLAYANIM_HANDSCOWER,
|
||||||
WAITSTATE_PLAYANIM_CHAT,
|
WAITSTATE_PLAYANIM_CHAT,
|
||||||
WAITSTATE_FINISH_FLEE
|
WAITSTATE_FINISH_FLEE,
|
||||||
|
WAITSTATE_SIT_DOWN,
|
||||||
|
WAITSTATE_SIT_DOWN_RVRS,
|
||||||
|
WAITSTATE_SIT_UP,
|
||||||
|
WAITSTATE_SIT_IDLE,
|
||||||
|
WAITSTATE_USE_ATM,
|
||||||
|
WAITSTATE_SUN_BATHE_PRE,
|
||||||
|
WAITSTATE_SUN_BATHE_DOWN,
|
||||||
|
WAITSTATE_SUN_BATHE_IDLE,
|
||||||
|
WAITSTATE_RIOT,
|
||||||
|
WAITSTATE_FAST_FALL,
|
||||||
|
WAITSTATE_BOMBER,
|
||||||
|
WAITSTATE_STRIPPER,
|
||||||
|
WAITSTATE_GROUND_ATTACK,
|
||||||
|
WAITSTATE_LANCESITTING,
|
||||||
|
WAITSTATE_PLAYANIM_HANDSUP_SIMPLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eObjective : uint32 {
|
enum eObjective : uint32 {
|
||||||
OBJECTIVE_NONE,
|
OBJECTIVE_NONE,
|
||||||
OBJECTIVE_IDLE,
|
OBJECTIVE_IDLE,
|
||||||
|
OBJ_2,
|
||||||
OBJECTIVE_FLEE_TILL_SAFE,
|
OBJECTIVE_FLEE_TILL_SAFE,
|
||||||
OBJECTIVE_GUARD_SPOT,
|
OBJECTIVE_GUARD_SPOT,
|
||||||
OBJECTIVE_GUARD_AREA, // not implemented
|
OBJECTIVE_GUARD_AREA, // not implemented
|
||||||
|
@ -165,6 +182,8 @@ enum eObjective : uint32 {
|
||||||
OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS,
|
OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS,
|
||||||
OBJECTIVE_GOTO_CHAR_ON_FOOT,
|
OBJECTIVE_GOTO_CHAR_ON_FOOT,
|
||||||
OBJECTIVE_FOLLOW_PED_IN_FORMATION,
|
OBJECTIVE_FOLLOW_PED_IN_FORMATION,
|
||||||
|
OBJ_14,
|
||||||
|
OBJ_15,
|
||||||
OBJECTIVE_LEAVE_VEHICLE,
|
OBJECTIVE_LEAVE_VEHICLE,
|
||||||
OBJECTIVE_ENTER_CAR_AS_PASSENGER,
|
OBJECTIVE_ENTER_CAR_AS_PASSENGER,
|
||||||
OBJECTIVE_ENTER_CAR_AS_DRIVER,
|
OBJECTIVE_ENTER_CAR_AS_DRIVER,
|
||||||
|
@ -175,8 +194,8 @@ enum eObjective : uint32 {
|
||||||
OBJECTIVE_GOTO_AREA_ANY_MEANS,
|
OBJECTIVE_GOTO_AREA_ANY_MEANS,
|
||||||
OBJECTIVE_GOTO_AREA_ON_FOOT,
|
OBJECTIVE_GOTO_AREA_ON_FOOT,
|
||||||
OBJECTIVE_RUN_TO_AREA,
|
OBJECTIVE_RUN_TO_AREA,
|
||||||
OBJECTIVE_23, // not implemented
|
OBJECTIVE_26, // not implemented
|
||||||
OBJECTIVE_24, // not implemented
|
OBJECTIVE_27, // not implemented
|
||||||
OBJECTIVE_FIGHT_CHAR,
|
OBJECTIVE_FIGHT_CHAR,
|
||||||
OBJECTIVE_SET_LEADER,
|
OBJECTIVE_SET_LEADER,
|
||||||
OBJECTIVE_FOLLOW_ROUTE,
|
OBJECTIVE_FOLLOW_ROUTE,
|
||||||
|
@ -185,11 +204,31 @@ enum eObjective : uint32 {
|
||||||
OBJECTIVE_CATCH_TRAIN,
|
OBJECTIVE_CATCH_TRAIN,
|
||||||
OBJECTIVE_BUY_ICE_CREAM,
|
OBJECTIVE_BUY_ICE_CREAM,
|
||||||
OBJECTIVE_STEAL_ANY_CAR,
|
OBJECTIVE_STEAL_ANY_CAR,
|
||||||
|
OBJ_36,
|
||||||
OBJECTIVE_MUG_CHAR,
|
OBJECTIVE_MUG_CHAR,
|
||||||
OBJECTIVE_FLEE_CAR,
|
OBJECTIVE_LEAVE_CAR_AND_DIE,
|
||||||
#ifdef VC_PED_PORTS
|
OBJECTIVE_USE_SEAT_ATTRACTOR,
|
||||||
OBJECTIVE_LEAVE_CAR_AND_DIE
|
OBJECTIVE_USE_ATM_ATTRACTOR,
|
||||||
#endif
|
OBJECTIVE_FLEE_CAR, // is it 41?
|
||||||
|
OBJ_42,
|
||||||
|
OBJECTIVE_USE_STOP_ATTRACTOR,
|
||||||
|
OBJECTIVE_USE_PIZZA_ATTRACTOR,
|
||||||
|
OBJECTIVE_USE_SHELTER_ATTRACTOR,
|
||||||
|
OBJ_46,
|
||||||
|
OBJ_47,
|
||||||
|
OBJECTIVE_WAIT_FOR_RAIN_TO_END,
|
||||||
|
OBJ_49,
|
||||||
|
OBJ_50,
|
||||||
|
OBJ_51,
|
||||||
|
OBJECTIVE_WAIT_FOR_BUS,
|
||||||
|
OBJECTIVE_USE_ICECREAM_ATTRACTOR,
|
||||||
|
OBJECTIVE_PURCHASE_ICECREAM,
|
||||||
|
OBJ_55,
|
||||||
|
OBJ_56,
|
||||||
|
OBJ_57,
|
||||||
|
OBJ_58,
|
||||||
|
OBJ_59
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -389,9 +428,12 @@ public:
|
||||||
uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator
|
uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator
|
||||||
uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle
|
uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle
|
||||||
|
|
||||||
uint32 bCarPassenger : 1;
|
uint32 bReachedAttractorHeadingTarget : 1; // 0x154 0x40
|
||||||
uint32 bMiamiViceCop : 1; //
|
uint32 bTurnedAroundOnAttractor : 1; // 0x154 0x80
|
||||||
uint32 bDeadPedInFrontOfCar : 1;
|
uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1
|
||||||
|
uint32 bCarPassenger : 1; // 0x155 0x4
|
||||||
|
uint32 bMiamiViceCop : 1; // 0x155 0x20
|
||||||
|
uint32 bDeadPedInFrontOfCar : 1; // 0x156 0x40
|
||||||
|
|
||||||
uint8 CharCreatedBy;
|
uint8 CharCreatedBy;
|
||||||
eObjective m_objective;
|
eObjective m_objective;
|
||||||
|
@ -399,6 +441,7 @@ public:
|
||||||
CPed *m_pedInObjective;
|
CPed *m_pedInObjective;
|
||||||
CVehicle *m_carInObjective;
|
CVehicle *m_carInObjective;
|
||||||
CVector m_nextRoutePointPos;
|
CVector m_nextRoutePointPos;
|
||||||
|
float m_attractorHeading;
|
||||||
CPed *m_leader;
|
CPed *m_leader;
|
||||||
eFormation m_pedFormation;
|
eFormation m_pedFormation;
|
||||||
uint32 m_fearFlags;
|
uint32 m_fearFlags;
|
||||||
|
@ -456,7 +499,9 @@ public:
|
||||||
CVehicle *m_pMyVehicle;
|
CVehicle *m_pMyVehicle;
|
||||||
bool bInVehicle;
|
bool bInVehicle;
|
||||||
float m_distanceToCountSeekDone;
|
float m_distanceToCountSeekDone;
|
||||||
|
float m_acceptableHeadingOffset;
|
||||||
|
CPedAttractor* m_attractor;
|
||||||
|
int32 m_positionInQueue;
|
||||||
CVehicle* m_vehicleInAccident;
|
CVehicle* m_vehicleInAccident;
|
||||||
|
|
||||||
bool bRunningToPhone;
|
bool bRunningToPhone;
|
||||||
|
@ -598,6 +643,7 @@ public:
|
||||||
void SetObjective(eObjective, int16, int16);
|
void SetObjective(eObjective, int16, int16);
|
||||||
void SetObjective(eObjective, CVector);
|
void SetObjective(eObjective, CVector);
|
||||||
void SetObjective(eObjective, CVector, float);
|
void SetObjective(eObjective, CVector, float);
|
||||||
|
void SetObjective(eObjective, float, const CVector&);
|
||||||
void ClearChat(void);
|
void ClearChat(void);
|
||||||
void InformMyGangOfAttack(CEntity*);
|
void InformMyGangOfAttack(CEntity*);
|
||||||
void ReactToAttack(CEntity*);
|
void ReactToAttack(CEntity*);
|
||||||
|
@ -816,8 +862,11 @@ public:
|
||||||
bool CanPedJumpThis(CEntity*);
|
bool CanPedJumpThis(CEntity*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int);
|
||||||
|
void ClearWaitState(void);
|
||||||
|
|
||||||
bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; }
|
bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; }
|
||||||
CWeapon &GetWeapon(uint8 slot) { return m_weapons[slot]; }
|
CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; }
|
||||||
CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
|
CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
|
||||||
|
|
||||||
PedState GetPedState(void) { return m_nPedState; }
|
PedState GetPedState(void) { return m_nPedState; }
|
||||||
|
@ -830,6 +879,12 @@ public:
|
||||||
bool Driving(void) { return m_nPedState == PED_DRIVING; }
|
bool Driving(void) { return m_nPedState == PED_DRIVING; }
|
||||||
bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.
|
bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.
|
||||||
bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }
|
bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }
|
||||||
|
bool HasAttractor(void) { return m_attractor != nil; }
|
||||||
|
bool IsUseAttractorObjective(eObjective obj) {
|
||||||
|
return obj == OBJECTIVE_USE_ATM_ATTRACTOR || obj == OBJECTIVE_USE_ICECREAM_ATTRACTOR ||
|
||||||
|
obj == OBJECTIVE_USE_PIZZA_ATTRACTOR || obj == OBJECTIVE_USE_SEAT_ATTRACTOR ||
|
||||||
|
obj == OBJECTIVE_USE_SHELTER_ATTRACTOR || obj == OBJECTIVE_USE_STOP_ATTRACTOR;
|
||||||
|
}
|
||||||
|
|
||||||
void ReplaceWeaponWhenExitingVehicle(void);
|
void ReplaceWeaponWhenExitingVehicle(void);
|
||||||
void RemoveWeaponWhenEnteringVehicle(void);
|
void RemoveWeaponWhenEnteringVehicle(void);
|
||||||
|
|
779
src/peds/PedAttactor.cpp
Normal file
779
src/peds/PedAttactor.cpp
Normal file
|
@ -0,0 +1,779 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "PedAttractor.h"
|
||||||
|
|
||||||
|
#include "General.h"
|
||||||
|
#include "Vehicle.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
const int gcMaxSizeOfAtmQueue = 1;
|
||||||
|
const int gcMaxSizeOfSeatQueue = 1;
|
||||||
|
const int gcMaxSizeOfStopQueue = 5;
|
||||||
|
const int gcMaxSizeOfPizzaQueue = 5;
|
||||||
|
const int gcMaxSizeOfShelterQueue = 5;
|
||||||
|
const int gcMaxSizeOfIceCreamQueue = 1;
|
||||||
|
|
||||||
|
//--MIAMI: file done, except TODO(MIAMI)
|
||||||
|
|
||||||
|
std::vector<CVector> CPedShelterAttractor::ms_displacements;
|
||||||
|
|
||||||
|
CPedAttractorManager* GetPedAttractorManager()
|
||||||
|
{
|
||||||
|
static CPedAttractorManager manager;
|
||||||
|
return &manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVehicleToEffect::CVehicleToEffect(CVehicle* pVehicle) : m_pVehicle(pVehicle)
|
||||||
|
{
|
||||||
|
m_effects[1].col = CRGBA(0, 0, 0, 0);
|
||||||
|
m_effects[1].type = EFFECT_PED_ATTRACTOR;
|
||||||
|
m_effects[1].pos = CVector(2.0f, 1.0f, 0.0f);
|
||||||
|
m_effects[1].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[1].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[1].pedattr.type = ATTRACTOR_ICECREAM;
|
||||||
|
|
||||||
|
m_effects[3].col = CRGBA(0, 0, 0, 0);
|
||||||
|
m_effects[3].type = EFFECT_PED_ATTRACTOR;
|
||||||
|
m_effects[3].pos = CVector(2.0f, -0.5f, 0.0f);
|
||||||
|
m_effects[3].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[3].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[3].pedattr.type = ATTRACTOR_ICECREAM;
|
||||||
|
|
||||||
|
m_effects[0].col = CRGBA(0, 0, 0, 0);
|
||||||
|
m_effects[0].type = EFFECT_PED_ATTRACTOR;
|
||||||
|
m_effects[0].pos = CVector(-2.0f, 1.0f, 0.0f);
|
||||||
|
m_effects[0].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[0].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[0].pedattr.type = ATTRACTOR_ICECREAM;
|
||||||
|
|
||||||
|
m_effects[2].col = CRGBA(0, 0, 0, 0);
|
||||||
|
m_effects[2].type = EFFECT_PED_ATTRACTOR;
|
||||||
|
m_effects[2].pos = CVector(-2.0f, -0.5f, 0.0f);
|
||||||
|
m_effects[2].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[2].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);
|
||||||
|
m_effects[2].pedattr.type = ATTRACTOR_ICECREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVehicleToEffect& CVehicleToEffect::From(const CVehicleToEffect& other)
|
||||||
|
{
|
||||||
|
m_pVehicle = other.m_pVehicle;
|
||||||
|
for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {
|
||||||
|
m_effects[i].col = other.m_effects[i].col;
|
||||||
|
m_effects[i].type = other.m_effects[i].type;
|
||||||
|
m_effects[i].pos = other.m_effects[i].pos;
|
||||||
|
m_effects[i].pedattr = other.m_effects[i].pedattr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const C2dEffect* CVehicleToEffect::ChooseEffect(const CVector& pos) const
|
||||||
|
{
|
||||||
|
if (!m_pVehicle)
|
||||||
|
return nil;
|
||||||
|
if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetRight()) > 0.0f) {
|
||||||
|
if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)
|
||||||
|
return &m_effects[0];
|
||||||
|
else
|
||||||
|
return &m_effects[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)
|
||||||
|
return &m_effects[1];
|
||||||
|
else
|
||||||
|
return &m_effects[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CVehicleToEffect::HasThisEffect(C2dEffect* pEffect) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {
|
||||||
|
if (pEffect == &m_effects[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos)
|
||||||
|
{
|
||||||
|
if (!vVehicleToEffect.empty()) {
|
||||||
|
for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) {
|
||||||
|
if (assoc->GetVehicle() == pVehicle)
|
||||||
|
return assoc->ChooseEffect(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CVehicleToEffect effect(pVehicle);
|
||||||
|
vVehicleToEffect.push_back(effect);
|
||||||
|
return effect.ChooseEffect(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect)
|
||||||
|
{
|
||||||
|
if (vVehicleToEffect.empty())
|
||||||
|
return false;
|
||||||
|
for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend(); ++assoc) {
|
||||||
|
if (assoc->HasThisEffect(pEffect))
|
||||||
|
return assoc->GetVehicle();
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (vecAttractors.empty())
|
||||||
|
return nil;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator attractor = vecAttractors.cbegin(); attractor != vecAttractors.cend(); ++attractor) {
|
||||||
|
if ((*attractor)->GetEffect() == pEffect)
|
||||||
|
return *attractor;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect)
|
||||||
|
{
|
||||||
|
CVehicle* pVehicle = GetIceCreamVanForEffect(pEffect);
|
||||||
|
if (!pVehicle)
|
||||||
|
return;
|
||||||
|
if (vVehicleToEffect.empty())
|
||||||
|
return;
|
||||||
|
for (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) {
|
||||||
|
if (assoc->GetVehicle() != pVehicle)
|
||||||
|
return;
|
||||||
|
size_t total = 0;
|
||||||
|
for (size_t j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) {
|
||||||
|
if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors))
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
if (total > 0)
|
||||||
|
assoc++;
|
||||||
|
else
|
||||||
|
assoc = vVehicleToEffect.erase(assoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
p2dEffect(pEffect),
|
||||||
|
m_nMaxPedsInAttractor(maxpeds),
|
||||||
|
m_fQueueDistance(qdist),
|
||||||
|
m_fTimeInWaitQueue(waitTime),
|
||||||
|
m_fTimeInApproachingQueue(approachTime),
|
||||||
|
m_fDistanceToUseAttractor(distance),
|
||||||
|
m_fAcceptableHeading(headingdiff),
|
||||||
|
m_fMaxPositionDisplacement(posdisp),
|
||||||
|
m_fMaxHeadingDisplacement(headdisp)
|
||||||
|
{
|
||||||
|
CPedAttractorManager::ComputeEffectPos(pEffect, matrix, vecEffectPos);
|
||||||
|
CPedAttractorManager::ComputeEffectQueueDir(pEffect, matrix, vecQueueDir);
|
||||||
|
CPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedPizzaAttractor::UpdatePedStateOnDeparture(CPed* pPed) const
|
||||||
|
{
|
||||||
|
/* TODO(MIAMI): uncomment
|
||||||
|
if (pPed->m_nPedMoney > 10)
|
||||||
|
pPed->m_nPedMoney -= 10;
|
||||||
|
else
|
||||||
|
pPed->m_nPedMoney = 0;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAtmAttractor::UpdatePedStateOnDeparture(CPed* pPed) const
|
||||||
|
{
|
||||||
|
/* TODO(MIAMI): uncomment
|
||||||
|
pPed->m_nPedMoney += 20 * CGeneral::GetRandomNumberInRange(1, 51);
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
float CPedAttractor::ComputeDeltaHeading() const
|
||||||
|
{
|
||||||
|
return CGeneral::GetRandomNumberInRange(-m_fMaxHeadingDisplacement, m_fMaxHeadingDisplacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CPedAttractor::ComputeDeltaPos() const
|
||||||
|
{
|
||||||
|
return CGeneral::GetRandomNumberInRange(-m_fMaxPositionDisplacement, m_fMaxPositionDisplacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractor::ComputeAttractTime(int32 id, bool approacher, float& time) const
|
||||||
|
{
|
||||||
|
if (approacher)
|
||||||
|
time = m_fTimeInApproachingQueue;
|
||||||
|
else
|
||||||
|
time = m_fTimeInWaitQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const
|
||||||
|
{
|
||||||
|
if (!p2dEffect)
|
||||||
|
return;
|
||||||
|
pos = vecEffectPos - qid * vecQueueDir * m_fQueueDistance;
|
||||||
|
if (qid != 0) {
|
||||||
|
pos.x += ComputeDeltaPos();
|
||||||
|
pos.y += ComputeDeltaPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector CPedShelterAttractor::GetDisplacement(int32 qid) const
|
||||||
|
{
|
||||||
|
if (ms_displacements.empty()) {
|
||||||
|
int i = 0;
|
||||||
|
while (i < gcMaxSizeOfShelterQueue) {
|
||||||
|
float fRandomAngle = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);
|
||||||
|
float fRandomOffset = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);
|
||||||
|
CVector vecDisplacement(fRandomOffset * Sin(fRandomAngle), fRandomOffset * Cos(fRandomAngle), 0.0f);
|
||||||
|
bool close = false;
|
||||||
|
for (std::vector<CVector>::const_iterator v = ms_displacements.cbegin(); v != ms_displacements.cend(); ++v) {
|
||||||
|
if ((*v - vecDisplacement).Magnitude() < 1.0f) {
|
||||||
|
close = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!close) {
|
||||||
|
ms_displacements.push_back(vecDisplacement);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ms_displacements[qid];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedShelterAttractor::ComputeAttractPos(int32 qid, CVector& pos) const
|
||||||
|
{
|
||||||
|
if (!p2dEffect)
|
||||||
|
return;
|
||||||
|
pos = vecEffectPos + GetDisplacement(qid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractor::ComputeAttractHeading(int32 qid, float& heading) const
|
||||||
|
{
|
||||||
|
heading = CGeneral::GetRadianAngleBetweenPoints(qid != 0 ? vecQueueDir.x : vecUseDir.x, qid != 0 ? vecQueueDir.y : vecUseDir.y, 0.0f, 0.0f);
|
||||||
|
if (qid != 0)
|
||||||
|
heading += ComputeDeltaHeading();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedShelterAttractor::ComputeAttractHeading(int32 qid, float& heading) const
|
||||||
|
{
|
||||||
|
heading = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::RegisterPed(CPed* pPed)
|
||||||
|
{
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed) {
|
||||||
|
vApproachingQueue.erase(pPedIt);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GetNoOfRegisteredPeds() >= m_nMaxPedsInAttractor)
|
||||||
|
return 0;
|
||||||
|
vApproachingQueue.push_back(pPed);
|
||||||
|
CVector pos;
|
||||||
|
float heading;
|
||||||
|
float time;
|
||||||
|
int32 slot = ComputeFreeSlot();
|
||||||
|
ComputeAttractPos(slot, pos);
|
||||||
|
ComputeAttractHeading(slot, heading);
|
||||||
|
ComputeAttractTime(slot, false, time);
|
||||||
|
pPed->SetNewAttraction(this, pos, heading, time, slot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ATTRACTOR_ATM:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_ATM_ATTRACTOR)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ATTRACTOR_SEAT:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_SEAT_ATTRACTOR)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ATTRACTOR_STOP:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_BUS || pPed->m_objective == OBJECTIVE_IDLE)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ATTRACTOR_PIZZA:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_PIZZA_ATTRACTOR || pPed->m_objective == OBJECTIVE_IDLE)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ATTRACTOR_SHELTER:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJECTIVE_WAIT_FOR_RAIN_TO_END)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ATTRACTOR_ICECREAM:
|
||||||
|
if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJECTIVE_PURCHASE_ICECREAM)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::DeRegisterPed(CPed* pPed)
|
||||||
|
{
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt != pPed)
|
||||||
|
continue;
|
||||||
|
pPed->m_attractor = nil;
|
||||||
|
pPed->m_positionInQueue = -1;
|
||||||
|
pPed->bHasAlreadyUsedAttractor = true;
|
||||||
|
|
||||||
|
if (IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed))
|
||||||
|
pPed->SetObjective(OBJECTIVE_NONE);
|
||||||
|
else if (pPed->GetPedState() != PED_IDLE && pPed->GetPedState() != PED_NONE) {
|
||||||
|
vApproachingQueue.erase(pPedIt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||||
|
vApproachingQueue.erase(pPedIt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return BroadcastDeparture(pPed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::BroadcastArrival(CPed* pPed)
|
||||||
|
{
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vWaitingQueue.push_back(pPed);
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed) {
|
||||||
|
vApproachingQueue.erase(pPedIt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
|
||||||
|
CPed* pPed = *pPedIt;
|
||||||
|
CVector pos;
|
||||||
|
float heading;
|
||||||
|
float time;
|
||||||
|
int32 slot = ComputeFreeSlot();
|
||||||
|
ComputeAttractPos(slot, pos);
|
||||||
|
ComputeAttractHeading(slot, heading);
|
||||||
|
ComputeAttractTime(slot, false, time);
|
||||||
|
pPed->SetNewAttraction(this, pos, heading, time, slot);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::BroadcastDeparture(CPed* pPed)
|
||||||
|
{
|
||||||
|
int qid = -1;
|
||||||
|
for (size_t i = 0; i < vWaitingQueue.size(); i++){
|
||||||
|
if (vWaitingQueue[i] == pPed)
|
||||||
|
qid = i;
|
||||||
|
}
|
||||||
|
if (qid < 0)
|
||||||
|
return false;
|
||||||
|
for (size_t i = qid + 1; i < vWaitingQueue.size(); i++) {
|
||||||
|
CVector pos;
|
||||||
|
float heading;
|
||||||
|
float time;
|
||||||
|
ComputeAttractPos(i - 1, pos);
|
||||||
|
ComputeAttractHeading(i - 1, heading);
|
||||||
|
ComputeAttractTime(i - 1, true, time);
|
||||||
|
pPed->SetNewAttraction(this, pos, heading, time, i - 1);
|
||||||
|
}
|
||||||
|
pPed->m_attractor = nil;
|
||||||
|
pPed->m_positionInQueue = -1;
|
||||||
|
pPed->bHasAlreadyUsedAttractor = true;
|
||||||
|
if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {
|
||||||
|
if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||||
|
}
|
||||||
|
else if (qid == 0)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));
|
||||||
|
else if (qid == vWaitingQueue.size() - 1)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||||
|
else
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z));
|
||||||
|
vWaitingQueue.erase(vWaitingQueue.cbegin() + qid);
|
||||||
|
for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
|
||||||
|
CPed* pPed = *pPedIt;
|
||||||
|
CVector pos;
|
||||||
|
float heading;
|
||||||
|
float time;
|
||||||
|
int32 slot = ComputeFreeSlot();
|
||||||
|
ComputeAttractPos(slot, pos);
|
||||||
|
ComputeAttractHeading(slot, heading);
|
||||||
|
ComputeAttractTime(slot, false, time);
|
||||||
|
pPed->SetNewAttraction(this, pos, heading, time, slot);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed)
|
||||||
|
{
|
||||||
|
int qid = -1;
|
||||||
|
for (size_t i = 0; i < vWaitingQueue.size(); i++) {
|
||||||
|
if (vWaitingQueue[i] == pPed)
|
||||||
|
qid = i;
|
||||||
|
}
|
||||||
|
if (qid < 0)
|
||||||
|
return false;
|
||||||
|
pPed->m_attractor = nil;
|
||||||
|
pPed->m_positionInQueue = -1;
|
||||||
|
pPed->bHasAlreadyUsedAttractor = true;
|
||||||
|
if (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {
|
||||||
|
if (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||||
|
}
|
||||||
|
else if (qid == 0)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));
|
||||||
|
else if (qid == vWaitingQueue.size() - 1)
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||||
|
else
|
||||||
|
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.z));
|
||||||
|
vWaitingQueue.erase(vWaitingQueue.cbegin() + qid);
|
||||||
|
for (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {
|
||||||
|
CPed* pPed = *pPedIt;
|
||||||
|
CVector pos;
|
||||||
|
float heading;
|
||||||
|
float time;
|
||||||
|
int32 slot = ComputeFreeSlot();
|
||||||
|
ComputeAttractPos(slot, pos);
|
||||||
|
ComputeAttractHeading(slot, heading);
|
||||||
|
ComputeAttractTime(slot, false, time);
|
||||||
|
pPed->SetNewAttraction(this, pos, heading, time, slot);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::IsRegisteredWithPed(CPed* pPed) const
|
||||||
|
{
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.cbegin(); pPedIt != vApproachingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractor::IsInQueue(CPed* pPed) const
|
||||||
|
{
|
||||||
|
for (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.cbegin(); pPedIt != vWaitingQueue.cend(); ++pPedIt) {
|
||||||
|
if (*pPedIt == pPed)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPedAttractor* CPedAttractorManager::RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix)
|
||||||
|
{
|
||||||
|
if (pEffect->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pEffect->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return RegisterPed(pPed, pEffect, matrix, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return RegisterPed(pPed, pEffect, matrix, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return RegisterPed(pPed, pEffect, matrix, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return RegisterPed(pPed, pEffect, matrix, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return RegisterPed(pPed, pEffect, matrix, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return RegisterPed(pPed, pEffect, matrix, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (!IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return DeRegisterPed(pPed, pAttractor, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return DeRegisterPed(pPed, pAttractor, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return DeRegisterPed(pPed, pAttractor, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return DeRegisterPed(pPed, pAttractor, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return DeRegisterPed(pPed, pAttractor, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (!IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return BroadcastArrival(pPed, pAttractor, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return BroadcastArrival(pPed, pAttractor, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return BroadcastArrival(pPed, pAttractor, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return BroadcastArrival(pPed, pAttractor, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return BroadcastArrival(pPed, pAttractor, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return BroadcastArrival(pPed, pAttractor, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (!IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return BroadcastDeparture(pPed, pAttractor, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return BroadcastDeparture(pPed, pAttractor, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return BroadcastDeparture(pPed, pAttractor, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return BroadcastDeparture(pPed, pAttractor, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return BroadcastDeparture(pPed, pAttractor, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return BroadcastDeparture(pPed, pAttractor, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (!IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return IsAtHeadOfQueue(pPed, pAttractor, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return IsAtHeadOfQueue(pPed, pAttractor, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return IsAtHeadOfQueue(pPed, pAttractor, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return IsAtHeadOfQueue(pPed, pAttractor, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return IsAtHeadOfQueue(pPed, pAttractor, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
if (!IsPedRegisteredWithEffect(pPed))
|
||||||
|
return nil;
|
||||||
|
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: return IsInQueue(pPed, pAttractor, vAtmAttractors);
|
||||||
|
case ATTRACTOR_SEAT: return IsInQueue(pPed, pAttractor, vSeatAttractors);
|
||||||
|
case ATTRACTOR_STOP: return IsInQueue(pPed, pAttractor, vStopAttractors);
|
||||||
|
case ATTRACTOR_PIZZA: return IsInQueue(pPed, pAttractor, vPizzaAttractors);
|
||||||
|
case ATTRACTOR_SHELTER: return IsInQueue(pPed, pAttractor, vShelterAttractors);
|
||||||
|
case ATTRACTOR_ICECREAM: return IsInQueue(pPed, pAttractor, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::HasEmptySlot(const C2dEffect* pEffect)
|
||||||
|
{
|
||||||
|
if (!pEffect)
|
||||||
|
return false;
|
||||||
|
if (pEffect->type != EFFECT_PED_ATTRACTOR)
|
||||||
|
return nil;
|
||||||
|
const CPedAttractor* pAttractor;
|
||||||
|
switch (pEffect->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: pAttractor = FindAssociatedAttractor(pEffect, vAtmAttractors); break;
|
||||||
|
case ATTRACTOR_SEAT: pAttractor = FindAssociatedAttractor(pEffect, vSeatAttractors); break;
|
||||||
|
case ATTRACTOR_STOP: pAttractor = FindAssociatedAttractor(pEffect, vStopAttractors); break;
|
||||||
|
case ATTRACTOR_PIZZA: pAttractor = FindAssociatedAttractor(pEffect, vPizzaAttractors); break;
|
||||||
|
case ATTRACTOR_SHELTER: pAttractor = FindAssociatedAttractor(pEffect, vShelterAttractors); break;
|
||||||
|
case ATTRACTOR_ICECREAM: pAttractor = FindAssociatedAttractor(pEffect, vIceCreamAttractors); break;
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
if (!pAttractor)
|
||||||
|
return true;
|
||||||
|
return pAttractor->GetNoOfRegisteredPeds() < pAttractor->GetMaxPedsInAttractor();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed)
|
||||||
|
{
|
||||||
|
return IsPedRegistered(pPed, vAtmAttractors) ||
|
||||||
|
IsPedRegistered(pPed, vSeatAttractors) ||
|
||||||
|
IsPedRegistered(pPed, vStopAttractors) ||
|
||||||
|
IsPedRegistered(pPed, vPizzaAttractors) ||
|
||||||
|
IsPedRegistered(pPed, vShelterAttractors) ||
|
||||||
|
IsPedRegistered(pPed, vIceCreamAttractors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractorManager::ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
|
||||||
|
{
|
||||||
|
pos = matrix.GetPosition() + Multiply3x3(matrix, pEffect->pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractorManager::ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
|
||||||
|
{
|
||||||
|
pos = Multiply3x3(matrix, pEffect->pedattr.queueDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPedAttractorManager::ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
|
||||||
|
{
|
||||||
|
pos = Multiply3x3(matrix, pEffect->pedattr.useDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
CPedAttractor* pRegisteredAttractor = nil;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
CPedAttractor* pAttractor = *pAttractorIt;
|
||||||
|
CVector vEffectPos;
|
||||||
|
ComputeEffectPos(pAttractor->GetEffect(), matrix, vEffectPos);
|
||||||
|
if (pAttractor->GetEffect() == pEffect && vEffectPos == pAttractor->GetEffectPos()) {
|
||||||
|
if (!IsApproachable(pEffect, matrix, pAttractor->ComputeFreeSlot(), pPed))
|
||||||
|
return false;
|
||||||
|
pRegisteredAttractor = pAttractor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pRegisteredAttractor || !IsApproachable(pEffect, matrix, 0, pPed)) {
|
||||||
|
if (pRegisteredAttractor)
|
||||||
|
pRegisteredAttractor->RegisterPed(pPed);
|
||||||
|
return pRegisteredAttractor;
|
||||||
|
}
|
||||||
|
switch (pEffect->pedattr.type) {
|
||||||
|
case ATTRACTOR_ATM: vecAttractors.push_back(new CPedAtmAttractor(pEffect, matrix, gcMaxSizeOfAtmQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.15f, 0.1f, 0.1f)); break;
|
||||||
|
case ATTRACTOR_SEAT: vecAttractors.push_back(new CPedSeatAttractor(pEffect, matrix, gcMaxSizeOfSeatQueue, 1.0f, 30000.0f, 3000.0f, 0.125f, 0.1f, 0.1f, 0.1f)); break;
|
||||||
|
case ATTRACTOR_STOP: vecAttractors.push_back(new CPedStopAttractor(pEffect, matrix, gcMaxSizeOfStopQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break;
|
||||||
|
case ATTRACTOR_PIZZA: vecAttractors.push_back(new CPedPizzaAttractor(pEffect, matrix, gcMaxSizeOfPizzaQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f)); break;
|
||||||
|
case ATTRACTOR_SHELTER: vecAttractors.push_back(new CPedShelterAttractor(pEffect, matrix, gcMaxSizeOfShelterQueue, 1.0f, 30000.0f, 3000.0f, 0.5f, 6.28f, 0.1f, 0.1f)); break;
|
||||||
|
case ATTRACTOR_ICECREAM: vecAttractors.push_back(new CPedIceCreamAttractor(pEffect, matrix, gcMaxSizeOfIceCreamQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.3f, 0.1f, 0.1f)); break;
|
||||||
|
}
|
||||||
|
if (pRegisteredAttractor)
|
||||||
|
pRegisteredAttractor->RegisterPed(pPed);
|
||||||
|
return pRegisteredAttractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
CPedAttractor* pFound = nil;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
pFound = *pAttractorIt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pFound)
|
||||||
|
return false;
|
||||||
|
pFound->DeRegisterPed(pPed);
|
||||||
|
if (pFound->GetNoOfRegisteredPeds() != 0)
|
||||||
|
return true;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
vecAttractors.erase(pAttractorIt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete pAttractor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
CPedAttractor* pFound = nil;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
pFound = *pAttractorIt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pFound)
|
||||||
|
return false;
|
||||||
|
pFound->BroadcastArrival(pPed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
CPedAttractor* pFound = nil;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
pFound = *pAttractorIt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pFound)
|
||||||
|
return false;
|
||||||
|
pFound->DeRegisterPed(pPed);
|
||||||
|
if (pFound->GetNoOfRegisteredPeds() != 0)
|
||||||
|
return true;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
vecAttractors.erase(pAttractorIt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete pAttractor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
return (*pAttractorIt)->IsInQueue(pPed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
if (!pAttractor)
|
||||||
|
return false;
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if (*pAttractorIt == pAttractor) {
|
||||||
|
return (*pAttractorIt)->IsAtHeadOfQueue(pPed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors)
|
||||||
|
{
|
||||||
|
for (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.cbegin(); pAttractorIt != vecAttractors.cend(); ++pAttractorIt) {
|
||||||
|
if ((*pAttractorIt)->IsRegisteredWithPed(pPed))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed)
|
||||||
|
{
|
||||||
|
if (pEffect->pedattr.type == ATTRACTOR_SHELTER) {
|
||||||
|
CVector pos;
|
||||||
|
ComputeEffectPos(pEffect, matrix, pos);
|
||||||
|
return CWorld::GetIsLineOfSightClear(pPed->GetPosition(), pos, true, false, false, false, false, false);
|
||||||
|
}
|
||||||
|
CVector vecUseDir, vecEffectPos;
|
||||||
|
ComputeEffectUseDir(pEffect, matrix, vecUseDir);
|
||||||
|
ComputeEffectPos(pEffect, matrix, vecEffectPos);
|
||||||
|
float dp = -DotProduct(vecUseDir, vecEffectPos);
|
||||||
|
if (pEffect->pedattr.type == ATTRACTOR_ATM || pEffect->pedattr.type == ATTRACTOR_PIZZA || pEffect->pedattr.type == ATTRACTOR_ICECREAM) {
|
||||||
|
vecUseDir = -vecUseDir;
|
||||||
|
dp = -dp;
|
||||||
|
}
|
||||||
|
if (dp + DotProduct(vecEffectPos, pPed->GetPosition()) > 0.0f) {
|
||||||
|
CVector vecPedToAttractor = pPed->GetPosition() - vecEffectPos;
|
||||||
|
vecPedToAttractor.Normalise();
|
||||||
|
if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f && CWorld::IsWanderPathClear(pPed->GetPosition(), vecEffectPos, 2.0f, 0))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
196
src/peds/PedAttractor.h
Normal file
196
src/peds/PedAttractor.h
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
#pragma once
|
||||||
|
#include "common.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "2dEffect.h"
|
||||||
|
#include "Ped.h"
|
||||||
|
|
||||||
|
#define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4
|
||||||
|
|
||||||
|
class CPedAttractor;
|
||||||
|
|
||||||
|
class CVehicleToEffect
|
||||||
|
{
|
||||||
|
CVehicle* m_pVehicle;
|
||||||
|
C2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN];
|
||||||
|
|
||||||
|
public:
|
||||||
|
CVehicleToEffect(CVehicle* pVehicle);
|
||||||
|
const C2dEffect* ChooseEffect(const CVector& pos) const;
|
||||||
|
CVehicleToEffect& From(const CVehicleToEffect& other);
|
||||||
|
CVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); }
|
||||||
|
~CVehicleToEffect() { m_pVehicle = nil; }
|
||||||
|
CVehicle* GetVehicle() const { return m_pVehicle; }
|
||||||
|
bool HasThisEffect(C2dEffect* pEffect) const;
|
||||||
|
const C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedAttractorManager
|
||||||
|
{
|
||||||
|
std::vector<CPedAttractor*> vAtmAttractors;
|
||||||
|
std::vector<CPedAttractor*> vSeatAttractors;
|
||||||
|
std::vector<CPedAttractor*> vStopAttractors;
|
||||||
|
std::vector<CPedAttractor*> vPizzaAttractors;
|
||||||
|
std::vector<CPedAttractor*> vShelterAttractors;
|
||||||
|
std::vector<CPedAttractor*> vIceCreamAttractors;
|
||||||
|
std::vector<CVehicleToEffect> vVehicleToEffect;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix);
|
||||||
|
CPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor);
|
||||||
|
bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos);
|
||||||
|
bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed);
|
||||||
|
void RemoveIceCreamVanEffects(C2dEffect* pEffect);
|
||||||
|
bool HasEmptySlot(const C2dEffect* pEffect);
|
||||||
|
const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor);
|
||||||
|
bool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor);
|
||||||
|
bool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor);
|
||||||
|
bool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor);
|
||||||
|
bool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
bool IsPedRegisteredWithEffect(CPed* pPed);
|
||||||
|
bool IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors);
|
||||||
|
CVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect);
|
||||||
|
|
||||||
|
static void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
|
||||||
|
static void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
|
||||||
|
static void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
CPedAttractorManager* GetPedAttractorManager();
|
||||||
|
|
||||||
|
enum ePedAttractorType
|
||||||
|
{
|
||||||
|
ATTRACTOR_ATM = 0,
|
||||||
|
ATTRACTOR_SEAT,
|
||||||
|
ATTRACTOR_STOP,
|
||||||
|
ATTRACTOR_PIZZA,
|
||||||
|
ATTRACTOR_SHELTER,
|
||||||
|
ATTRACTOR_ICECREAM
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedAttractor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
C2dEffect* p2dEffect;
|
||||||
|
std::vector<CPed*> vApproachingQueue;
|
||||||
|
std::vector<CPed*> vWaitingQueue;
|
||||||
|
int32 m_nMaxPedsInAttractor;
|
||||||
|
float m_fQueueDistance;
|
||||||
|
float m_fTimeInWaitQueue;
|
||||||
|
float m_fTimeInApproachingQueue;
|
||||||
|
float m_fDistanceToUseAttractor;
|
||||||
|
float m_fAcceptableHeading;
|
||||||
|
float m_fMaxPositionDisplacement;
|
||||||
|
float m_fMaxHeadingDisplacement;
|
||||||
|
CVector vecEffectPos;
|
||||||
|
CVector vecQueueDir;
|
||||||
|
CVector vecUseDir;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual float GetHeadOfQueueWaitTime() { return 0.0f; }
|
||||||
|
virtual ~CPedAttractor() {};
|
||||||
|
virtual ePedAttractorType GetType() const = 0;
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0;
|
||||||
|
virtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; }
|
||||||
|
virtual void ComputeAttractPos(int32 id, CVector& pos) const;
|
||||||
|
virtual void ComputeAttractHeading(int32 id, float& pHeading) const;
|
||||||
|
virtual bool BroadcastDeparture(CPed* pPed);
|
||||||
|
|
||||||
|
bool IsRegisteredWithPed(CPed* pPed) const;
|
||||||
|
bool DeRegisterPed(CPed* pPed);
|
||||||
|
float ComputeDeltaHeading() const;
|
||||||
|
float ComputeDeltaPos() const;
|
||||||
|
void ComputeAttractTime(int32 id, bool, float& time) const;
|
||||||
|
int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); }
|
||||||
|
int32 ComputeFreeSlot() const { return vWaitingQueue.size(); }
|
||||||
|
bool IsInQueue(CPed*) const;
|
||||||
|
bool RegisterPed(CPed*);
|
||||||
|
bool BroadcastArrival(CPed*);
|
||||||
|
|
||||||
|
CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp);
|
||||||
|
|
||||||
|
C2dEffect* GetEffect() const { return p2dEffect; }
|
||||||
|
const CVector& GetEffectPos() const { return vecEffectPos; }
|
||||||
|
int32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; }
|
||||||
|
float GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; }
|
||||||
|
float GetAcceptableHeading() const { return m_fAcceptableHeading; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedAtmAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; };
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override;
|
||||||
|
CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedIceCreamAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~CPedIceCreamAttractor() override { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); }
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; }
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
|
||||||
|
CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedPizzaAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual float GetHeadOfQueueWaitTime() override { return 2000.0f; }
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_PIZZA; }
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override;
|
||||||
|
CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedSeatAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; }
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
|
||||||
|
CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedShelterAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
static std::vector<CVector> ms_displacements;
|
||||||
|
public:
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_SHELTER; }
|
||||||
|
virtual bool BroadcastDeparture(CPed*) override;
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
|
||||||
|
virtual bool IsAtHeadOfQueue(CPed* pPed) const override { return true; }
|
||||||
|
virtual void ComputeAttractPos(int qid, CVector& pos) const override;
|
||||||
|
virtual void ComputeAttractHeading(int qid, float& heading) const override;
|
||||||
|
|
||||||
|
CPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
|
CVector GetDisplacement(int32 qid) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPedStopAttractor : public CPedAttractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; }
|
||||||
|
virtual void UpdatePedStateOnDeparture(CPed* pPed) const override {};
|
||||||
|
|
||||||
|
CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :
|
||||||
|
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)
|
||||||
|
{};
|
||||||
|
};
|
|
@ -1123,7 +1123,8 @@ CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)
|
||||||
return nil;
|
return nil;
|
||||||
CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter
|
CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter
|
||||||
pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
|
pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
|
||||||
//TODO(MIAMI): set money == 0
|
//TODO(MIAMI): uncomment
|
||||||
|
//pPed->m_nPedMoney = 0;
|
||||||
pPed->bDeadPedInFrontOfCar = true;
|
pPed->bDeadPedInFrontOfCar = true;
|
||||||
pPed->m_vehicleInAccident = pCulprit;
|
pPed->m_vehicleInAccident = pCulprit;
|
||||||
pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident);
|
pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident);
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
enum {
|
enum {
|
||||||
EFFECT_LIGHT,
|
EFFECT_LIGHT,
|
||||||
EFFECT_PARTICLE,
|
EFFECT_PARTICLE,
|
||||||
EFFECT_ATTRACTOR
|
EFFECT_ATTRACTOR,
|
||||||
|
EFFECT_PED_ATTRACTOR
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -63,6 +64,11 @@ public:
|
||||||
uint8 flags;
|
uint8 flags;
|
||||||
uint8 probability;
|
uint8 probability;
|
||||||
};
|
};
|
||||||
|
struct PedAttractor {
|
||||||
|
CVector queueDir;
|
||||||
|
CVector useDir;
|
||||||
|
int8 type;
|
||||||
|
};
|
||||||
|
|
||||||
CVector pos;
|
CVector pos;
|
||||||
CRGBA col;
|
CRGBA col;
|
||||||
|
@ -71,6 +77,7 @@ public:
|
||||||
Light light;
|
Light light;
|
||||||
Particle particle;
|
Particle particle;
|
||||||
Attractor attractor;
|
Attractor attractor;
|
||||||
|
PedAttractor pedattr;
|
||||||
};
|
};
|
||||||
|
|
||||||
C2dEffect(void) {}
|
C2dEffect(void) {}
|
||||||
|
|
|
@ -143,7 +143,8 @@ CRenderer::RenderOneNonRoad(CEntity *e)
|
||||||
resetLights = e->SetupLighting();
|
resetLights = e->SetupLighting();
|
||||||
|
|
||||||
if(e->IsVehicle()){
|
if(e->IsVehicle()){
|
||||||
CVisibilityPlugins::SetupVehicleVariables(e->GetClump());
|
// unfortunately can't use GetClump here
|
||||||
|
CVisibilityPlugins::SetupVehicleVariables((RpClump*)e->m_rwObject);
|
||||||
CVisibilityPlugins::InitAlphaAtomicList();
|
CVisibilityPlugins::InitAlphaAtomicList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "DMAudio.h"
|
#include "DMAudio.h"
|
||||||
#include "General.h"
|
#include "General.h"
|
||||||
#include "Pad.h"
|
#include "Pad.h"
|
||||||
|
#include "PlayerPed.h"
|
||||||
#include "Particle.h"
|
#include "Particle.h"
|
||||||
#include "RenderBuffer.h"
|
#include "RenderBuffer.h"
|
||||||
#include "Stats.h"
|
#include "Stats.h"
|
||||||
|
@ -40,41 +41,60 @@ float CWeather::Rain;
|
||||||
float CWeather::InterpolationValue;
|
float CWeather::InterpolationValue;
|
||||||
float CWeather::WetRoads;
|
float CWeather::WetRoads;
|
||||||
float CWeather::Rainbow;
|
float CWeather::Rainbow;
|
||||||
|
float CWeather::SunGlare;
|
||||||
|
float CWeather::WindClipped;
|
||||||
|
float CWeather::TrafficLightBrightness;
|
||||||
|
|
||||||
bool CWeather::bScriptsForceRain;
|
bool CWeather::bScriptsForceRain;
|
||||||
bool CWeather::Stored_StateStored;
|
|
||||||
|
|
||||||
float CWeather::Stored_InterpolationValue;
|
|
||||||
int16 CWeather::Stored_OldWeatherType;
|
|
||||||
int16 CWeather::Stored_NewWeatherType;
|
|
||||||
float CWeather::Stored_Rain;
|
|
||||||
|
|
||||||
tRainStreak Streaks[NUM_RAIN_STREAKS];
|
tRainStreak Streaks[NUM_RAIN_STREAKS];
|
||||||
|
|
||||||
const int16 WeatherTypesList[] = {
|
const int16 WeatherTypesList[] = {
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
|
WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
|
||||||
WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
|
|
||||||
WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_CLOUDY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_CLOUDY,
|
WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY, WEATHER_CLOUDY,
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
|
||||||
|
};
|
||||||
|
|
||||||
|
const int16 WeatherTypesList_WithHurricanes[] = {
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
|
WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY,
|
||||||
|
WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_CLOUDY, WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_RAINY,
|
WEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE,
|
||||||
WEATHER_CLOUDY, WEATHER_RAINY, WEATHER_CLOUDY, WEATHER_SUNNY,
|
WEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,
|
||||||
WEATHER_SUNNY, WEATHER_FOGGY, WEATHER_FOGGY, WEATHER_SUNNY,
|
WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY
|
||||||
WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_RAINY, WEATHER_CLOUDY,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const float Windiness[] = {
|
const float Windiness[] = {
|
||||||
0.0f, // WEATHER_SUNNY
|
0.25f,// WEATHER_SUNNY
|
||||||
0.7f, // WEATHER_CLOUDY
|
0.7f, // WEATHER_CLOUDY
|
||||||
1.0f, // WEATHER_RAINY
|
1.0f, // WEATHER_RAINY
|
||||||
0.5f // WEATHER_FOGGY
|
0.0f, // WEATHER_FOGGY
|
||||||
|
0.0f, // WEATHER_EXTRA_SUNNY
|
||||||
|
2.0f, // WEATHER_HURRICANE
|
||||||
|
0.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)
|
#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)
|
||||||
|
@ -105,10 +125,9 @@ const float Windiness[] = {
|
||||||
|
|
||||||
void CWeather::Init(void)
|
void CWeather::Init(void)
|
||||||
{
|
{
|
||||||
NewWeatherType = WEATHER_SUNNY;
|
NewWeatherType = WEATHER_EXTRA_SUNNY;
|
||||||
bScriptsForceRain = false;
|
bScriptsForceRain = false;
|
||||||
OldWeatherType = WEATHER_CLOUDY;
|
OldWeatherType = WEATHER_EXTRA_SUNNY;
|
||||||
Stored_StateStored = false;
|
|
||||||
InterpolationValue = 0.0f;
|
InterpolationValue = 0.0f;
|
||||||
WhenToPlayLightningSound = 0;
|
WhenToPlayLightningSound = 0;
|
||||||
WeatherTypeInList = 0;
|
WeatherTypeInList = 0;
|
||||||
|
@ -128,16 +147,8 @@ void CWeather::Update(void)
|
||||||
NewWeatherType = ForcedWeatherType;
|
NewWeatherType = ForcedWeatherType;
|
||||||
else {
|
else {
|
||||||
WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);
|
WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);
|
||||||
NewWeatherType = WeatherTypesList[WeatherTypeInList];
|
NewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList];
|
||||||
#ifdef FIX_BUGS
|
|
||||||
}
|
}
|
||||||
if (NewWeatherType == WEATHER_RAINY)
|
|
||||||
CStats::mmRain += CGeneral::GetRandomNumber() & 7;
|
|
||||||
#else
|
|
||||||
if (NewWeatherType == WEATHER_RAINY)
|
|
||||||
CStats::mmRain += CGeneral::GetRandomNumber() & 7;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
InterpolationValue = fNewInterpolation;
|
InterpolationValue = fNewInterpolation;
|
||||||
if (CPad::GetPad(1)->GetRightShockJustDown()) {
|
if (CPad::GetPad(1)->GetRightShockJustDown()) {
|
||||||
|
@ -189,14 +200,14 @@ void CWeather::Update(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wet roads
|
// Wet roads
|
||||||
if (OldWeatherType == WEATHER_RAINY) {
|
if (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) {
|
||||||
if (NewWeatherType == WEATHER_RAINY)
|
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
|
||||||
WetRoads = 1.0f;
|
WetRoads = 1.0f;
|
||||||
else
|
else
|
||||||
WetRoads = 1.0f - InterpolationValue;
|
WetRoads = 1.0f - InterpolationValue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NewWeatherType == WEATHER_RAINY)
|
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)
|
||||||
WetRoads = InterpolationValue;
|
WetRoads = InterpolationValue;
|
||||||
else
|
else
|
||||||
WetRoads = 0.0f;
|
WetRoads = 0.0f;
|
||||||
|
@ -204,10 +215,10 @@ void CWeather::Update(void)
|
||||||
|
|
||||||
// Rain
|
// Rain
|
||||||
float fNewRain;
|
float fNewRain;
|
||||||
if (NewWeatherType == WEATHER_RAINY) {
|
if (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {
|
||||||
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
|
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
|
||||||
fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
|
fNewRain = ((uint16)CTimer::GetTimeInMilliseconds() >> 14) * 0.33f;
|
||||||
if (OldWeatherType != WEATHER_RAINY) {
|
if (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {
|
||||||
if (InterpolationValue < 0.4f)
|
if (InterpolationValue < 0.4f)
|
||||||
// if rain has just started (<24 minutes), always 0.5
|
// if rain has just started (<24 minutes), always 0.5
|
||||||
fNewRain = 0.5f;
|
fNewRain = 0.5f;
|
||||||
|
@ -218,19 +229,14 @@ void CWeather::Update(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fNewRain = 0.0f;
|
fNewRain = 0.0f;
|
||||||
if (Rain != fNewRain) { // ok to use comparasion
|
Rain = fNewRain;
|
||||||
if (Rain < fNewRain)
|
|
||||||
Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
|
|
||||||
else
|
|
||||||
Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
if (OldWeatherType != WEATHER_SUNNY)
|
if (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
|
||||||
CloudCoverage = 1.0f - InterpolationValue;
|
CloudCoverage = 1.0f - InterpolationValue;
|
||||||
else
|
else
|
||||||
CloudCoverage = 0.0f;
|
CloudCoverage = 0.0f;
|
||||||
if (NewWeatherType != WEATHER_SUNNY)
|
if (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)
|
||||||
CloudCoverage += InterpolationValue;
|
CloudCoverage += InterpolationValue;
|
||||||
|
|
||||||
// Fog
|
// Fog
|
||||||
|
@ -240,12 +246,76 @@ void CWeather::Update(void)
|
||||||
Foggyness = 0.0f;
|
Foggyness = 0.0f;
|
||||||
if (NewWeatherType == WEATHER_FOGGY)
|
if (NewWeatherType == WEATHER_FOGGY)
|
||||||
Foggyness += InterpolationValue;
|
Foggyness += InterpolationValue;
|
||||||
if (OldWeatherType == WEATHER_RAINY && NewWeatherType == WEATHER_SUNNY && InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)
|
|
||||||
|
// Extra Sunnyness
|
||||||
|
if (OldWeatherType == WEATHER_EXTRA_SUNNY)
|
||||||
|
ExtraSunnyness = 1.0f - InterpolationValue;
|
||||||
|
else
|
||||||
|
ExtraSunnyness = 0.0f;
|
||||||
|
if (NewWeatherType == WEATHER_EXTRA_SUNNY)
|
||||||
|
ExtraSunnyness += InterpolationValue;
|
||||||
|
|
||||||
|
// Rainbow
|
||||||
|
if (OldWeatherType == WEATHER_RAINY && (NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&
|
||||||
|
InterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)
|
||||||
Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f;
|
Rainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f;
|
||||||
else
|
else
|
||||||
Rainbow = 0.0f;
|
Rainbow = 0.0f;
|
||||||
|
|
||||||
|
// Sun Glare
|
||||||
|
if (OldWeatherType == WEATHER_EXTRA_SUNNY)
|
||||||
|
SunGlare = 1.0f - InterpolationValue;
|
||||||
|
else
|
||||||
|
SunGlare = 0.0f;
|
||||||
|
if (NewWeatherType == WEATHER_EXTRA_SUNNY)
|
||||||
|
SunGlare += InterpolationValue;
|
||||||
|
|
||||||
|
if (SunGlare > 0.0f) {
|
||||||
|
SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunPosition().z);
|
||||||
|
SunGlare = clamp(SunGlare, 0.0f, 1.0f);
|
||||||
|
// TODO(MIAMI): if (CSpecialFX::bSnapShotActive)...
|
||||||
|
}
|
||||||
|
|
||||||
Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
|
Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
|
||||||
|
WindClipped = Max(1.0f, Wind);
|
||||||
|
|
||||||
|
if (CClock::GetHours() == 20)
|
||||||
|
TrafficLightBrightness = CClock::GetMinutes() / 60.0f;
|
||||||
|
else if (CClock::GetHours() > 6 && CClock::GetHours() < 20)
|
||||||
|
TrafficLightBrightness = 0.0f;
|
||||||
|
else if (CClock::GetHours() == 6)
|
||||||
|
TrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f;
|
||||||
|
else
|
||||||
|
TrafficLightBrightness = 1.0f;
|
||||||
|
TrafficLightBrightness = Max(WetRoads, TrafficLightBrightness);
|
||||||
|
TrafficLightBrightness = Max(Rain, TrafficLightBrightness);
|
||||||
|
|
||||||
AddRain();
|
AddRain();
|
||||||
|
|
||||||
|
if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&
|
||||||
|
!CGame::IsInInterior() && !CCutsceneMgr::IsRunning() && (CTimer::GetFrameCounter() & 7) == 0) {
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
if (FindPlayerPed() && (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&
|
||||||
|
CClock::GetHours() > 6 && CClock::GetHours() < 18))
|
||||||
|
#else
|
||||||
|
if (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&
|
||||||
|
CClock::GetHours() > 6 && CClock::GetHours() < 18)
|
||||||
|
#endif
|
||||||
|
AddHeatHaze();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && !CGame::IsInInterior() && !CCutsceneMgr::IsRunning())
|
||||||
|
AddBeastie();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWeather::AddHeatHaze()
|
||||||
|
{
|
||||||
|
/* TODO(MIAMI) */
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWeather::AddBeastie()
|
||||||
|
{
|
||||||
|
/* TODO(MIAMI) */
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWeather::ForceWeather(int16 weather)
|
void CWeather::ForceWeather(int16 weather)
|
||||||
|
@ -511,23 +581,3 @@ void CWeather::RenderRainStreaks(void)
|
||||||
TempBufferVerticesStored = 0;
|
TempBufferVerticesStored = 0;
|
||||||
TempBufferIndicesStored = 0;
|
TempBufferIndicesStored = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWeather::StoreWeatherState()
|
|
||||||
{
|
|
||||||
Stored_StateStored = true;
|
|
||||||
Stored_InterpolationValue = InterpolationValue;
|
|
||||||
Stored_Rain = Rain;
|
|
||||||
Stored_NewWeatherType = NewWeatherType;
|
|
||||||
Stored_OldWeatherType = OldWeatherType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWeather::RestoreWeatherState()
|
|
||||||
{
|
|
||||||
#ifdef FIX_BUGS // it's not used anyway though
|
|
||||||
Stored_StateStored = false;
|
|
||||||
#endif
|
|
||||||
InterpolationValue = Stored_InterpolationValue;
|
|
||||||
Rain = Stored_Rain;
|
|
||||||
NewWeatherType = Stored_NewWeatherType;
|
|
||||||
OldWeatherType = Stored_OldWeatherType;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
enum {
|
enum {
|
||||||
WEATHER_SUNNY,
|
WEATHER_RANDOM = -1,
|
||||||
|
WEATHER_SUNNY = 0,
|
||||||
WEATHER_CLOUDY,
|
WEATHER_CLOUDY,
|
||||||
WEATHER_RAINY,
|
WEATHER_RAINY,
|
||||||
WEATHER_FOGGY
|
WEATHER_FOGGY,
|
||||||
|
WEATHER_EXTRA_SUNNY,
|
||||||
|
WEATHER_HURRICANE,
|
||||||
|
WEATHER_TOTAL
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWeather
|
class CWeather
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
|
||||||
WEATHER_RANDOM = -1,
|
|
||||||
WEATHER_SUNNY = 0,
|
|
||||||
WEATHER_CLOUDY = 1,
|
|
||||||
WEATHER_RAINY = 2,
|
|
||||||
WEATHER_FOGGY = 3,
|
|
||||||
WEATHER_TOTAL = 4
|
|
||||||
};
|
|
||||||
static int32 SoundHandle;
|
static int32 SoundHandle;
|
||||||
|
|
||||||
static int32 WeatherTypeInList;
|
static int32 WeatherTypeInList;
|
||||||
|
@ -38,13 +34,11 @@ public:
|
||||||
static float InterpolationValue;
|
static float InterpolationValue;
|
||||||
static float WetRoads;
|
static float WetRoads;
|
||||||
static float Rainbow;
|
static float Rainbow;
|
||||||
|
static float SunGlare;
|
||||||
|
static float WindClipped;
|
||||||
|
static float TrafficLightBrightness;
|
||||||
|
|
||||||
static bool bScriptsForceRain;
|
static bool bScriptsForceRain;
|
||||||
static bool Stored_StateStored;
|
|
||||||
static float Stored_InterpolationValue;
|
|
||||||
static int16 Stored_OldWeatherType;
|
|
||||||
static int16 Stored_NewWeatherType;
|
|
||||||
static float Stored_Rain;
|
|
||||||
|
|
||||||
static void RenderRainStreaks(void);
|
static void RenderRainStreaks(void);
|
||||||
static void Update(void);
|
static void Update(void);
|
||||||
|
@ -53,9 +47,9 @@ public:
|
||||||
static void ReleaseWeather();
|
static void ReleaseWeather();
|
||||||
static void ForceWeather(int16);
|
static void ForceWeather(int16);
|
||||||
static void ForceWeatherNow(int16);
|
static void ForceWeatherNow(int16);
|
||||||
static void StoreWeatherState();
|
|
||||||
static void RestoreWeatherState();
|
|
||||||
static void AddRain();
|
static void AddRain();
|
||||||
|
static void AddHeatHaze();
|
||||||
|
static void AddBeastie();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -139,6 +139,8 @@ static float PitchToCamera;
|
||||||
void
|
void
|
||||||
CVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle)
|
CVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle)
|
||||||
{
|
{
|
||||||
|
if (vehicle->object.type != rpCLUMP)
|
||||||
|
return;
|
||||||
DistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle));
|
DistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle));
|
||||||
RwV3d distToCam;
|
RwV3d distToCam;
|
||||||
RwV3dSub(&distToCam, ms_pCameraPosn, &RwFrameGetMatrix(RpClumpGetFrame(vehicle))->pos);
|
RwV3dSub(&distToCam, ms_pCameraPosn, &RwFrameGetMatrix(RpClumpGetFrame(vehicle))->pos);
|
||||||
|
|
|
@ -186,7 +186,7 @@ bool CCarGenerator::CheckForBlockage(int32 mi)
|
||||||
CWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false);
|
CWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false);
|
||||||
for (int i = 0; i < entities; i++) {
|
for (int i = 0; i < entities; i++) {
|
||||||
if (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f &&
|
if (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f &&
|
||||||
m_vecPos.z + pColModel->boundingBox.max.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) {
|
m_vecPos.z + pColModel->boundingBox.max.z > pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) {
|
||||||
m_bIsBlocking = true;
|
m_bIsBlocking = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue