From 09c9e16cb122f2939f60be7565712324897bd5f9 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 30 May 2020 20:08:31 +0300 Subject: [PATCH] roadblocks --- src/control/CarCtrl.h | 2 - src/control/PathFind.h | 6 +- src/control/RoadBlocks.cpp | 244 ++++++++++++++++++++++++------------- src/control/RoadBlocks.h | 18 ++- src/control/Script.cpp | 6 +- src/core/config.h | 1 + src/math/Matrix.h | 8 ++ 7 files changed, 193 insertions(+), 92 deletions(-) diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index ed63a0e2..6b4e94ee 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -16,8 +16,6 @@ enum{ MAX_CAR_MODELS_IN_ARRAY = 25, }; -#define LANE_WIDTH 5.0f - #ifdef FIX_BUGS #define FIX_PATHFIND_BUG #endif diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 7abc455a..171a79c5 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -5,6 +5,8 @@ class CVehicle; class CPtrList; +#define LANE_WIDTH 5.0f + enum { NodeTypeExtern = 1, @@ -85,6 +87,8 @@ struct CPathNode float GetX(void) { return x/8.0f; } float GetY(void) { return y/8.0f; } float GetZ(void) { return z/8.0f; } + bool HasDivider(void) { return width != 0; } + float GetDivider(void) { return width/(2*8.0f); } CPathNode *GetPrev(void); CPathNode *GetNext(void); void SetPrev(CPathNode *node); @@ -120,7 +124,7 @@ struct CCarPathLink float GetY(void) { return y/8.0f; } float GetDirX(void) { return dirX/100.0f; } float GetDirY(void) { return dirY/100.0f; } - float GetLaneOffset(void) { return width/80.0f; } + float GetLaneOffset(void) { return width/(2*8.0f*LANE_WIDTH); } float OneWayLaneOffset() { diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index a26e19f5..67847cf9 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -14,14 +14,18 @@ #include "Camera.h" #include "CarCtrl.h" #include "General.h" +#include "Object.h" + +//--MIAMI: file done #define ROADBLOCKDIST (90.0f) +#define ROADBLOCK_OBJECT_WIDTH (4.0f) int16 CRoadBlocks::NumRoadBlocks; int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS]; bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; +CScriptRoadblock CRoadBlocks::aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS]; -//--MIAMI: TODO void CRoadBlocks::Init(void) { @@ -43,7 +47,7 @@ CRoadBlocks::Init(void) } } - // TODO(MIAMI): script roadblocks + ClearScriptRoadBlocks(); } void @@ -83,14 +87,11 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45); CPedPlacement::FindZCoorForPed(&posForZ); pCopPed->SetPosition(posForZ); - CVector vecSavedPos = pCopPed->GetPosition(); - pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI); - pCopPed->m_matrix.GetPosition() += vecSavedPos; + pCopPed->SetOrientation(0.0f, 0.0f, -HALFPI); pCopPed->m_bIsDisabledCop = true; pCopPed->SetIdle(); pCopPed->bKindaStayInSamePlace = true; pCopPed->bNotAllowedToDuck = false; -// pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->bCrouchWhenShooting = roadBlockType != 2; if (pEntityToAttack) { pCopPed->m_pPointGunAt = pEntityToAttack; @@ -105,99 +106,178 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType } } -//--MIAMI: TODO: implement this void CRoadBlocks::GenerateRoadBlocks(void) { - CMatrix offsetMatrix; + CMatrix tmp1, tmp2; + static int16 unk; uint32 frame = CTimer::GetFrameCounter() & 0xF; int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16; const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16; for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) { - CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition(); + int16 node = RoadBlockNodes[nRoadblockNode]; + CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[node].GetPosition(); if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST && vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST && vecDistance.Magnitude() < ROADBLOCKDIST) { if (!InOrOut[nRoadblockNode]) { InOrOut[nRoadblockNode] = true; if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) { -#ifndef MIAMI - CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; - float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; - int32 vehicleId = MI_POLICE; - if (pPlayerWanted->AreArmyRequired()) - vehicleId = MI_BARRACKS; - else if (pPlayerWanted->AreFbiRequired()) - vehicleId = MI_FBICAR; - else if (pPlayerWanted->AreSwatRequired()) - vehicleId = MI_ENFORCER; - if (!CStreaming::HasModelLoaded(vehicleId)) - vehicleId = MI_POLICE; - CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); - float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; - int16 radius = (int16)(fMapObjectRadius / fModelRadius); - if (radius > 0 && radius < 6) { - CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->GetPosition(); - float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->GetForward()); - float fOffset = 0.5f * fModelRadius * (float)(radius - 1); - for (int16 i = 0; i < radius; i++) { - uint8 nRoadblockType = fDotProduct < 0.0f; - if (CGeneral::GetRandomNumber() & 1) { - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI); - } - else { - nRoadblockType = !nRoadblockType; - offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); - } - if (ThePaths.m_objectFlags[RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) - offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); - else - offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); - CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix; - float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f; - int16 colliding = 0; - CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); - if (!colliding) { - CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); - pVehicle->SetStatus(STATUS_ABANDONED); - // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? - vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; - pVehicle->m_matrix = vehicleMatrix; - pVehicle->PlaceOnRoadProperly(); - pVehicle->bIsStatic = false; - pVehicle->m_matrix.UpdateRW(); - pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; - CCarCtrl::JoinCarWithRoadSystem(pVehicle); - pVehicle->bIsLocked = false; - pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; - pVehicle->AutoPilot.m_nCurrentLane = 0; - pVehicle->AutoPilot.m_nNextLane = 0; - pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f; - pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f; - pVehicle->bExtendedRange = true; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) - pVehicle->m_bSirenOrAlarm = true; - if (pVehicle->GetForward().z > 0.94f) { - CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); - CWorld::Add(pVehicle); - pVehicle->bCreateRoadBlockPeds = true; - pVehicle->m_nRoadblockType = nRoadblockType; - pVehicle->m_nRoadblockNode = nRoadblockNode; - } - else { - delete pVehicle; - } - } - } + CCarPathLink* pLink1 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink]]; + CCarPathLink* pLink2 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink + 1]]; + int lanes = Min(pLink1->numRightLanes + pLink1->numLeftLanes, pLink2->numLeftLanes + pLink2->numRightLanes); + float length = LANE_WIDTH * (lanes + 1); + CVector forward(pLink2->GetY() - pLink1->GetY(), -(pLink2->GetX() - pLink1->GetX()), 0.0f); + forward.Normalise(); + if (ThePaths.m_pathNodes[node].HasDivider()) { + CreateRoadBlockBetween2Points( + ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f + ThePaths.m_pathNodes[node].GetDivider()) * forward, + ThePaths.m_pathNodes[node].GetPosition() + ThePaths.m_pathNodes[node].GetDivider() * forward); + CreateRoadBlockBetween2Points( + ThePaths.m_pathNodes[node].GetPosition() - ThePaths.m_pathNodes[node].GetDivider() * forward, + ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f + ThePaths.m_pathNodes[node].GetDivider()) * forward); + } + else { + CreateRoadBlockBetween2Points( + ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f) * forward, + ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f) * forward); } -#endif } } - } else { + } + else { InOrOut[nRoadblockNode] = false; } } - - // TODO(MIAMI): script roadblocks + int i = CTimer::GetFrameCounter() & 0xF; + if (!aScriptRoadBlocks[i].m_bInUse) + return; + if ((aScriptRoadBlocks[i].GetPosition() - FindPlayerCoors()).Magnitude() < 100.0f) { + CreateRoadBlockBetween2Points(aScriptRoadBlocks[i].m_vInf, aScriptRoadBlocks[i].m_vSup); + aScriptRoadBlocks[i].m_bInUse = false; + } +} + +void +CRoadBlocks::ClearScriptRoadBlocks(void) +{ + for (int i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++) + aScriptRoadBlocks[i].m_bInUse = false; +} + +void +CRoadBlocks::RegisterScriptRoadBlock(CVector vInf, CVector vSup) +{ + int32 i; + for (i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++) { + if (!aScriptRoadBlocks[i].m_bInUse) + break; + } + if (i == NUM_SCRIPT_ROADBLOCKS) + return; + aScriptRoadBlocks[i].m_bInUse = true; + aScriptRoadBlocks[i].m_vInf = vInf; + aScriptRoadBlocks[i].m_vSup = vSup; +} + +void +CRoadBlocks::CreateRoadBlockBetween2Points(CVector point1, CVector point2) +{ + CMatrix tmp; + CVector forward = (point2 - point1); + float distBetween = forward.Magnitude(); + CVector pos = (point1 + point2) / 2; + CVector right(forward.y, -forward.x, 0.0f); + forward.Normalise(); + right.Normalise(); + if (DotProduct(FindPlayerCoors() - pos, right) < 0.0f) { + right *= -1.0f; + } + int32 vehicleId = MI_POLICE; + if (FindPlayerPed()->m_pWanted->AreArmyRequired()) + vehicleId = MI_BARRACKS; + else if (FindPlayerPed()->m_pWanted->AreFbiRequired()) + vehicleId = MI_FBICAR; + else if (FindPlayerPed()->m_pWanted->AreSwatRequired()) + vehicleId = MI_ENFORCER; + if (!CStreaming::HasModelLoaded(vehicleId)) + vehicleId = MI_POLICE; + CColModel* pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel(); + float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; + int16 numRoadblockVehicles = Min(6, (int16)(distBetween / fModelRadius)); + for (int16 i = 0; i < numRoadblockVehicles; i++) { + float offset = fModelRadius * (i - numRoadblockVehicles / 2); + tmp.SetTranslate(0.0f, 0.0f, 0.0f); + tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f); + tmp.GetForward() = forward; + tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f); + tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f); + if (CGeneral::GetRandomNumber() & 1) + tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + 3.1416f); + tmp.SetTranslateOnly(offset * forward + pos); + tmp.GetPosition().z += 0.6f; + float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f; + int16 colliding = 0; + CWorld::FindObjectsKindaColliding(tmp.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); + if (!colliding) { + CAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); + pVehicle->SetStatus(STATUS_ABANDONED); + // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? + tmp.GetPosition().z += fModelRadius - 0.6f; + pVehicle->m_matrix = tmp; + pVehicle->PlaceOnRoadProperly(); + pVehicle->bIsStatic = false; + pVehicle->m_matrix.UpdateRW(); + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CCarCtrl::JoinCarWithRoadSystem(pVehicle); + pVehicle->bIsLocked = false; + pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0; + pVehicle->AutoPilot.m_nCruiseSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0; + pVehicle->bExtendedRange = true; + if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) + pVehicle->m_bSirenOrAlarm = true; + if (pVehicle->GetUp().z > 0.94f) { + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + CWorld::Add(pVehicle); + pVehicle->bCreateRoadBlockPeds = true; + pVehicle->m_nRoadblockType = DotProduct(pVehicle->GetRight(), pVehicle->GetPosition() - FindPlayerCoors()) >= 0.0f; + pVehicle->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 7000; + } + else { + delete pVehicle; + } + } + } + int numBarriers = distBetween / ROADBLOCK_OBJECT_WIDTH; + CStreaming::RequestModel(MI_ROADWORKBARRIER1, STREAMFLAGS_DONT_REMOVE); + if (!CStreaming::HasModelLoaded(MI_ROADWORKBARRIER1)) + return; + for (int i = 0; i < numBarriers; i++) { + float offset = ROADBLOCK_OBJECT_WIDTH * (i - numBarriers / 2); + tmp.SetTranslate(0.0f, 0.0f, 0.0f); + tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f); + tmp.GetForward() = forward; + tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f); + tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f); + tmp.SetTranslateOnly(5.0f * right + offset * forward + pos); + tmp.GetPosition().x += (CGeneral::GetRandomNumber() & 0xF) * 0.1f; + tmp.GetPosition().y += (CGeneral::GetRandomNumber() & 0xF) * 0.1f; + bool found; + tmp.GetPosition().z = CWorld::FindGroundZFor3DCoord(tmp.GetPosition().x, tmp.GetPosition().y, tmp.GetPosition().z + 2.0f, &found); + if (!found) + continue; + int16 colliding = 0; + CBaseModelInfo* pMI = CModelInfo::GetModelInfo(MI_ROADWORKBARRIER1); + tmp.GetPosition().z -= pMI->GetColModel()->boundingBox.min.z; + CWorld::FindObjectsKindaColliding(tmp.GetPosition(), pMI->GetColModel()->boundingSphere.radius, 0, &colliding, 2, nil, false, true, true, false, false); + if (colliding == 0) { + CObject* pObject = new CObject(MI_ROADWORKBARRIER1, true); + pObject->GetMatrix() = tmp; + pObject->ObjectCreatedBy = TEMP_OBJECT; + pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 600000; + CWorld::Add(pObject); + } + } } diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index c8469ba5..ef614950 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -3,18 +3,28 @@ class CVehicle; +class CScriptRoadblock +{ +public: + CVector m_vInf; + CVector m_vSup; + bool m_bInUse; + CVector GetPosition() { return (m_vInf + m_vSup) / 2; } +}; + class CRoadBlocks { public: static int16 NumRoadBlocks; -#ifndef MIAMI - static int16 RoadBlockObjects[NUMROADBLOCKS]; -#else static int16 RoadBlockNodes[NUMROADBLOCKS]; -#endif static bool InOrOut[NUMROADBLOCKS]; + static CScriptRoadblock aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS]; static void Init(void); static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType); static void GenerateRoadBlocks(void); + + static void CreateRoadBlockBetween2Points(CVector, CVector); + static void RegisterScriptRoadBlock(CVector, CVector); + static void ClearScriptRoadBlocks(); }; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index f3583cbe..46fdab73 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -272,7 +272,7 @@ void CMissionCleanup::Process() CPed::nThreatReactionRangeMultiplier = 1; CPed::nEnterCarRangeMultiplier = 1; FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; - //CRoadBlocks::ClearScriptRoadblocks() // TODO(MIAMI) + CRoadBlocks::ClearScriptRoadBlocks(); CRouteNode::Initialise(); if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) TheCamera.Restore(); @@ -10533,12 +10533,12 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_CREATE_SCRIPT_ROADBLOCK: { CollectParameters(&m_nIp, 6); - debug("CREATE_SCRIPT_ROADBLOCK not implemented\n"); // TODO(MIAMI) + CRoadBlocks::RegisterScriptRoadBlock(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]); return 0; } case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS: { - debug("CLEAR_ALL_SCRIPT_ROADBLOCKS not implemented\n"); // TODO(MIAMI) + CRoadBlocks::ClearScriptRoadBlocks(); return 0; } case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR: diff --git a/src/core/config.h b/src/core/config.h index c90d3cbf..802925a0 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -115,6 +115,7 @@ enum Config { NUMSHOTINFOS = 100, NUMROADBLOCKS = 300, + NUM_SCRIPT_ROADBLOCKS = 16, NUMVISIBLEENTITIES = 2000, NUMINVISIBLEENTITIES = 150, diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 1d26cc20..9979e701 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -255,6 +255,14 @@ public: m_matrix.at.y = 0.0f; m_matrix.at.z = 1.0f; } + void SetTranslateOnly(float x, float y, float z) { + m_matrix.pos.x = x; + m_matrix.pos.y = y; + m_matrix.pos.z = z; + } + void SetTranslateOnly(const CVector& pos) { + SetTranslateOnly(pos.x, pos.y, pos.z); + } };