diff options
Diffstat (limited to 'src/vehicles/CarGen.cpp')
| -rw-r--r-- | src/vehicles/CarGen.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp new file mode 100644 index 0000000..78e67d4 --- /dev/null +++ b/src/vehicles/CarGen.cpp @@ -0,0 +1,305 @@ +#include "common.h" + +#include "CarGen.h" + +#include "Automobile.h" +#include "Bike.h" +#include "Boat.h" +#include "Camera.h" +#include "CarCtrl.h" +#include "CutsceneMgr.h" +#include "General.h" +#include "Pools.h" +#include "Streaming.h" +#include "Timer.h" +#include "Vehicle.h" +#include "VisibilityPlugins.h" +#include "World.h" +#include "Zones.h" +#include "Occlusion.h" + +uint8 CTheCarGenerators::ProcessCounter; +uint32 CTheCarGenerators::NumOfCarGenerators; +CCarGenerator CTheCarGenerators::CarGeneratorArray[NUM_CARGENS]; +uint8 CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter; +uint32 CTheCarGenerators::CurrentActiveCount; + +void CCarGenerator::SwitchOff() +{ +#ifdef FIX_BUGS + if (m_nUsesRemaining != 0) +#endif + { + m_nUsesRemaining = 0; + --CTheCarGenerators::CurrentActiveCount; + } +} + +void CCarGenerator::SwitchOn() +{ + m_nUsesRemaining = UINT16_MAX; + m_nTimer = CalcNextGen(); + ++CTheCarGenerators::CurrentActiveCount; +} + +uint32 CCarGenerator::CalcNextGen() +{ + return CTimer::GetTimeInMilliseconds() + 4; +} + +void CCarGenerator::DoInternalProcessing() +{ + int mi; + if (CCarCtrl::NumParkedCars >= 10) + return; + if (m_nModelIndex >= 0) { + if (CheckForBlockage(m_nModelIndex)) { + m_nTimer += 4; + return; + } + CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY); + mi = m_nModelIndex; + } + else { + mi = -m_nModelIndex; + if (m_nModelIndex == -1 || !CStreaming::HasModelLoaded(mi)) { + CZoneInfo pZone; + CVector pos = FindPlayerCoors(); + CTheZones::GetZoneInfoForTimeOfDay(&pos, &pZone); + mi = CCarCtrl::ChooseCarModel(CCarCtrl::ChooseCarRating(&pZone)); + if (mi < 0) + return; + m_nModelIndex = -mi; + m_nColor1 = -1; + m_nColor2 = -1; + } + if (CheckForBlockage(mi)) { + m_nTimer += 4; + return; + } + } + if (!CStreaming::HasModelLoaded(mi)) + return; + CVehicle* pVehicle; + + CVector pos; + if (CModelInfo::IsBoatModel(mi)){ + CBoat* pBoat = new CBoat(mi, PARKED_VEHICLE); + pos = m_vecPos; + pVehicle = pBoat; + if (pos.z <= -100.0f) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pBoat->bExtendedRange = true; + }else{ + bool groundFound; + pos = m_vecPos; + if (pos.z > -100.0f){ + pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound); + }else{ + groundFound = false; + CColPoint cp; + CEntity* pEntity; + groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f, + cp, pEntity, true, false, false, false, false, false, nil); + if (groundFound) + pos.z = cp.point.z; + } + if (!groundFound) { + debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); + return; + } + if (((CVehicleModelInfo*)CModelInfo::GetModelInfo(mi))->m_vehicleType == VEHICLE_TYPE_BIKE) { + CBike* pBike = new CBike(mi, PARKED_VEHICLE); + pBike->bIsStanding = true; + pVehicle = pBike; + } + else { + CAutomobile* pCar = new CAutomobile(mi, PARKED_VEHICLE); + pVehicle = pCar; + } + // pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); + pVehicle->bLightsOn = false; + } + pVehicle->bIsStatic = false; + pVehicle->bEngineOn = false; + pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); + pVehicle->SetPosition(pos); + pVehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); + pVehicle->SetStatus(STATUS_ABANDONED); + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(pVehicle); + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm) + pVehicle->m_nAlarmState = -1; + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock) + pVehicle->m_nDoorLock = CARLOCK_LOCKED; + if (m_nColor1 != -1 && m_nColor2 != -1) { + pVehicle->m_currentColour1 = m_nColor1; + pVehicle->m_currentColour2 = m_nColor2; + } + else if (m_nModelIndex < -1) { + m_nColor1 = pVehicle->m_currentColour1; + m_nColor2 = pVehicle->m_currentColour2; + } + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pVehicle); + /* I don't think this is a correct comparasion */ +#ifdef FIX_BUGS + if (m_nUsesRemaining < UINT16_MAX) + --m_nUsesRemaining; +#else + if (m_nUsesRemaining < ~0) + --m_nUsesRemaining; +#endif + m_nTimer = CalcNextGen(); + if (m_nUsesRemaining == 0) + --CTheCarGenerators::CurrentActiveCount; +} + +void CCarGenerator::Process() +{ + if (m_nVehicleHandle == -1 && + (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) && + m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayers()) + DoInternalProcessing(); + if (m_nVehicleHandle == -1) + return; + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle); + if (!pVehicle){ + m_nVehicleHandle = -1; + return; + } + if (pVehicle->GetStatus() != STATUS_PLAYER) + return; + m_nTimer += 60000; + m_nVehicleHandle = -1; + m_bIsBlocking = true; + pVehicle->bExtendedRange = false; + if (m_nModelIndex < 0) + m_nModelIndex = -1; +} + +void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) +{ + CMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */ + m_vecPos = CVector(x, y, z); + m_fAngle = angle; + m_nModelIndex = mi; + m_nColor1 = color1; + m_nColor2 = color2; + m_bForceSpawn = force; + m_nAlarm = alarm; + m_nDoorlock = lock; + m_nMinDelay = min_delay; + m_nMaxDelay = max_delay; + m_nVehicleHandle = -1; + m_nTimer = CTimer::GetTimeInMilliseconds() + 1; + m_nUsesRemaining = 0; + m_bIsBlocking = false; +} + +bool CCarGenerator::CheckForBlockage(int32 mi) +{ + int16 entities; + CEntity* pEntities[8]; + CColModel* pColModel = CModelInfo::GetModelInfo(mi)->GetColModel(); + CWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false); + for (int i = 0; i < entities; i++) { + if (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f && + m_vecPos.z + pColModel->boundingBox.max.z > pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) { + m_bIsBlocking = true; + return true; + } + } + return false; +} + +bool CCarGenerator::CheckIfWithinRangeOfAnyPlayers() +{ + CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos; + float distance = direction.Magnitude(); + float farclip = 110.0f * TheCamera.GenerationDistMultiplier; + float nearclip = farclip - 20.0f; + bool canBeRemoved = (m_nModelIndex > 0 && CModelInfo::IsBoatModel(m_nModelIndex) && 165.0f * TheCamera.GenerationDistMultiplier > distance && + TheCamera.IsSphereVisible(m_vecPos, 0.0f) && !COcclusion::IsPositionOccluded(m_vecPos, 0.0f)); + if (distance >= farclip && !canBeRemoved){ + if (m_bIsBlocking) + m_bIsBlocking = false; + return false; + } + if (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter) + return true; + if (m_bIsBlocking) + return false; + if (distance < nearclip && !m_bForceSpawn) + return false; + return DotProduct2D(direction, FindPlayerSpeed()) <= 0; +} + +void CTheCarGenerators::Process() +{ + if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing()) + return; + if (++CTheCarGenerators::ProcessCounter == 4) + CTheCarGenerators::ProcessCounter = 0; + for (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4) + CTheCarGenerators::CarGeneratorArray[i].Process(); + if (GenerateEvenIfPlayerIsCloseCounter) + GenerateEvenIfPlayerIsCloseCounter--; +} + +int32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) +{ + if (NumOfCarGenerators < NUM_CARGENS) + CarGeneratorArray[NumOfCarGenerators++].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay); + return NumOfCarGenerators - 1; +} + +void CTheCarGenerators::Init() +{ + GenerateEvenIfPlayerIsCloseCounter = 0; + NumOfCarGenerators = 0; + ProcessCounter = 0; + CurrentActiveCount = 0; +} + +void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size) +{ + const uint32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16); + *size = sizeof(int) + nGeneralDataSize + sizeof(uint32) + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE; +INITSAVEBUF + WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE); + + WriteSaveBuf(buffer, nGeneralDataSize); + WriteSaveBuf(buffer, NumOfCarGenerators); + WriteSaveBuf(buffer, CurrentActiveCount); + WriteSaveBuf(buffer, ProcessCounter); + WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter); + WriteSaveBuf(buffer, (int16)0); // alignment + WriteSaveBuf(buffer, (uint32)sizeof(CarGeneratorArray)); + for (int i = 0; i < NUM_CARGENS; i++) + WriteSaveBuf(buffer, CarGeneratorArray[i]); +VALIDATESAVEBUF(*size) +} + +void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size) +{ + NumOfCarGenerators = 0; + GenerateEvenIfPlayerIsCloseCounter = 0; + CurrentActiveCount = 0; + ProcessCounter = 0; + + const int32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16); + Init(); +INITSAVEBUF + CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE); + assert(ReadSaveBuf<uint32>(buffer) == nGeneralDataSize); + NumOfCarGenerators = ReadSaveBuf<uint32>(buffer); + CurrentActiveCount = ReadSaveBuf<uint32>(buffer); + ProcessCounter = ReadSaveBuf<uint8>(buffer); + GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer); + ReadSaveBuf<int16>(buffer); // alignment + assert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray)); + for (int i = 0; i < NUM_CARGENS; i++) + CarGeneratorArray[i] = ReadSaveBuf<CCarGenerator>(buffer); +VALIDATESAVEBUF(size) +} |
