From 08b2138c7e59ce3350d333832ceca5c24799a34c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 16 May 2020 01:49:30 +0300 Subject: [PATCH] ped attractors done --- src/core/FileLoader.cpp | 8 +++--- src/core/World.cpp | 55 ++++++++++++++++++++++++++++++++++++++++ src/core/World.h | 2 ++ src/peds/CivilianPed.cpp | 22 ++++++++-------- src/peds/Ped.cpp | 22 ++++++++-------- src/peds/PedAttactor.cpp | 12 ++++----- src/render/2dEffect.h | 2 +- 7 files changed, 90 insertions(+), 33 deletions(-) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 589ec23c..41c96401 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1033,12 +1033,12 @@ CFileLoader::Load2dEffect(const char *line) 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.useDir.x, - &effect->pedattr.useDir.y, - &effect->pedattr.useDir.z, &effect->pedattr.queueDir.x, &effect->pedattr.queueDir.y, - &effect->pedattr.queueDir.z); + &effect->pedattr.queueDir.z, + &effect->pedattr.useDir.x, + &effect->pedattr.useDir.y, + &effect->pedattr.useDir.z); effect->pedattr.type = ptype; break; } diff --git a/src/core/World.cpp b/src/core/World.cpp index 493ce042..0392ba2f 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -2236,3 +2236,58 @@ CWorld::UseDetonator(CEntity *pEntity) } } } + +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; +} diff --git a/src/core/World.h b/src/core/World.h index bc905bf5..89f05cfd 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -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 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 GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } static int GetSectorIndexX(float f) { return (int)GetSectorX(f); } diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 7d4f4d12..f90dffa8 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -216,7 +216,7 @@ 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 || IsUseAttractorObjective(m_objective)) && m_pNextPathNode) { m_pNextPathNode = nil; #ifdef TOGGLEABLE_BETA_FEATURES } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) { @@ -248,7 +248,7 @@ 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 || IsUseAttractorObjective(m_objective)) { SetIdle(); } else { RestorePreviousState(); @@ -422,9 +422,8 @@ void CCivilianPed::UseNearbyAttractors() 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 + //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) + //continue; CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); @@ -433,7 +432,7 @@ void CCivilianPed::UseNearbyAttractors() if (!IsAttractedTo(pEffect->pedattr.type)) continue; CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), 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)) { @@ -446,9 +445,10 @@ void CCivilianPed::UseNearbyAttractors() } 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 + //if (pEntity->IsObject() && (CObject*)(pEntity)->IsBroken()) + //continue; + if (pEntity->GetModelIndex() == 3181) + debug("get2\n"); CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex()); for (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) { C2dEffect* pEffect = pModelInfo->Get2dEffect(i); @@ -457,7 +457,7 @@ void CCivilianPed::UseNearbyAttractors() if (!IsAttractedTo(pEffect->pedattr.type)) continue; CVector pos; - CPedAttractorManager::ComputeEffectPos(pEffect, GetMatrix(), 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)) { @@ -482,7 +482,7 @@ bool CCivilianPed::IsAttractedTo(int8 type) case ATTRACTOR_STOP: return true; case ATTRACTOR_PIZZA: return true; case ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f; - case ATTRACTOR_ICECREAM: return true; + case ATTRACTOR_ICECREAM: return false; } return false; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1441e1d5..6cc16ad2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -5529,17 +5529,17 @@ CPed::SetWaitState(eWaitState state, void *time) 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 = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 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 = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 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 = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -5547,7 +5547,7 @@ CPed::SetWaitState(eWaitState state, void *time) 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 = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 5000.0f); // TODO(MIAMI): proper anim! animAssoc->SetFinishCallback(FinishedWaitCB, this); if (time) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time; @@ -14046,7 +14046,7 @@ CPed::ProcessObjective(void) if (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) { switch (m_objective) { case OBJECTIVE_USE_SEAT_ATTRACTOR: - if (bTurnedAroundOnAttractor) { + if (!bTurnedAroundOnAttractor) { ClearObjective(); SetWaitState(WAITSTATE_SIT_DOWN, 0); } @@ -17998,19 +17998,19 @@ CPed::ClearWaitState(void) 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; + case WAITSTATE_SIT_DOWN: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_DOWN_RVRS: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_UP: id = ANIM_HANDSUP; break; + case WAITSTATE_SIT_IDLE: id = ANIM_HANDSUP; break; + case WAITSTATE_USE_ATM: id = ANIM_HANDSUP; break; } CAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetAssociation(GetClump(), id); if (pAssoc) pAssoc->blendDelta = -8.0f; if (m_attractor) GetPedAttractorManager()->DeRegisterPed(this, m_attractor); - break; } + break; case WAITSTATE_RIOT: case WAITSTATE_FAST_FALL: case WAITSTATE_BOMBER: diff --git a/src/peds/PedAttactor.cpp b/src/peds/PedAttactor.cpp index bef14308..a3b93067 100644 --- a/src/peds/PedAttactor.cpp +++ b/src/peds/PedAttactor.cpp @@ -485,7 +485,7 @@ bool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttracto 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 BroadcastArrival(pPed, pAttractor, vAtmAttractors); @@ -504,7 +504,7 @@ bool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttrac 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 BroadcastDeparture(pPed, pAttractor, vAtmAttractors); @@ -523,7 +523,7 @@ bool CPedAttractorManager::IsAtHeadOfQueue(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 IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors); @@ -542,7 +542,7 @@ bool CPedAttractorManager::IsInQueue(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 IsInQueue(pPed, pAttractor, vAtmAttractors); @@ -747,13 +747,13 @@ bool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& mat 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; + 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) */) + if (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f && CWorld::IsWanderPathClear(pPed->GetPosition(), vecEffectPos, 2.0f, 0)) return true; } return false; diff --git a/src/render/2dEffect.h b/src/render/2dEffect.h index 33b553bd..ed5ce5ba 100644 --- a/src/render/2dEffect.h +++ b/src/render/2dEffect.h @@ -65,8 +65,8 @@ public: uint8 probability; }; struct PedAttractor { - CVector useDir; CVector queueDir; + CVector useDir; int8 type; };