more pedattractor

This commit is contained in:
Nikolay Korolev
2020-05-14 13:46:11 +03:00
parent d426588496
commit d031943f2a
6 changed files with 934 additions and 179 deletions

View File

@@ -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;
}