diff --git a/src/collision/ColStore.h b/src/collision/ColStore.h index 8e2a3a70..e0da92ca 100644 --- a/src/collision/ColStore.h +++ b/src/collision/ColStore.h @@ -33,6 +33,7 @@ public: static void RequestCollision(const CVector2D &pos); static void EnsureCollisionIsInMemory(const CVector2D &pos); static bool HasCollisionLoaded(const CVector2D &pos); + static bool HasCollisionLoaded(eLevelName level) { return true; }; // TODO static ColDef *GetSlot(int slot) { assert(slot >= 0); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index d71f532d..4e34c4b2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1659,11 +1659,13 @@ const uint32 CRunningScript::nSaveStructSize = sizeof(CRunningScript); #endif +// done(LCS) CMissionCleanup::CMissionCleanup() { Init(); } +// done(LCS) void CMissionCleanup::Init() { m_nCount = 0; @@ -1673,6 +1675,7 @@ void CMissionCleanup::Init() } } +// done(LCS) cleanup_entity_struct* CMissionCleanup::FindFree() { for (int i = 0; i < MAX_CLEANUP; i++){ @@ -1683,7 +1686,8 @@ cleanup_entity_struct* CMissionCleanup::FindFree() return nil; } -static void SleepThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) +// done(LCS) +void SleepThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) { printf("*** SLEEPING PED %i %i\n", pCleanup->id, pPed->GetModelIndex()); if (!pPed->GetIsStatic()) @@ -1691,7 +1695,8 @@ static void SleepThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) pPed->bIsStaticWaitingForCollision = true; } -static void WakeThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) +// done(LCS) +void WakeThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) { printf("*** WAKING UP PED %i %i\n", pCleanup->id, pPed->GetModelIndex()); pPed->bIsStaticWaitingForCollision = false; @@ -1700,6 +1705,42 @@ static void WakeThisPed(cleanup_entity_struct* pCleanup, CPed* pPed) } +// done(LCS) +void SleepThisVehicle(cleanup_entity_struct* pCleanup, CVehicle* pVehicle) +{ + printf("*** SLEEPING VEHICLE %i %i\n", pCleanup->id, pVehicle->GetModelIndex()); + if (!pVehicle->GetIsStatic()) + pVehicle->RemoveFromMovingList(); + pVehicle->bIsStaticWaitingForCollision = true; +} + +// done(LCS) +void WakeThisVehicle(cleanup_entity_struct* pCleanup, CVehicle* pVehicle) +{ + printf("*** WAKING UP VEHICLE %i %i\n", pCleanup->id, pVehicle->GetModelIndex()); + pVehicle->bIsStaticWaitingForCollision = false; + if (!pVehicle->bIsStatic) + pVehicle->AddToMovingList(); +} + +// done(LCS) +void SleepThisObject(cleanup_entity_struct* pCleanup, CObject* pObject) +{ + if (!pObject->GetIsStatic()) + pObject->RemoveFromMovingList(); + pObject->bIsStaticWaitingForCollision = true; +} + +// done(LCS) +void WakeThisObject(cleanup_entity_struct* pCleanup, CObject* pObject) +{ + pObject->bIsStaticWaitingForCollision = false; + if (!pObject->bIsStatic) + pObject->AddToMovingList(); + +} + +// done(LCS) void CMissionCleanup::AddEntityToList(int32 id, uint8 type) { cleanup_entity_struct* pNew = FindFree(); @@ -1710,6 +1751,7 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type) m_nCount++; } +// done(LCS) static void PossiblyWakeThisEntity(CPhysical* pEntity, bool ifColLoaded = false) { if (!pEntity->bIsStaticWaitingForCollision) @@ -1721,6 +1763,7 @@ static void PossiblyWakeThisEntity(CPhysical* pEntity, bool ifColLoaded = false) } } +// done(LCS) void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) { for (int i = 0; i < MAX_CLEANUP; i++){ @@ -1757,37 +1800,102 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) } } +// done(LCS) void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects() { for (int i = 0; i < MAX_CLEANUP; i++) { switch (m_sEntities[i].type) { case CLEANUP_CAR: { - CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); - if (v) - PossiblyWakeThisEntity(v, true); - break; + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (pVehicle) { + eLevelName level = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); + if (level == LEVEL_GENERIC) + level = CGame::currLevel; + if (!CColStore::HasCollisionLoaded(level)) { + if (!pVehicle->bIsStaticWaitingForCollision) { + if (!pVehicle->IsHeli() && !pVehicle->IsPlane() && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI && + pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) { + SleepThisVehicle(&m_sEntities[i], pVehicle); + } + } + } + else { + if (pVehicle->bIsStaticWaitingForCollision) + WakeThisVehicle(&m_sEntities[i], pVehicle); + } + } } + break; + case CLEANUP_OBJECT: + CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); + if (pObject) { + eLevelName level = CTheZones::GetLevelFromPosition(&pObject->GetPosition()); + if (level == LEVEL_GENERIC) + level = CGame::currLevel; + if (!CColStore::HasCollisionLoaded(level)) { + if (!pObject->bIsStaticWaitingForCollision) { + SleepThisObject(&m_sEntities[i], pObject); + } + } + else { + if (pObject->bIsStaticWaitingForCollision) + WakeThisObject(&m_sEntities[i], pObject); + } + } + } + } + for (int i = 0; i < MAX_CLEANUP; i++) { + switch (m_sEntities[i].type) { case CLEANUP_CHAR: { - CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id); - if (p) - PossiblyWakeThisEntity(p, true); - break; + CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (pPed) { + eLevelName level = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); + if (level == LEVEL_GENERIC) + level = CGame::currLevel; + if (!pPed->bIsStaticWaitingForCollision) { + if (pPed->bInVehicle) { + if (pPed->m_pMyVehicle->GetIsStatic()) { + SleepThisPed(&m_sEntities[i], pPed); + continue; + } + } + if (!CColStore::HasCollisionLoaded(level)) { + if (pPed->bInVehicle && pPed->m_pMyVehicle->GetIsStatic() || + pPed->m_attachedTo && pPed->m_attachedTo->GetIsStatic()) + SleepThisPed(&m_sEntities[i], pPed); + } + } + else { + if (!pPed->bInVehicle) { + if (CColStore::HasCollisionLoaded(level)) { + if (!(pPed->bInVehicle && pPed->m_pMyVehicle->GetIsStatic() || + pPed->m_attachedTo && pPed->m_attachedTo->GetIsStatic())) + WakeThisPed(&m_sEntities[i], pPed); + } + } + else { + if (!pPed->m_pMyVehicle->GetIsStatic()) { + WakeThisPed(&m_sEntities[i], pPed); + continue; + } + if (CColStore::HasCollisionLoaded(level)) { + if (!(pPed->bInVehicle && pPed->m_pMyVehicle->GetIsStatic() || + pPed->m_attachedTo && pPed->m_attachedTo->GetIsStatic())) + WakeThisPed(&m_sEntities[i], pPed); + } + } + } + + } } - case CLEANUP_OBJECT: - { - CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); - if (o) - PossiblyWakeThisEntity(o, true); - break; - } - default: - break; + break; } } } +// TODO(LCS) CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i) { if (m_sEntities[i].type == CLEANUP_CAR) { @@ -1803,6 +1911,7 @@ CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i) return nil; } +// done(LCS) except TODO void CMissionCleanup::Process() { CPopulation::m_AllRandomPedsThisType = -1; @@ -1810,6 +1919,8 @@ void CMissionCleanup::Process() CCarCtrl::CarDensityMultiplier = 1.0f; CPed::nThreatReactionRangeMultiplier = 1; CPed::nEnterCarRangeMultiplier = 1; + for (int i = 0; i < MAX_ALLOWED_COLLISIONS; i++) + CTheScripts::AllowedCollision[i] = 0; FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; CRoadBlocks::ClearScriptRoadBlocks(); CRouteNode::Initialise(); @@ -1817,20 +1928,19 @@ void CMissionCleanup::Process() TheCamera.Restore(); TheCamera.SetWideScreenOff(); CSpecialFX::bLiftCam = false; - CSpecialFX::bVideoCam = false; - CTimeCycle::StopExtraColour(0); + // TODO(LCS): CHud::m_ClockEventWarningMinutes = 0; + // TODO(LCS): CHud::m_ClockEventFlashTimer = 0; + CTimeCycle::StopExtraColour(0); // TODO: thiscall for (int i = 0; i < MISSION_AUDIO_SLOTS; i++) DMAudio.ClearMissionAudio(i); CWeather::ReleaseWeather(); for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++) CStreaming::SetMissionDoesntRequireSpecialChar(i); - for (int i = 0; i < NUM_OF_CUTSCENE_OBJECTS; i++) - CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i); CStreaming::ms_disableStreaming = false; - CHud::m_ItemToFlash = -1; - CHud::SetHelpMessage(nil, false); + if (CHud::m_ItemToFlash != ITEM_ARMOUR && CHud::m_ItemToFlash != ITEM_HEALTH) + CHud::m_ItemToFlash = -1; + CHud::SetHelpMessage(nil, false); // nil, false, false, true TODO(LCS) CUserDisplay::OnscnTimer.m_bDisabled = false; - CTheScripts::RemoveScriptTextureDictionary(); CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false; CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CWorld::Players[0].MakePlayerSafe(false); @@ -1838,10 +1948,11 @@ void CMissionCleanup::Process() CWorld::Players[0].m_pPed->m_nDrunkCountdown = 0; CPad::GetPad(0)->SetDrunkInputDelay(0); CWorld::Players[0].m_bDriveByAllowed = true; + CPad::GetPad(0)->unk_B4 = 1.0f; + CPad::GetPad(0)->unk_B8 = 0.5f; DMAudio.ShutUpPlayerTalking(0); CVehicle::bDisableRemoteDetonation = false; CVehicle::bDisableRemoteDetonationOnContact = false; - CGameLogic::ClearShortCut(); CTheScripts::RiotIntensity = 0; CTheScripts::StoreVehicleIndex = -1; CTheScripts::StoreVehicleWasRandom = true; @@ -1879,12 +1990,17 @@ void CMissionCleanup::Process() m_sEntities[i].type = CLEANUP_UNUSED; m_nCount--; } + for (int i = 1; i < NUMSTREAMINFO; i++) { + if (CStreaming::IsScriptOwnedModel(i)) + CStreaming::SetMissionDoesntRequireModel(i); + } } /* NB: CUpsideDownCarCheck is not used by actual script at all * It has a weird usage: AreAnyCarsUpsideDown would fail any mission * just like death or arrest. */ + // done(LCS) except TODO void CUpsideDownCarCheck::Init() { for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ @@ -1893,6 +2009,7 @@ void CUpsideDownCarCheck::Init() } } +// done(LCS) bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id) { CVehicle* v = CPools::GetVehiclePool()->GetAt(id); @@ -1901,6 +2018,7 @@ bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id) v->GetTurnSpeed().Magnitude() < 0.02f; } +// done(LCS) void CUpsideDownCarCheck::UpdateTimers() { uint32 timeStep = CTimer::GetTimeStepInMilliseconds(); @@ -1918,6 +2036,7 @@ void CUpsideDownCarCheck::UpdateTimers() } } +// done(LCS) bool CUpsideDownCarCheck::AreAnyCarsUpsideDown() { for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ @@ -1927,6 +2046,7 @@ bool CUpsideDownCarCheck::AreAnyCarsUpsideDown() return false; } +// done(LCS) void CUpsideDownCarCheck::AddCarToCheck(int32 id) { uint16 index = 0; @@ -1938,6 +2058,7 @@ void CUpsideDownCarCheck::AddCarToCheck(int32 id) m_sCars[index].m_nUpsideDownTimer = 0; } +// done(LCS) void CUpsideDownCarCheck::RemoveCarFromCheck(int32 id) { for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ @@ -1948,6 +2069,7 @@ void CUpsideDownCarCheck::RemoveCarFromCheck(int32 id) } } +// done(LCS) bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id) { for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ diff --git a/src/control/Script.h b/src/control/Script.h index 66c9914e..2690b4ff 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -267,7 +267,8 @@ enum { MAX_NUM_MISSION_SCRIPTS = 120, MAX_NUM_BUILDING_SWAPS = 25, MAX_NUM_INVISIBILITY_SETTINGS = 20, - MAX_NUM_STORED_LINES = 1024 + MAX_NUM_STORED_LINES = 1024, + MAX_ALLOWED_COLLISIONS = 2 }; class CTheScripts @@ -317,6 +318,8 @@ class CTheScripts #define CARDS_IN_STACK (CARDS_IN_DECK * MAX_DECKS) static int16 CardStack[CARDS_IN_STACK]; static int16 CardStackPosition; + + static int AllowedCollision[MAX_ALLOWED_COLLISIONS]; #endif public: static bool bPlayerIsInTheStatium; diff --git a/src/core/Pad.h b/src/core/Pad.h index 9f9f81b6..3a4f54b3 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -164,6 +164,8 @@ public: int32 LastTimeTouched; int32 AverageWeapon; int32 AverageEntries; + float unk_B4; + float unk_B8; #ifdef DETECT_PAD_INPUT_SWITCH static bool IsAffectedByController; diff --git a/src/core/Streaming.h b/src/core/Streaming.h index a67384f6..6e354021 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -123,6 +123,7 @@ public: static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); } static bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); } static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; } + static bool IsScriptOwnedModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED) == 0; } static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); } static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); } static bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); }