summaryrefslogtreecommitdiffstats
path: root/src/peds/CivilianPed.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/peds/CivilianPed.cpp210
1 files changed, 119 insertions, 91 deletions
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index 2d782a73..51c11775 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -9,30 +9,9 @@
#include "World.h"
#include "Vehicle.h"
#include "SurfaceTable.h"
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-eCrimeType
-EventTypeToCrimeType(eEventType event)
-{
- eCrimeType crime;
- switch (event) {
- case EVENT_ASSAULT: crime = CRIME_HIT_PED; break;
- case EVENT_RUN_REDLIGHT: crime = CRIME_RUN_REDLIGHT; break;
- case EVENT_ASSAULT_POLICE: crime = CRIME_HIT_COP; break;
- case EVENT_GUNSHOT: crime = CRIME_POSSESSION_GUN; break;
- case EVENT_STEAL_CAR: crime = CRIME_STEAL_CAR; break;
- case EVENT_HIT_AND_RUN: crime = CRIME_RUNOVER_PED; break;
- case EVENT_HIT_AND_RUN_COP: crime = CRIME_RUNOVER_COP; break;
- case EVENT_SHOOT_PED: crime = CRIME_SHOOT_PED; break;
- case EVENT_SHOOT_COP: crime = CRIME_SHOOT_COP; break;
- case EVENT_PED_SET_ON_FIRE: crime = CRIME_PED_BURNED; break;
- case EVENT_COP_SET_ON_FIRE: crime = CRIME_COP_BURNED; break;
- case EVENT_CAR_SET_ON_FIRE: crime = CRIME_VEHICLE_BURNED; break;
- default: crime = CRIME_NONE; break;
- }
- return crime;
-}
-#endif
+#include "Weather.h"
+#include "PedAttractor.h"
+#include "Object.h"
CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)
{
@@ -40,6 +19,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
@@ -122,7 +103,7 @@ CCivilianPed::CivilianAI(void)
SetLookTimer(500);
} else if (closestThreatFlag == PED_FLAG_DEADPEDS) {
float eventDistSqr = (m_pEventEntity->GetPosition() - GetPosition()).MagnitudeSqr2D();
- if (IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) {
+ if (((CPed*)m_pEventEntity)->bIsDrowning || IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) {
if (eventDistSqr < sq(5.0f)) {
SetFindPathAndFlee(m_pEventEntity, 2000);
SetMoveState(PEDMOVE_RUN);
@@ -137,26 +118,12 @@ CCivilianPed::CivilianAI(void)
investigateDeadPed = false;
}
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- int32 eventId = CheckForPlayerCrimes((CPed*)m_pEventEntity);
- eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type));
- bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear;
- if (IsGangMember() || !eligibleToReport || !RunToReportCrime(crime))
-#endif
if (investigateDeadPed)
SetInvestigateEvent(EVENT_DEAD_PED, CVector2D(m_pEventEntity->GetPosition()), 1.0f, 20000, 0.0f);
} else {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- int32 eventId = CheckForPlayerCrimes((CPed*)m_pEventEntity);
- eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type));
- bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear;
- if(!eligibleToReport || !RunToReportCrime(crime))
-#endif
- {
- SetFindPathAndFlee(m_pEventEntity, 5000);
- SetMoveState(PEDMOVE_RUN);
- }
+ SetFindPathAndFlee(m_pEventEntity, 5000);
+ SetMoveState(PEDMOVE_RUN);
}
} else if (closestThreatFlag == PED_FLAG_EXPLOSION) {
CVector2D eventDistVec = m_eventOrThreat - GetPosition();
@@ -184,55 +151,30 @@ CCivilianPed::CivilianAI(void)
}
}
} else {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- bool youShouldRunEventually = false;
- bool dontGoToPhone = false;
-#endif
if (m_threatEntity && m_threatEntity->IsPed()) {
CPed *threatPed = (CPed*)m_threatEntity;
if (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) {
if (threatPed->GetWeapon(m_currentWeapon).IsTypeMelee() || !GetWeapon()->IsTypeMelee()) {
if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- dontGoToPhone = true;
-#endif
SetFindPathAndFlee(m_threatEntity, 10000);
}
} else {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- dontGoToPhone = true;
-#endif
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
}
}
} else {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- youShouldRunEventually = true;
-#else
- SetFindPathAndFlee(m_threatEntity, 10000, true);
-#endif
- }
- }
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (!dontGoToPhone) {
- int32 eventId = CheckForPlayerCrimes(nil);
- eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type));
- bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness;
-
- if ((!eligibleToReport || !RunToReportCrime(crime)) && youShouldRunEventually) {
SetFindPathAndFlee(m_threatEntity, 10000, true);
}
}
-#endif
}
}
+// --MIAMI: Done except comments
void
CCivilianPed::ProcessControl(void)
{
- if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory)
+ if (CharCreatedBy == TODO_CHAR)
return;
CPed::ProcessControl();
@@ -243,7 +185,7 @@ CCivilianPed::ProcessControl(void)
if (DyingOrDead())
return;
- GetWeapon()->Update(m_audioEntityId);
+ GetWeapon()->Update(m_audioEntityId, nil);
switch (m_nPedState) {
case PED_WANDER_RANGE:
case PED_WANDER_PATH:
@@ -260,34 +202,20 @@ CCivilianPed::ProcessControl(void)
// fall through
case PED_SEEK_POS:
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 || m_objective == OBJECTIVE_SPRINT_TO_AREA ||
+ IsUseAttractorObjective(m_objective)) && m_pNextPathNode) {
m_pNextPathNode = nil;
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE) {
- if (!isPhoneAvailable(m_phoneId)) {
- RestorePreviousState();
- if (crimeReporters[m_phoneId] == this)
- crimeReporters[m_phoneId] = nil;
- m_phoneId = -1;
- bRunningToPhone = false;
- } else {
- crimeReporters[m_phoneId] = this;
- m_facePhoneStart = true;
- m_nPedState = PED_FACE_PHONE;
- }
-#else
} else if (bRunningToPhone) {
if (gPhoneInfo.m_aPhones[m_phoneId].m_nState != PHONE_STATE_FREE) {
RestorePreviousState();
m_phoneId = -1;
} else {
gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_REPORTING_CRIME;
- m_nPedState = PED_FACE_PHONE;
+ SetPedState(PED_FACE_PHONE);
}
-#endif
} else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
- if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+ if (m_pedInObjective && m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
if (m_moved.Magnitude() == 0.0f) {
if (m_pedInObjective->m_nMoveState == PEDMOVE_STILL)
m_fRotationDest = m_pedInObjective->m_fRotationCur;
@@ -295,7 +223,8 @@ CCivilianPed::ProcessControl(void)
} else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT
&& m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) {
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 || m_objective == OBJECTIVE_SPRINT_TO_AREA ||
+ IsUseAttractorObjective(m_objective)) {
SetIdle();
} else {
RestorePreviousState();
@@ -305,7 +234,7 @@ CCivilianPed::ProcessControl(void)
break;
case PED_FACE_PHONE:
if (FacePhone())
- m_nPedState = PED_MAKE_CALL;
+ SetPedState(PED_MAKE_CALL);
break;
case PED_MAKE_CALL:
if (MakePhonecall())
@@ -361,6 +290,8 @@ CCivilianPed::ProcessControl(void)
GetPosition().x - m_pMyVehicle->GetPosition().x, GetPosition().y - m_pMyVehicle->GetPosition().y, 0.0f);
DMAudio.PlayOneShot(m_pMyVehicle->m_audioEntityId, SOUND_CAR_JERK, 0.0f);
+ m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_BEFORESEX);
+ Say(SOUND_PED_PLAYER_BEFORESEX);
int playerSexFrequency = CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency;
if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= 10 && playerSexFrequency > 250) {
@@ -371,19 +302,23 @@ CCivilianPed::ProcessControl(void)
CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10);
}
- m_pMyVehicle->pDriver->m_fHealth = Min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);
+ m_pMyVehicle->pDriver->m_fHealth = Min(CWorld::Players[0].m_nMaxHealth + 25.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);
if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250)
CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
} else {
bWanderPathAfterExitingCar = true;
CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
+ ClearLeader();
SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX);
}
} else {
bWanderPathAfterExitingCar = true;
CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
- m_pMyVehicle->pDriver->m_fHealth = 125.0f;
+ m_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f;
+ ClearLeader();
SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX);
}
} else {
CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
@@ -396,6 +331,7 @@ CCivilianPed::ProcessControl(void)
} else {
bWanderPathAfterExitingCar = true;
CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
+ ClearLeader();
SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
}
}
@@ -416,6 +352,11 @@ CCivilianPed::ProcessControl(void)
if (IsPedInControl())
CivilianAI();
+ if (CharCreatedBy == RANDOM_CHAR) {
+ // TODO(Miami): EnterVacantNearbyCars();
+ UseNearbyAttractors();
+ }
+
if (CTimer::GetTimeInMilliseconds() > m_timerUnused) {
m_stateUnused = 0;
m_timerUnused = 0;
@@ -424,3 +365,90 @@ CCivilianPed::ProcessControl(void)
if (m_moved.Magnitude() > 0.0f)
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;
+}