mirror of
https://github.com/halpz/re3.git
synced 2024-12-26 18:15:27 +00:00
more pedattractor
This commit is contained in:
parent
d426588496
commit
d031943f2a
|
@ -9,6 +9,8 @@
|
|||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "SurfaceTable.h"
|
||||
#include "Weather.h"
|
||||
#include "PedAttractor.h"
|
||||
|
||||
CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
|
||||
{
|
||||
|
@ -16,6 +18,8 @@ CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
|
|||
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
|
||||
m_nearPeds[i] = nil;
|
||||
}
|
||||
m_nAttractorCycleState = 0;
|
||||
m_bAttractorUnk = (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 1.25f);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -365,6 +369,10 @@ CCivilianPed::ProcessControl(void)
|
|||
if (IsPedInControl())
|
||||
CivilianAI();
|
||||
|
||||
if (CharCreatedBy == RANDOM_CHAR) {
|
||||
UseNearbyAttractors();
|
||||
}
|
||||
|
||||
if (CTimer::GetTimeInMilliseconds() > m_timerUnused) {
|
||||
m_stateUnused = 0;
|
||||
m_timerUnused = 0;
|
||||
|
@ -373,3 +381,108 @@ CCivilianPed::ProcessControl(void)
|
|||
if (m_moved.Magnitude() > 0.0f)
|
||||
Avoid();
|
||||
}
|
||||
|
||||
const int32 gFrequencyOfAttractorAttempt = 11;
|
||||
const float gDistanceToSeekAttractors = 50.0f;
|
||||
const float gMaxDistanceToAttract = 10.0f;
|
||||
|
||||
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);
|
||||
for (CPtrNode* pNode = s->m_lists[ENTITYLIST_BUILDINGS].first; pNode != nil; pNode = pNode->next) {
|
||||
CEntity* pEntity = (CEntity*)pNode->item;
|
||||
if (!pEntity->IsObject())
|
||||
continue;
|
||||
// TODO: some flag check
|
||||
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, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (CPtrNode* pNode = s->m_lists[ENTITYLIST_OBJECTS].first; pNode != nil; pNode = pNode->next) {
|
||||
CEntity* pEntity = (CEntity*)pNode->item;
|
||||
if (!pEntity->IsObject())
|
||||
continue;
|
||||
// TODO: some flag check
|
||||
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, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,16 @@
|
|||
|
||||
class CCivilianPed : public CPed
|
||||
{
|
||||
bool m_bAttractorUnk;
|
||||
int32 m_nAttractorCycleState;
|
||||
public:
|
||||
CCivilianPed(ePedType, uint32);
|
||||
~CCivilianPed(void) { }
|
||||
|
||||
void CivilianAI(void);
|
||||
void ProcessControl(void);
|
||||
void UseNearbyAttractors(void);
|
||||
bool IsAttractedTo(int8);
|
||||
};
|
||||
#ifndef PED_SKIN
|
||||
VALIDATE_SIZE(CCivilianPed, 0x53C);
|
||||
|
|
433
src/peds/Ped.cpp
433
src/peds/Ped.cpp
|
@ -57,6 +57,7 @@
|
|||
#include "Timecycle.h"
|
||||
#include "ParticleObject.h"
|
||||
#include "Floater.h"
|
||||
#include "PedAttractor.h"
|
||||
|
||||
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
|
||||
|
||||
|
@ -384,6 +385,8 @@ CPed::DebugRenderOnePedText(void)
|
|||
CPed::~CPed(void)
|
||||
{
|
||||
CWorld::Remove(this);
|
||||
if (m_attractor)
|
||||
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||
CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
|
||||
if (InVehicle()){
|
||||
uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
|
||||
|
@ -452,7 +455,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
|||
CharCreatedBy = RANDOM_CHAR;
|
||||
m_leader = nil;
|
||||
m_pedInObjective = nil;
|
||||
m_attractorHeading = 0.0f;
|
||||
m_carInObjective = nil;
|
||||
m_attractorHeading = 0.0f;
|
||||
bInVehicle = false;
|
||||
m_pMyVehicle = nil;
|
||||
m_pVehicleAnim = nil;
|
||||
|
@ -489,6 +494,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
|||
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_wepSkills = 0;
|
||||
m_distanceToCountSeekDone = 1.0f;
|
||||
m_acceptableHeadingOffset = 0.1f;
|
||||
bRunningToPhone = false;
|
||||
m_phoneId = -1;
|
||||
m_lastAccident = 0;
|
||||
|
@ -611,6 +617,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
|
|||
bSomeVCflag1 = false;
|
||||
#endif
|
||||
|
||||
bReachedAttractorHeadingTarget = false;
|
||||
bTurnedAroundOnAttractor = false;
|
||||
bCarPassenger = false;
|
||||
bMiamiViceCop = false;
|
||||
bDeadPedInFrontOfCar = false;
|
||||
|
@ -3666,6 +3674,8 @@ CPed::SetStoredState(void)
|
|||
void
|
||||
CPed::SetDie(AnimationId animId, float delta, float speed)
|
||||
{
|
||||
if (m_attractor)
|
||||
GetPedAttractorManager()->DeRegisterPed(this, m_attractor);
|
||||
CPlayerPed *player = FindPlayerPed();
|
||||
if (player == this) {
|
||||
if (!player->m_bCanBeDamaged)
|
||||
|
@ -5518,8 +5528,45 @@ CPed::SetWaitState(eWaitState state, void *time)
|
|||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
||||
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
|
||||
break;
|
||||
case WAITSTATE_SIT_DOWN:
|
||||
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim!
|
||||
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 10000;
|
||||
break;
|
||||
case WAITSTATE_SIT_UP:
|
||||
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f); // TODO(MIAMI): proper anim!
|
||||
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;
|
||||
break;
|
||||
case WAITSTATE_SIT_IDLE:
|
||||
animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim!
|
||||
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_XPRESS_SCRATCH, 5000.0f); // TODO(MIAMI): proper anim!
|
||||
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:
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
RestoreHeadingRate();
|
||||
return;
|
||||
}
|
||||
|
@ -7177,7 +7224,7 @@ CPed::Wait(void)
|
|||
CPed *pedWeLook;
|
||||
|
||||
if (DyingOrDead()) {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
RestoreHeadingRate();
|
||||
return;
|
||||
}
|
||||
|
@ -7187,7 +7234,7 @@ CPed::Wait(void)
|
|||
case WAITSTATE_TRAFFIC_LIGHTS:
|
||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
SetMoveState(PEDMOVE_WALK);
|
||||
}
|
||||
}
|
||||
|
@ -7196,7 +7243,7 @@ CPed::Wait(void)
|
|||
case WAITSTATE_CROSS_ROAD:
|
||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
else
|
||||
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
|
||||
|
||||
|
@ -7210,7 +7257,7 @@ CPed::Wait(void)
|
|||
|
||||
case WAITSTATE_CROSS_ROAD_LOOK:
|
||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
|
||||
if (animAssoc) {
|
||||
animAssoc->blendDelta = -8.0f;
|
||||
|
@ -7227,7 +7274,7 @@ CPed::Wait(void)
|
|||
CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
|
||||
}
|
||||
} else {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
SetMoveState(PEDMOVE_WALK);
|
||||
}
|
||||
break;
|
||||
|
@ -7238,13 +7285,13 @@ CPed::Wait(void)
|
|||
m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
|
||||
}
|
||||
} else {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
}
|
||||
break;
|
||||
|
||||
case WAITSTATE_TURN180:
|
||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
SetMoveState(PEDMOVE_WALK);
|
||||
m_fRotationCur = m_fRotationCur + PI;
|
||||
if (m_nPedState == PED_INVESTIGATE)
|
||||
|
@ -7263,7 +7310,7 @@ CPed::Wait(void)
|
|||
animAssoc->SetFinishCallback(FinishedWaitCB, this);
|
||||
m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
|
||||
} else {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -7292,7 +7339,7 @@ CPed::Wait(void)
|
|||
|
||||
if (animAssoc->animId == ANIM_TURN_180) {
|
||||
m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
SetMoveState(PEDMOVE_WALK);
|
||||
m_nStoredMoveState = PEDMOVE_NONE;
|
||||
m_panicCounter = 0;
|
||||
|
@ -7329,7 +7376,7 @@ CPed::Wait(void)
|
|||
|
||||
case WAITSTATE_LOOK_ABOUT:
|
||||
if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
|
||||
if (animAssoc) {
|
||||
animAssoc->blendDelta = -8.0f;
|
||||
|
@ -7356,7 +7403,7 @@ CPed::Wait(void)
|
|||
|
||||
TurnBody();
|
||||
} else {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
m_nWaitTimer = 0;
|
||||
if (m_pLookTarget && m_pLookTarget->IsPed()) {
|
||||
|
||||
|
@ -7431,7 +7478,7 @@ CPed::Wait(void)
|
|||
animAssoc->blendDelta = -4.0f;
|
||||
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
||||
}
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
}
|
||||
#ifdef VC_PED_PORTS
|
||||
else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
|
||||
|
@ -7455,13 +7502,59 @@ CPed::Wait(void)
|
|||
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
|
||||
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
|
||||
int timer = 2000;
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
|
||||
}
|
||||
} else {
|
||||
m_nWaitState = WAITSTATE_FALSE;
|
||||
ClearWaitState();
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -9461,7 +9554,7 @@ CPed::ProcessControl(void)
|
|||
} else if (m_nPedStateTimer < 1001) {
|
||||
m_nPedStateTimer = 0;
|
||||
}
|
||||
} else {
|
||||
} else if (!GetPedAttractorManager()->IsInQueue(this, m_attractor)) {
|
||||
if (m_panicCounter == 50 && IsPedInControl()) {
|
||||
SetWaitState(WAITSTATE_STUCK, nil);
|
||||
// Leftover
|
||||
|
@ -12668,9 +12761,21 @@ CPed::ProcessObjective(void)
|
|||
case OBJECTIVE_SET_LEADER:
|
||||
break;
|
||||
case OBJECTIVE_IDLE:
|
||||
if (GetPedState() == PED_DRIVING)
|
||||
m_objective = OBJECTIVE_NONE;
|
||||
else {
|
||||
SetIdle();
|
||||
if (m_attractor) {
|
||||
if (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
|
||||
GetPedAttractorManager()->BroadcastDeparture(this, m_attractor);
|
||||
m_objectiveTimer = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_objective = OBJECTIVE_NONE;
|
||||
SetMoveState(PEDMOVE_STILL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OBJECTIVE_FLEE_TILL_SAFE:
|
||||
if (InVehicle()) {
|
||||
|
@ -13851,6 +13956,187 @@ CPed::ProcessObjective(void)
|
|||
}
|
||||
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
|
||||
}
|
||||
if (bObjectiveCompleted
|
||||
|
@ -16939,6 +17225,22 @@ CPed::WarpPedIntoCar(CVehicle *car)
|
|||
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
|
||||
CPed::SetObjective(eObjective newObj, CVector dest)
|
||||
{
|
||||
|
@ -16988,14 +17290,50 @@ CPed::SetObjective(eObjective newObj, CVector dest)
|
|||
break;
|
||||
case OBJECTIVE_GOTO_AREA_ANY_MEANS:
|
||||
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;
|
||||
m_pNextPathNode = nil;
|
||||
m_nextRoutePointPos = dest;
|
||||
m_vecSeekPos = m_nextRoutePointPos;
|
||||
m_distanceToCountSeekDone = 0.5f;
|
||||
bUsePedNodeSeek = true;
|
||||
if (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D())
|
||||
if (m_objective == OBJECTIVE_USE_ATM_ATTRACTOR) {
|
||||
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;
|
||||
if (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case OBJECTIVE_RUN_TO_AREA:
|
||||
bIsRunning = true;
|
||||
|
@ -17622,6 +17960,65 @@ CPed::SetExitBoat(CVehicle *boat)
|
|||
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_XPRESS_SCRATCH; break;
|
||||
case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_XPRESS_SCRATCH; break;
|
||||
case WAITSTATE_SIT_UP: id = ANIM_XPRESS_SCRATCH; break;
|
||||
case WAITSTATE_SIT_IDLE: id = ANIM_XPRESS_SCRATCH; break;
|
||||
case WAITSTATE_USE_ATM: id = ANIM_XPRESS_SCRATCH; 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
|
||||
void
|
||||
CPed::Save(uint8*& buf)
|
||||
|
|
|
@ -149,7 +149,22 @@ enum eWaitState {
|
|||
WAITSTATE_PLAYANIM_HANDSUP,
|
||||
WAITSTATE_PLAYANIM_HANDSCOWER,
|
||||
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 {
|
||||
|
@ -201,14 +216,13 @@ enum eObjective : uint32 {
|
|||
OBJECTIVE_USE_SHELTER_ATTRACTOR,
|
||||
OBJ_46,
|
||||
OBJ_47,
|
||||
OBJ_48,
|
||||
OBJECTIVE_WAIT_FOR_RAIN_TO_END,
|
||||
OBJ_49,
|
||||
OBJ_50,
|
||||
OBJ_51,
|
||||
OBJ_52,
|
||||
OBJECTIVE_WAIT_FOR_BUS,
|
||||
OBJECTIVE_USE_ICECREAM_ATTRACTOR,
|
||||
OBJ_53,
|
||||
OBJ_54,
|
||||
OBJECTIVE_PURCHASE_ICECREAM,
|
||||
OBJ_55,
|
||||
OBJ_56,
|
||||
OBJ_57,
|
||||
|
@ -414,6 +428,8 @@ public:
|
|||
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 bReachedAttractorHeadingTarget : 1; // 0x154 0x40
|
||||
uint32 bTurnedAroundOnAttractor : 1; // 0x154 0x80
|
||||
uint32 bHasAlreadyUsedAttractor : 1; // 0x155 0x1
|
||||
uint32 bCarPassenger : 1; // 0x155 0x4
|
||||
uint32 bMiamiViceCop : 1; // 0x155 0x20
|
||||
|
@ -425,6 +441,7 @@ public:
|
|||
CPed *m_pedInObjective;
|
||||
CVehicle *m_carInObjective;
|
||||
CVector m_nextRoutePointPos;
|
||||
float m_attractorHeading;
|
||||
CPed *m_leader;
|
||||
eFormation m_pedFormation;
|
||||
uint32 m_fearFlags;
|
||||
|
@ -482,7 +499,7 @@ public:
|
|||
CVehicle *m_pMyVehicle;
|
||||
bool bInVehicle;
|
||||
float m_distanceToCountSeekDone;
|
||||
|
||||
float m_acceptableHeadingOffset;
|
||||
CPedAttractor* m_attractor;
|
||||
int32 m_positionInQueue;
|
||||
CVehicle* m_vehicleInAccident;
|
||||
|
@ -610,6 +627,7 @@ public:
|
|||
void SetObjective(eObjective, int16, int16);
|
||||
void SetObjective(eObjective, CVector);
|
||||
void SetObjective(eObjective, CVector, float);
|
||||
void SetObjective(eObjective, float, const CVector&);
|
||||
void ClearChat(void);
|
||||
void InformMyGangOfAttack(CEntity*);
|
||||
void ReactToAttack(CEntity*);
|
||||
|
@ -822,6 +840,7 @@ public:
|
|||
#endif
|
||||
|
||||
void SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int);
|
||||
void ClearWaitState(void);
|
||||
|
||||
bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
|
||||
CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
|
||||
|
@ -837,6 +856,12 @@ public:
|
|||
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 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 RemoveWeaponWhenEnteringVehicle(void);
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
|
||||
#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;
|
||||
|
||||
std::vector<CVector> CPedShelterAttractor::ms_displacements;
|
||||
|
||||
CPedAttractorManager* GetPedAttractorManager()
|
||||
{
|
||||
|
@ -107,7 +114,7 @@ CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect)
|
|||
return nil;
|
||||
}
|
||||
|
||||
const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*> vecAttractors)
|
||||
const CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors)
|
||||
{
|
||||
if (vecAttractors.empty())
|
||||
return nil;
|
||||
|
@ -140,20 +147,21 @@ void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect)
|
|||
}
|
||||
}
|
||||
|
||||
CPedAttractor::CPedAttractor(C2dEffect* pEffect, CMatrix const& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
p2dEffect(p2dEffect),
|
||||
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),
|
||||
field_30(unk8),
|
||||
field_34(unk9),
|
||||
m_fDistanceToUseAttractor(distance),
|
||||
m_fAcceptableHeading(headingdiff),
|
||||
m_fMaxPositionDisplacement(posdisp),
|
||||
m_fMaxHeadingDisplacement(headdisp),
|
||||
vecEffectPos(Multiply3x3(matrix, pEffect->pos)),
|
||||
vecQueueDir(Multiply3x3(matrix, pEffect->pedattr.queueDir)),
|
||||
vecUseDir(Multiply3x3(matrix, pEffect->pedattr.useDir))
|
||||
{}
|
||||
m_fMaxHeadingDisplacement(headdisp)
|
||||
{
|
||||
CPedAttractorManager::ComputeEffectPos(pEffect, matrix, vecEffectPos);
|
||||
CPedAttractorManager::ComputeEffectQueueDir(pEffect, matrix, vecQueueDir);
|
||||
CPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir);
|
||||
}
|
||||
|
||||
float CPedAttractor::ComputeDeltaHeading() const
|
||||
{
|
||||
|
@ -184,7 +192,7 @@ void CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const
|
|||
}
|
||||
}
|
||||
|
||||
CVector CPedShelterAttractor::GetDisplacement(int32 qid)
|
||||
CVector CPedShelterAttractor::GetDisplacement(int32 qid) const
|
||||
{
|
||||
if (ms_displacements.empty()) {
|
||||
int i = 0;
|
||||
|
@ -208,6 +216,13 @@ CVector CPedShelterAttractor::GetDisplacement(int32 qid)
|
|||
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);
|
||||
|
@ -254,7 +269,7 @@ static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed)
|
|||
return true;
|
||||
break;
|
||||
case ATTRACTOR_STOP:
|
||||
if (pPed->m_objective == OBJECTIVE_USE_STOP_ATTRACTOR || pPed->m_objective == OBJ_52 || pPed->m_objective == OBJECTIVE_IDLE)
|
||||
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:
|
||||
|
@ -262,11 +277,11 @@ static bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed)
|
|||
return true;
|
||||
break;
|
||||
case ATTRACTOR_SHELTER:
|
||||
if (pPed->m_objective == OBJECTIVE_USE_SHELTER_ATTRACTOR || pPed->m_objective == OBJ_48)
|
||||
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 == OBJ_54)
|
||||
if (pPed->m_objective == OBJECTIVE_USE_ICECREAM_ATTRACTOR || pPed->m_objective == OBJECTIVE_PURCHASE_ICECREAM)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
@ -289,6 +304,7 @@ bool CPedAttractor::DeRegisterPed(CPed* pPed)
|
|||
return true;
|
||||
}
|
||||
pPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));
|
||||
vApproachingQueue.erase(pPedIt);
|
||||
return true;
|
||||
}
|
||||
return BroadcastDeparture(pPed);
|
||||
|
@ -404,6 +420,29 @@ bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed)
|
|||
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)
|
||||
|
@ -427,7 +466,7 @@ bool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor)
|
|||
return false;
|
||||
if (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)
|
||||
return nil;
|
||||
if (IsPedRegisteredWithEffect(pPed))
|
||||
if (!IsPedRegisteredWithEffect(pPed))
|
||||
return nil;
|
||||
switch (pAttractor->GetEffect()->pedattr.type) {
|
||||
case ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors);
|
||||
|
@ -516,6 +555,27 @@ bool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor)
|
|||
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) ||
|
||||
|
@ -526,11 +586,21 @@ bool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed)
|
|||
IsPedRegistered(pPed, vIceCreamAttractors);
|
||||
}
|
||||
|
||||
void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)
|
||||
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;
|
||||
|
@ -552,8 +622,139 @@ CPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect,
|
|||
}
|
||||
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, vecEffectPos, 2.0f, 0) */)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,131 +7,7 @@
|
|||
|
||||
#define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4
|
||||
|
||||
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 field_30;
|
||||
float field_34;
|
||||
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() 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 unk8, float unk9, float posdisp, float headdisp);
|
||||
|
||||
C2dEffect* GetEffect() const { return p2dEffect; }
|
||||
const CVector& GetEffectPos() const { return vecEffectPos; }
|
||||
};
|
||||
|
||||
class CPedAtmAttractor : public CPedAttractor
|
||||
{
|
||||
public:
|
||||
virtual ePedAttractorType GetType() const override { return ATTRACTOR_ATM; };
|
||||
virtual void UpdatePedStateOnDeparture() const override;
|
||||
CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp)
|
||||
{};
|
||||
};
|
||||
|
||||
class CPedIceCreamAttractor : public CPedAttractor
|
||||
{
|
||||
public:
|
||||
virtual ePedAttractorType GetType() const override { return ATTRACTOR_ICECREAM; }
|
||||
virtual void UpdatePedStateOnDeparture() const override;
|
||||
CPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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() const override;
|
||||
CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp)
|
||||
{};
|
||||
};
|
||||
|
||||
class CPedSeatAttractor : public CPedAttractor
|
||||
{
|
||||
public:
|
||||
virtual ePedAttractorType GetType() const override { return ATTRACTOR_SEAT; }
|
||||
virtual void UpdatePedStateOnDeparture() const override;
|
||||
CPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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() 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 unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp)
|
||||
{};
|
||||
|
||||
|
||||
CVector GetDisplacement(int32 qid);
|
||||
};
|
||||
|
||||
class CPedStopAttractor : public CPedAttractor
|
||||
{
|
||||
public:
|
||||
virtual ePedAttractorType GetType() const override { return ATTRACTOR_STOP; }
|
||||
virtual void UpdatePedStateOnDeparture() const override;
|
||||
|
||||
CPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp)
|
||||
{};
|
||||
};
|
||||
class CPedAttractor;
|
||||
|
||||
class CVehicleToEffect
|
||||
{
|
||||
|
@ -165,24 +41,163 @@ public:
|
|||
bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor);
|
||||
bool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||
const C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos);
|
||||
void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir);
|
||||
bool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed);
|
||||
void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& dir);
|
||||
void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);
|
||||
void RemoveIceCreamVanEffects(C2dEffect* pEffect);
|
||||
bool HasEmptySlot(const C2dEffect* pEffect);
|
||||
const CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*> vecAttractors);
|
||||
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 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 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 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 DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);
|
||||
bool IsPedRegisteredWithEffect(CPed* pPed);
|
||||
bool IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*> vecAttractors);
|
||||
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 unk8, float unk9, 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 { /* pPed->m_money += 20 * CGeneral::GetRandomNumberInRange(1, 51); */ };
|
||||
CPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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 unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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
|
||||
{ /*
|
||||
if (pPed->m_money > 10)
|
||||
pPed->m_money = 0;
|
||||
else
|
||||
pPed->m_money -= 10;
|
||||
*/
|
||||
}
|
||||
CPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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 unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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 unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, 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 unk8, float unk9, float posdisp, float headdisp) :
|
||||
CPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, unk8, unk9, posdisp, headdisp)
|
||||
{};
|
||||
};
|
Loading…
Reference in a new issue