1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-11-05 11:25:54 +00:00

Revert "Remove Miami stuff"

This reverts commit 9960c41193.
This commit is contained in:
Sergeanur 2020-05-05 18:04:43 +03:00
parent 9960c41193
commit c2b9ddc5b8
50 changed files with 2028 additions and 14 deletions

View file

@ -6,6 +6,7 @@
#include "Curves.h"
#include "PathFind.h"
//--MIAMI: done
void CAutoPilot::ModifySpeed(float speed)
{
m_fMaxTrafficSpeed = Max(0.01f, speed);
@ -39,6 +40,7 @@ void CAutoPilot::ModifySpeed(float speed)
#endif
}
//--MIAMI: done
void CAutoPilot::RemoveOnePathNode()
{
--m_nPathFindNodesCount;
@ -47,6 +49,7 @@ void CAutoPilot::RemoveOnePathNode()
}
#ifdef COMPATIBLE_SAVES
//--MIAMI: TODO
void CAutoPilot::Save(uint8*& buf)
{
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode);
@ -86,6 +89,7 @@ void CAutoPilot::Save(uint8*& buf)
SkipSaveBuf(buf, 6);
}
//--MIAMI: TODO
void CAutoPilot::Load(uint8*& buf)
{
m_nCurrentRouteNode = ReadSaveBuf<int32>(buf);

View file

@ -26,6 +26,15 @@ enum eCarMission : uint8
MISSION_BLOCKCAR_FARAWAY,
MISSION_BLOCKCAR_CLOSE,
MISSION_BLOCKCAR_HANDBRAKESTOP,
#ifdef MIAMI
MISSION_HELI_FLYTOCOORS,
MISSION_ATTACKPLAYER,
MISSION_PLANE_FLYTOCOORS,
MISSION_HELI_LAND,
MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1,
MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2,
MISSION_BLOCKPLAYER_FORWARDANDBACK
#endif
};
enum eCarTempAction : uint8
@ -75,11 +84,18 @@ public:
uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed;
#ifdef MIAMI
uint8 m_nCruiseSpeedMultiplierType;
float m_fCruiseSpeedMultiplier;
#endif
uint8 m_bSlowedDownBecauseOfCars : 1;
uint8 m_bSlowedDownBecauseOfPeds : 1;
uint8 m_bStayInCurrentLevel : 1;
uint8 m_bStayInFastLane : 1;
uint8 m_bIgnorePathfinding : 1;
#ifdef MIAMI
uint8 m_nSwitchDistance;
#endif
CVector m_vecDestinationCoors;
CPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT];
int16 m_nPathFindNodesCount;
@ -109,6 +125,10 @@ public:
m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
m_nAntiReverseTimer = m_nTimeToStartMission;
m_bStayInFastLane = false;
#ifdef MIAMI
m_nCruiseSpeedMultiplierType = 0;
m_fCruiseSpeedMultiplier = 1.0f;
#endif
}
void ModifySpeed(float);
@ -119,4 +139,3 @@ public:
#endif
};
static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error");

View file

@ -21,16 +21,23 @@
#define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f
//--MIAMI: done
float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)
{
#ifndef MIAMI
return 30.0f;
#else
return pVehicle->AutoPilot.m_nSwitchDistance;
#endif
}
//--MIAMI: done
float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle)
{
return FindSwitchDistanceClose(pVehicle) + 5.0f;
}
//--MIAMI: done
float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer)
@ -38,6 +45,23 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
return FindSwitchDistanceFarNormalVehicle(pVehicle);
}
#ifdef MIAMI
//--MIAMI: done
void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle)
{
if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
pVehicle->m_bSirenOrAlarm = false;
if (CCullZones::NoPolice())
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
}
#endif
//--MIAMI: done
void CCarAI::UpdateCarAI(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer){
@ -67,6 +91,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
#ifndef MIAMI
if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
@ -76,6 +101,9 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (CCullZones::NoPolice())
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
#else
BackToCruisingIfNoWantedLevel(pVehicle);
#endif
break;
case MISSION_RAMPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@ -120,6 +148,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
#ifdef MIAMI
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
BackToCruisingIfNoWantedLevel(pVehicle);
#else
if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())){
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
@ -132,6 +165,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
else if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
#endif
break;
case MISSION_BLOCKPLAYER_FARAWAY:
if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@ -140,6 +174,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
#ifndef MIAMI
if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
@ -149,6 +184,9 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (CCullZones::NoPolice())
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
#else
BackToCruisingIfNoWantedLevel(pVehicle);
#endif
break;
case MISSION_BLOCKPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@ -178,6 +216,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
#ifdef MIAMI
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
BackToCruisingIfNoWantedLevel(pVehicle);
#else
if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
@ -192,7 +235,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
#endif
break;
case MISSION_GOTOCOORDS:
#ifdef MIAMI
if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
#else
if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < DISTANCE_TO_SWITCH_DISTANCE_GOTO ||
#endif
pVehicle->AutoPilot.m_bIgnorePathfinding)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
break;
@ -204,6 +251,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 5.0f){
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
#ifdef MIAMI
if (pVehicle->bParking) {
TellOccupantsToLeaveCar(pVehicle);
pVehicle->bParking = false;
}
#endif
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@ -260,6 +313,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 1.0f) {
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
#ifdef MIAMI
if (pVehicle->bParking) {
TellOccupantsToLeaveCar(pVehicle);
pVehicle->bParking = false;
}
#endif
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@ -279,6 +338,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
break;
case MISSION_RAMCAR_CLOSE:
if (pVehicle->AutoPilot.m_pTargetCar){
#ifndef MIAMI
if
#ifdef FIX_BUGS
(FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar &&
@ -296,6 +356,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (CCullZones::NoPolice())
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
#else
#ifdef FIX_BUGS // btw fixed in SA
if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar)
#endif
BackToCruisingIfNoWantedLevel(pVehicle);
#endif
if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding){
if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){
@ -337,6 +403,42 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
break;
#ifdef MIAMI
case MISSION_ATTACKPLAYER:
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeedBoat(pVehicle);
BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
if (((CVector2D)(pVehicle->AutoPilot.m_vecDestinationCoors) - pVehicle->GetPosition()).Magnitude() < 1.5f)
pVehicle->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2;
BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
{
float distance = ((CVector2D)FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
if (distance < 13.0f) {
TellOccupantsToLeaveCar(pVehicle);
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
}
if (distance > 70.0f || FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone ||
(FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
TellOccupantsToLeaveCar(pVehicle);
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
}
break;
}
case MISSION_BLOCKPLAYER_FORWARDANDBACK:
{
CVector2D diff = (CVector2D)FindPlayerCoors() - pVehicle->GetPosition();
float distance = Max(0.001f, diff.Magnitude());
if (!FindPlayerVehicle() || DotProduct2D(CVector2D(diff.x / distance, diff.y / distance), FindPlayerSpeed()) > 0.05f)
pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;
BackToCruisingIfNoWantedLevel(pVehicle);
}
#endif
default:
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && !CCullZones::NoPolice()){
if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f ||
@ -344,6 +446,9 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nCarMission =
#ifdef MIAMI
pVehicle->GetVehicleAppearance() == VEHICLE_BOAT ? FindPoliceBoatMissionForWantedLevel() :
#endif
FindPoliceCarMissionForWantedLevel();
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
@ -365,6 +470,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
break;
}
#ifdef MIAMI
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel >= 1 && CCullZones::PoliceAbandonCars()) {
TellOccupantsToLeaveCar(pVehicle);
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
#endif
float flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D();
if (flatSpeed > SQR(0.018f)){
pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
@ -373,9 +485,16 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_STOP_FOREVER &&
#ifdef MIAMI
pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP &&
#endif
pVehicle->AutoPilot.m_nCruiseSpeed != 0 &&
(pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){
if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS
#ifdef MIAMI
&& pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS ||
pVehicle->VehicleCreatedBy == MISSION_VEHICLE
#endif
) {
if (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500)
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
@ -407,6 +526,15 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400;
}
}
#ifdef MIAMI
if (pVehicle->bIsLawEnforcer) {
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||
pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {
if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE)
pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;
}
}
#endif
if (pVehicle->GetUp().z < 0.7f){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
@ -446,13 +574,45 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD)
pVehicle->m_nCarHornTimer = 45;
}
#ifdef MIAMI
float target = 1.0f;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)
target = CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(pVehicle->AutoPilot.m_nCruiseSpeedMultiplierType);
float change = CTimer::GetTimeStep() * 0.01f;
if (Abs(pVehicle->AutoPilot.m_fCruiseSpeedMultiplier - target) < change)
pVehicle->AutoPilot.m_fCruiseSpeedMultiplier = target;
else if (pVehicle->AutoPilot.m_fCruiseSpeedMultiplier > target)
pVehicle->AutoPilot.m_fCruiseSpeedMultiplier -= change;
else
pVehicle->AutoPilot.m_fCruiseSpeedMultiplier += change;
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) {
if (!FindPlayerVehicle() ||
FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_CAR ||
FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) {
if (pVehicle->GetVehicleAppearance() == VEHICLE_BOAT) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
}
}
else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BOAT) {
if (pVehicle->GetVehicleAppearance() == VEHICLE_CAR ||
pVehicle->GetVehicleAppearance() == VEHICLE_BIKE) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
}
}
}
#endif
}
//--MIAMI: done
void CCarAI::CarHasReasonToStop(CVehicle* pVehicle)
{
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
}
//--MIAMI: done
float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
{
if (pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT){
@ -470,6 +630,18 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
}
#ifdef MIAMI
//--MIAMI: done
float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget)
{
GetCarToGoToCoors(pVehicle, pTarget);
pVehicle->bParking = true;
pVehicle->AutoPilot.m_nCruiseSpeed = 10;
return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
}
#endif
//--MIAMI: TODO: MI_VICECHEE
void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
{
if (pVehicle->bOccupantsHaveBeenGenerated)
@ -489,23 +661,43 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 1)
pVehicle->SetupPassenger(0);
return;
#ifdef MIAMI
case MI_PREDATOR:
pVehicle->SetUpDriver();
return;
//TODO(MIAMI) uncomment this when we have MI_VICECHEE
/*
case MI_VICECHEE:
{
pVehicle->SetUpDriver()->bIsMiamiViceCop = true;
pVehicle->SetUpPassenger(0)->bIsMiamiViceCop = true;
CPopulation::NumMiamiViceCops += 2;
CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
return;
}
*/
#endif
default:
return;
}
}
//--MIAMI: done
void CCarAI::AddAmbulanceOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(1);
}
//--MIAMI: done
void CCarAI::AddFiretruckOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(0);
}
//--MIAMI: done
void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
{
if (pVehicle->pDriver){
@ -516,11 +708,38 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
int timer = 100;
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){
if (pVehicle->pPassengers[i]) {
#ifdef MIAMI
pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
timer += CGeneral::GetRandomNumberInRange(200, 400);
#else
pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
#endif
}
}
}
#ifdef MIAMI
//--MIAMI: done
void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)
{
if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {
pVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
if (pVehicle->GetModelIndex() != MI_FIRETRUCK && pVehicle->GetModelIndex() == MI_AMBULAN)
pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);
}
int timer = 100;
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
if (pVehicle->pPassengers[i]) {
pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
timer += CGeneral::GetRandomNumberInRange(200, 400);
}
}
}
#endif
//--MIAMI: done
void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@ -530,6 +749,7 @@ void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
//--MIAMI: done
void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@ -539,6 +759,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
//--MIAMI: done
eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){
@ -553,6 +774,24 @@ eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
}
}
#ifdef MIAMI
//--MIAMI: done
eCarMission CCarAI::FindPoliceBoatMissionForWantedLevel()
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
case 0:
case 1: return MISSION_BLOCKPLAYER_FARAWAY;
case 2:
case 3:
case 4:
case 5:
case 6: return MISSION_ATTACKPLAYER;
default: return MISSION_BLOCKPLAYER_FARAWAY;
}
}
#endif
//--MIAMI: done
int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
@ -567,6 +806,7 @@ int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
}
}
//--MIAMI: done
void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
{
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel == 1){
@ -605,8 +845,31 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 34;
}
}
#ifdef MIAMI
if (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) {
if ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f)
pVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed);
}
#endif
}
#ifdef MIAMI
//--MIAMI: done
void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle)
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
case 0: pVehicle->AutoPilot.m_nCruiseSpeed = 8; break;
case 1: pVehicle->AutoPilot.m_nCruiseSpeed = 10; break;
case 2: pVehicle->AutoPilot.m_nCruiseSpeed = 15; break;
case 3: pVehicle->AutoPilot.m_nCruiseSpeed = 20; break;
case 4: pVehicle->AutoPilot.m_nCruiseSpeed = 25; break;
case 5: pVehicle->AutoPilot.m_nCruiseSpeed = 30; break;
case 6: pVehicle->AutoPilot.m_nCruiseSpeed = 40; break;
}
}
#endif
//--MIAMI: done
void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
{
float flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D();
@ -629,6 +892,10 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
continue;
if (vehicle == pVehicle)
continue;
#ifdef MIAMI
if (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
return;
#endif
if (Abs(pVehicle->GetPosition().z - vehicle->GetPosition().z) >= 5.0f)
continue;
CVector2D distance = vehicle->GetPosition() - pVehicle->GetPosition();

View file

@ -10,17 +10,32 @@ public:
static float FindSwitchDistanceClose(CVehicle*);
static float FindSwitchDistanceFarNormalVehicle(CVehicle*);
static float FindSwitchDistanceFar(CVehicle*);
#ifdef MIAMI
static void BackToCruisingIfNoWantedLevel(CVehicle*);
#endif
static void UpdateCarAI(CVehicle*);
static void CarHasReasonToStop(CVehicle*);
static float GetCarToGoToCoors(CVehicle*, CVector*);
#ifdef MIAMI
static float GetCarToParkAtCoors(CVehicle*, CVector*);
#endif
static void AddPoliceCarOccupants(CVehicle*);
static void AddAmbulanceOccupants(CVehicle*);
static void AddFiretruckOccupants(CVehicle*);
static void TellOccupantsToLeaveCar(CVehicle*);
#ifdef MIAMI
static void TellOccupantsToFleeCar(CVehicle*);
#endif
static void TellCarToRamOtherCar(CVehicle*, CVehicle*);
static void TellCarToBlockOtherCar(CVehicle*, CVehicle*);
static eCarMission FindPoliceCarMissionForWantedLevel();
#ifdef MIAMI
static eCarMission FindPoliceBoatMissionForWantedLevel();
#endif
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static void MellowOutChaseSpeed(CVehicle*);
#ifdef MIAMI
static void MellowOutChaseSpeedBoat(CVehicle*);
#endif
static void MakeWayForCarWithSiren(CVehicle *veh);
};

View file

@ -1641,6 +1641,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
CPathNode* pTargetNode;
int16 numNodes;
float distanceToTargetNode;
#ifndef MIAMI
if (pTarget && pTarget->m_pCurGroundEntity &&
pTarget->m_pCurGroundEntity->IsBuilding() &&
((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() &&
@ -1666,6 +1667,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
#endif
&pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
}else
#endif
{
ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
@ -2749,3 +2751,15 @@ bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
return false;
#endif
}
#ifdef MIAMI
float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
{
switch (type)
{
case 1: return 1.5f;
case 2: return 2.0f;
}
return 1.0f;
}
#endif

View file

@ -104,6 +104,9 @@ public:
static void ClearInterestingVehicleList();
static void FindLinksToGoWithTheseNodes(CVehicle*);
static bool GenerateOneEmergencyServicesCar(uint32, CVector);
#ifdef MIAMI
static float FindSpeedMultiplierWithSpeedFromNodes(int8);
#endif
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{

File diff suppressed because it is too large Load diff

View file

@ -55,6 +55,7 @@ public:
struct CPathNode
{
#ifndef MIAMI
CVector pos;
CPathNode *prev;
CPathNode *next;
@ -80,6 +81,44 @@ struct CPathNode
CPathNode *GetNext(void) { return next; }
void SetPrev(CPathNode *node) { prev = node; }
void SetNext(CPathNode *node) { next = node; }
#else
int16 prevIndex;
int16 nextIndex;
int16 x;
int16 y;
int16 z;
int16 distance; // in path search
int16 firstLink;
int8 width;
int8 group;
uint8 numLinks : 4;
uint8 bDeadEnd : 1;
uint8 bDisabled : 1;
uint8 bBetweenLevels : 1;
uint8 bUseInRoadBlock : 1;
uint8 bWaterPath : 1;
uint8 flagB2 : 1; // flag 2 in node info, always zero
uint8 flagB4 : 1; // where is this set?
uint8 speedLimit : 2;
//uint8 flagB20 : 1;
//uint8 flagB40 : 1;
//uint8 flagB80 : 1;
uint8 spawnRate : 4;
uint8 flagsC : 4;
CVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); }
void SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; }
float GetX(void) { return x/8.0f; }
float GetY(void) { return y/8.0f; }
float GetZ(void) { return z/8.0f; }
CPathNode *GetPrev(void);
CPathNode *GetNext(void);
void SetPrev(CPathNode *node);
void SetNext(CPathNode *node);
#endif
};
union CConnectionFlags
@ -93,6 +132,7 @@ union CConnectionFlags
struct CCarPathLink
{
#ifndef MIAMI
CVector2D pos;
CVector2D dir;
int16 pathNodeIndex;
@ -109,6 +149,26 @@ struct CCarPathLink
float GetY(void) { return pos.y; }
float GetDirX(void) { return dir.x; }
float GetDirY(void) { return dir.y; }
#else
int16 x;
int16 y;
int16 pathNodeIndex;
int8 dirX;
int8 dirY;
int8 numLeftLanes : 3;
int8 numRightLanes : 3;
uint8 flag1 : 1;
uint8 trafficLightType : 2;
uint8 bBridgeLights : 1; // at least in LCS...
int8 width;
CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }
CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }
float GetX(void) { return x/8.0f; }
float GetY(void) { return y/8.0f; }
float GetDirX(void) { return dirX/100.0f; }
float GetDirY(void) { return dirY/100.0f; }
#endif
float OneWayLaneOffset()
{
@ -123,6 +183,7 @@ struct CCarPathLink
// This is what we're reading from the files, only temporary
struct CPathInfoForObject
{
#ifndef MIAMI
int16 x;
int16 y;
int16 z;
@ -131,6 +192,28 @@ struct CPathInfoForObject
int8 numLeftLanes;
int8 numRightLanes;
uint8 crossing : 1;
#else
float x;
float y;
float z;
int8 type;
int8 next;
int8 numLeftLanes;
int8 numRightLanes;
int8 speedLimit;
int8 width;
uint8 crossing : 1;
uint8 flag02 : 1; // always zero
uint8 roadBlock : 1;
uint8 disabled : 1;
uint8 waterPath : 1;
uint8 betweenLevels : 1;
uint8 spawnRate : 4;
void SwapConnectionsToBeRightWayRound(void);
#endif
};
extern CPathInfoForObject *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds;
@ -138,6 +221,7 @@ extern CPathInfoForObject *InfoForTilePeds;
struct CTempNode
{
CVector pos;
#ifndef MIAMI
float dirX;
float dirY;
int16 link1;
@ -145,12 +229,37 @@ struct CTempNode
int8 numLeftLanes;
int8 numRightLanes;
int8 linkState;
#else
int8 dirX; // *100
int8 dirY;
int16 link1;
int16 link2;
int8 numLeftLanes;
int8 numRightLanes;
int8 width;
bool isCross;
int8 linkState;
#endif
};
#ifdef MIAMI
struct CTempNodeExternal // made up name
{
CVector pos;
int16 next;
int8 numLeftLanes;
int8 numRightLanes;
int8 width;
bool isCross;
};
#endif
#ifndef MIAMI
struct CTempDetachedNode // unused
{
uint8 foo[20];
};
#endif
class CPathFind
{
@ -158,10 +267,15 @@ public:
CPathNode m_pathNodes[NUM_PATHNODES];
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
CTreadable *m_mapObjects[NUM_MAPOBJECTS];
#ifndef MIAMI
uint8 m_objectFlags[NUM_MAPOBJECTS];
int16 m_connections[NUM_PATHCONNECTIONS];
int16 m_distances[NUM_PATHCONNECTIONS];
CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS];
#else
uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags
uint8 m_distances[NUM_PATHCONNECTIONS];
#endif
int16 m_carPathConnections[NUM_PATHCONNECTIONS];
int32 m_numPathNodes;
@ -179,12 +293,20 @@ public:
void RegisterMapObject(CTreadable *mapObject);
void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing);
void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight);
#ifndef MIAMI
void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out);
#else
void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);
#endif
bool LoadPathFindData(void);
void PreparePathData(void);
void CountFloodFillGroups(uint8 type);
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
#ifndef MIAMI
float maxdist, CTempDetachedNode *detachednodes, int32 numDetached);
#else
float maxdist, CPathInfoForObject *detachednodes, int32 numDetached);
#endif
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
@ -202,29 +324,56 @@ public:
void MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);
void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
void PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
#ifndef MIAMI
int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false);
#else
//--MIAMI: TODO: check callers for new arguments
int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreFlagB4 = false, bool bWaterPath = false);
#endif
int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
float FindNodeOrientationForCarPlacement(int32 nodeId);
float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards);
bool NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false);
bool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix);
#ifndef MIAMI
CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type);
#endif
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);
void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size);
void Load(uint8 *buf, uint32 size);
#ifdef MIAMI
CPathNode *GetNode(int16 index);
int16 GetIndex(CPathNode *node);
uint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; }
bool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); }
bool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); }
void ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; }
#else
uint16 ConnectedNode(int id) { return m_connections[id]; }
bool ConnectionCrossesRoad(int id) { return m_connectionFlags[id].bCrossesRoad; }
bool ConnectionHasTrafficLight(int id) { return m_connectionFlags[id].bTrafficLight; }
void ConnectionSetTrafficLight(int id) { m_connectionFlags[id].bTrafficLight = true; }
#endif
void DisplayPathData(void);
};
#ifndef MIAMI
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
#endif
extern CPathFind ThePaths;
#ifdef MIAMI
inline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); }
inline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); }
inline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); }
inline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); }
#endif
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;

View file

@ -417,8 +417,10 @@ void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomo
*ppCar = pCar;
}
//--MIAMI: unused
void RemoveUnusedCollision(void)
{
#ifndef MIAMI
static const char* dontDeleteArray[] = {
"rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
"road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
@ -430,6 +432,7 @@ void RemoveUnusedCollision(void)
CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE);
for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
#endif
}
void CRecordDataForChase::StartChaseScene(float startTime)

View file

@ -15,22 +15,40 @@
#include "CarCtrl.h"
#include "General.h"
#ifndef MIAMI
#define ROADBLOCKDIST (80.0f)
#else
#define ROADBLOCKDIST (90.0f)
#endif
int16 CRoadBlocks::NumRoadBlocks;
#ifndef MIAMI
int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS];
#else
int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
#endif
bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
//--MIAMI: TODO: script roadblocks
void
CRoadBlocks::Init(void)
{
int i;
NumRoadBlocks = 0;
#ifndef MIAMI
for (i = 0; i < ThePaths.m_numMapObjects; i++) {
if (ThePaths.m_objectFlags[i] & UseInRoadBlock) {
#else
for(i = 0; i < ThePaths.m_numCarPathNodes; i++){
if(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){
#endif
if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true;
#ifndef MIAMI
RoadBlockObjects[NumRoadBlocks] = i;
#else
RoadBlockNodes[NumRoadBlocks] = i;
#endif
NumRoadBlocks++;
} else {
#ifndef MASTER
@ -110,14 +128,19 @@ CRoadBlocks::GenerateRoadBlocks(void)
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
#ifndef MIAMI
CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]];
CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
#else
CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition();
#endif
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;
@ -187,10 +210,13 @@ CRoadBlocks::GenerateRoadBlocks(void)
}
}
}
#endif
}
}
} else {
InOrOut[nRoadblockNode] = false;
}
}
//--MIAMI: TODO script roadblocks
}

View file

@ -7,7 +7,11 @@ class CRoadBlocks
{
public:
static int16 NumRoadBlocks;
#ifndef MIAMI
static int16 RoadBlockObjects[NUMROADBLOCKS];
#else
static int16 RoadBlockNodes[NUMROADBLOCKS];
#endif
static bool InOrOut[NUMROADBLOCKS];
static void Init(void);

View file

@ -372,6 +372,9 @@ private:
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
#ifdef MIAMI
friend class CColStore;
#endif
};

View file

@ -934,11 +934,13 @@ CCamera::CamControl(void)
if(CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer())
stairs = true;
// Some hack for Mr Whoopee in a bomb shop
#ifndef MIAMI // uhh, check this
if(Cams[ActiveCam].Using3rdPersonMouseCam() && CCollision::ms_collisionInMemory == LEVEL_COMMERCIAL){
if(pTargetEntity->GetPosition().x < 83.0f && pTargetEntity->GetPosition().x > 18.0f &&
pTargetEntity->GetPosition().y < -305.0f && pTargetEntity->GetPosition().y > -390.0f)
disableGarageCam = true;
}
#endif
if(!disableGarageCam && (CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs)){
if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){
if(pToGarageWeAreIn || stairs){

View file

@ -20,6 +20,10 @@
#include "SurfaceTable.h"
#include "Lines.h"
#include "Collision.h"
#ifdef MIAMI
#include "Camera.h"
#include "ColStore.h"
#endif
enum Direction
{
@ -34,22 +38,32 @@ enum Direction
eLevelName CCollision::ms_collisionInMemory;
CLinkList<CColModel*> CCollision::ms_colModelCache;
//--MIAMI: done
void
CCollision::Init(void)
{
ms_colModelCache.Init(NUMCOLCACHELINKS);
ms_collisionInMemory = LEVEL_NONE;
#ifdef MIAMI
CColStore::Initialise();
#endif
}
//--MIAMI: done
void
CCollision::Shutdown(void)
{
ms_colModelCache.Shutdown();
#ifdef MIAMI
CColStore::Shutdown();
#endif
}
//--MIAMI: done
void
CCollision::Update(void)
{
#ifndef MIAMI
CVector playerCoors;
playerCoors = FindPlayerCoors();
eLevelName level = CTheZones::m_CurrLevel;
@ -83,8 +97,10 @@ CCollision::Update(void)
if(ms_collisionInMemory != CGame::currLevel)
LoadCollisionWhenINeedIt(forceLevelChange);
CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
#endif
}
//--MIAMI: unused
eLevelName
GetCollisionInSectorList(CPtrList &list)
{
@ -101,6 +117,7 @@ GetCollisionInSectorList(CPtrList &list)
return LEVEL_NONE;
}
//--MIAMI: unused
// Get a level this sector is in based on collision models
eLevelName
GetCollisionInSector(CSector &sect)
@ -121,9 +138,11 @@ GetCollisionInSector(CSector &sect)
return (eLevelName)level;
}
//--MIAMI: done
void
CCollision::LoadCollisionWhenINeedIt(bool forceChange)
{
#ifndef MIAMI
eLevelName level, l;
bool multipleLevels;
CVector playerCoors;
@ -210,11 +229,14 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange)
CTimer::Update();
DMAudio.SetEffectsFadeVol(127);
}
#endif
}
//--MIAMI: done
void
CCollision::SortOutCollisionAfterLoad(void)
{
#ifndef MIAMI
if(ms_collisionInMemory == CGame::currLevel)
return;
@ -226,6 +248,10 @@ CCollision::SortOutCollisionAfterLoad(void)
}
ms_collisionInMemory = CGame::currLevel;
CGame::TidyUpMemory(true, false);
#else
CColStore::LoadCollision(TheCamera.GetPosition());
CStreaming::LoadAllRequestedModels(false);
#endif
}
void
@ -1974,7 +2000,11 @@ CColModel::CColModel(void)
vertices = nil;
triangles = nil;
trianglePlanes = nil;
#ifndef MIAMI
level = CGame::currLevel;
#else
level = 0; // generic col slot
#endif
ownsCollisionVolumes = true;
}

View file

@ -93,7 +93,11 @@ struct CColModel
int16 numLines;
int16 numBoxes;
int16 numTriangles;
#ifndef MIAMI
int32 level;
#else
uint8 level; // colstore slot but probably same name
#endif
bool ownsCollisionVolumes;
CColSphere *spheres;
CColLine *lines;

View file

@ -24,6 +24,10 @@
#include "ZoneCull.h"
#include "CdStream.h"
#include "FileLoader.h"
#ifdef MIAMI
#include "Streaming.h"
#include "ColStore.h"
#endif
char CFileLoader::ms_line[256];
@ -53,7 +57,9 @@ CFileLoader::LoadLevel(const char *filename)
savedTxd = RwTexDictionaryGetCurrent();
objectsLoaded = false;
#ifndef MIAMI
savedLevel = CGame::currLevel;
#endif
if(savedTxd == nil){
savedTxd = RwTexDictionaryCreate();
RwTexDictionarySetCurrent(savedTxd);
@ -77,12 +83,17 @@ CFileLoader::LoadLevel(const char *filename)
AddTexDictionaries(savedTxd, txd);
RwTexDictionaryDestroy(txd);
}else if(strncmp(line, "COLFILE", 7) == 0){
#ifndef MIAMI
int level;
sscanf(line+8, "%d", &level);
CGame::currLevel = (eLevelName)level;
LoadingScreenLoadingFile(line+10);
LoadCollisionFile(line+10);
CGame::currLevel = savedLevel;
#else
LoadingScreenLoadingFile(line+10);
LoadCollisionFile(line+10, 0);
#endif
}else if(strncmp(line, "MODELFILE", 9) == 0){
LoadingScreenLoadingFile(line + 10);
LoadModelFile(line + 10);
@ -94,8 +105,16 @@ CFileLoader::LoadLevel(const char *filename)
LoadObjectTypes(line + 4);
}else if(strncmp(line, "IPL", 3) == 0){
if(!objectsLoaded){
#ifndef MIAMI
CModelInfo::ConstructMloClumps();
CObjectData::Initialise("DATA\\OBJECT.DAT");
#else
LoadingScreenLoadingFile("Collision");
CObjectData::Initialise("DATA\\OBJECT.DAT");
CStreaming::Init();
CColStore::LoadAllCollision();
// TODO: anim indices
#endif
objectsLoaded = true;
}
LoadingScreenLoadingFile(line + 4);
@ -112,8 +131,18 @@ CFileLoader::LoadLevel(const char *filename)
CFileMgr::CloseFile(fd);
RwTexDictionarySetCurrent(savedTxd);
#ifdef MIAMI
int i;
for(i = 1; i < COLSTORESIZE; i++)
if(CColStore::GetSlot(i))
CColStore::GetBoundingBox(i).Grow(120.0f);
CWorld::RepositionCertainDynamicObjects();
CColStore::RemoveAllCollision();
#endif
}
#ifndef MIAMI
void
CFileLoader::LoadCollisionFromDatFile(int currlevel)
{
@ -137,6 +166,7 @@ CFileLoader::LoadCollisionFromDatFile(int currlevel)
CFileMgr::CloseFile(fd);
}
#endif
char*
CFileLoader::LoadLine(int fd)
@ -178,8 +208,14 @@ struct ColHeader
uint32 size;
};
//--MIAMI: done
#ifndef MIAMI
void
CFileLoader::LoadCollisionFile(const char *filename)
#else
void
CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot)
#endif
{
int fd;
char modelname[24];
@ -196,10 +232,17 @@ CFileLoader::LoadCollisionFile(const char *filename)
mi = CModelInfo::GetModelInfo(modelname, nil);
if(mi){
#ifndef MIAMI
if(mi->GetColModel()){
#else
if(mi->GetColModel() && mi->DoesOwnColModel()){
#endif
LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname);
}else{
CColModel *model = new CColModel;
#ifdef MIAMI
model->level = colSlot;
#endif
LoadCollisionModel(work_buff+24, *model, modelname);
mi->SetColModel(model, true);
}
@ -211,6 +254,82 @@ CFileLoader::LoadCollisionFile(const char *filename)
CFileMgr::CloseFile(fd);
}
#ifdef MIAMI
bool
CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot)
{
uint32 modelsize;
char modelname[24];
CBaseModelInfo *mi;
ColHeader *header;
int modelIndex;
while(size > 8){
header = (ColHeader*)buffer;
modelsize = header->size;
if(strncmp(header->ident, "COLL", 4) != 0)
return size-8 < CDSTREAM_SECTOR_SIZE;
memcpy(modelname, buffer+8, 24);
memcpy(work_buff, buffer+32, modelsize-24);
size -= 32 + (modelsize-24);
buffer += 32 + (modelsize-24);
if(modelsize > 15*1024)
debug("colmodel %s is huge, size %d\n", modelname, modelsize);
mi = CModelInfo::GetModelInfo(modelname, &modelIndex);
if(mi){
if(modelIndex == 855)
modelIndex = modelIndex;
CColStore::IncludeModelIndex(colSlot, modelIndex);
CColModel *model = new CColModel;
model->level = colSlot;
LoadCollisionModel(work_buff, *model, modelname);
mi->SetColModel(model, true);
}else{
debug("colmodel %s can't find a modelinfo\n", modelname);
}
}
return true;
}
bool
CFileLoader::LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot)
{
uint32 modelsize;
char modelname[24];
CBaseModelInfo *mi;
ColHeader *header;
while(size > 8){
header = (ColHeader*)buffer;
modelsize = header->size;
if(strncmp(header->ident, "COLL", 4) != 0)
return size-8 < CDSTREAM_SECTOR_SIZE;
memcpy(modelname, buffer+8, 24);
memcpy(work_buff, buffer+32, modelsize-24);
size -= 32 + (modelsize-24);
buffer += 32 + (modelsize-24);
if(modelsize > 15*1024)
debug("colmodel %s is huge, size %d\n", modelname, modelsize);
mi = CModelInfo::GetModelInfo(modelname, CColStore::GetSlot(colSlot)->minIndex, CColStore::GetSlot(colSlot)->maxIndex);
if(mi){
if(mi->GetColModel()){
LoadCollisionModel(work_buff, *mi->GetColModel(), modelname);
}else{
CColModel *model = new CColModel;
model->level = colSlot;
LoadCollisionModel(work_buff, *model, modelname);
mi->SetColModel(model, true);
}
}else{
debug("colmodel %s can't find a modelinfo\n", modelname);
}
}
return true;
}
#endif
void
CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
{
@ -1063,18 +1182,36 @@ CFileLoader::LoadObjectInstance(const char *line)
CSimpleModelInfo *mi;
RwMatrix *xform;
CEntity *entity;
#ifdef MIAMI
float area;
if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f %f",
&id, name, &area,
&trans.x, &trans.y, &trans.z,
&scale.x, &scale.y, &scale.z,
&axis.x, &axis.y, &axis.z, &angle) != 13){
#endif
if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f",
&id, name,
&trans.x, &trans.y, &trans.z,
&scale.x, &scale.y, &scale.z,
&axis.x, &axis.y, &axis.z, &angle) != 12)
return;
#ifdef MIAMI
area = 0;
}
#endif
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
if(mi == nil)
return;
assert(mi->IsSimple());
#ifdef MIAMI
if(!CStreaming::IsObjectInCdImage(id))
debug("Not in cdimage %s\n", mi->GetName());
#endif
angle = -RADTODEG(2.0f * acosf(angle));
xform = RwMatrixCreate();
RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE);
@ -1089,6 +1226,9 @@ CFileLoader::LoadObjectInstance(const char *line)
entity->SetModelIndexNoCreate(id);
entity->GetMatrix() = CMatrix(xform);
entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition());
#ifdef MIAMI
entity->m_area = area;
#endif
if(mi->IsSimple()){
if(mi->m_isBigBuilding)
entity->SetupBigBuilding();
@ -1098,14 +1238,28 @@ CFileLoader::LoadObjectInstance(const char *line)
if(mi->GetLargestLodDistance() < 2.0f)
entity->bIsVisible = false;
CWorld::Add(entity);
#ifdef MIAMI
CColModel *col = entity->GetColModel();
if(col->numSpheres || col->numBoxes || col->numTriangles){
if(col->level != 0)
CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect());
}else
entity->bUsesCollision = false;
// TODO: set some flag here if col min is below 6
#endif
}else{
entity = new CDummyObject;
entity->SetModelIndexNoCreate(id);
entity->GetMatrix() = CMatrix(xform);
CWorld::Add(entity);
//--MIAMI: TODO
if(IsGlass(entity->GetModelIndex()))
entity->bIsVisible = false;
entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition());
#ifdef MIAMI
entity->m_area = area;
#endif
}
RwMatrixDestroy(xform);

View file

@ -8,7 +8,13 @@ public:
static void LoadCollisionFromDatFile(int currlevel);
static char *LoadLine(int fd);
static RwTexDictionary *LoadTexDictionary(const char *filename);
#ifndef MIAMI
static void LoadCollisionFile(const char *filename);
#else
static void LoadCollisionFile(const char *filename, uint8 colSlot = 0);
static bool LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot);
static bool LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot);
#endif
static void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name);
static void LoadModelFile(const char *filename);
static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data);

View file

@ -624,6 +624,10 @@ public:
void LoadAllTextures();
void LoadSettings();
void MessageScreen(const char *);
#ifdef MIAMI
//--MIAMI: TODO: implement the second argument
void MessageScreen(const char *str, bool) { MessageScreen(str); }
#endif
void PickNewPlayerColour();
void PrintBriefs();
static void PrintErrorMessage();

View file

@ -89,6 +89,9 @@
eLevelName CGame::currLevel;
#ifdef MIAMI
int32 CGame::currArea;
#endif
bool CGame::bDemoMode = true;
bool CGame::nastyGame = true;
bool CGame::frenchGame;
@ -319,7 +322,9 @@ bool CGame::Initialise(const char* datFile)
CDraw::SetFOV(120.0f);
CDraw::ms_fLODDistance = 500.0f;
LoadingScreen("Loading the Game", "Setup streaming", nil);
#ifndef MIAMI
CStreaming::Init();
#endif
CStreaming::LoadInitialVehicles();
CStreaming::LoadInitialPeds();
CStreaming::RequestBigBuildings(LEVEL_NONE);
@ -367,8 +372,10 @@ bool CGame::Initialise(const char* datFile)
CWaterCannons::Init();
CBridge::Init();
CGarages::Init();
#ifndef MIAMI
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
CWorld::RepositionCertainDynamicObjects();
#endif
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
#ifdef GTA_ZONECULL
CCullZones::ResolveVisibilities();
@ -383,7 +390,9 @@ bool CGame::Initialise(const char* datFile)
CTheScripts::Process();
TheCamera.Process();
LoadingScreen("Loading the Game", "Load scene", nil);
#ifndef MIAMI
CModelInfo::RemoveColModelsFromOtherLevels(currLevel);
#endif
CCollision::ms_collisionInMemory = currLevel;
for (int i = 0; i < MAX_PADS; i++)
CPad::GetPad(i)->Clear(true);
@ -523,7 +532,9 @@ void CGame::ReloadIPLs(void)
CRoadBlocks::Init();
CCranes::InitCranes();
CGarages::Init();
#ifndef MIAMI
CWorld::RepositionCertainDynamicObjects();
#endif
#ifdef GTA_ZONECULL
CCullZones::ResolveVisibilities();
#endif

View file

@ -12,6 +12,9 @@ class CGame
{
public:
static eLevelName currLevel;
#ifdef MIAMI
static int32 currArea;
#endif
static bool bDemoMode;
static bool nastyGame;
static bool frenchGame;

View file

@ -80,4 +80,6 @@ public:
~CPlayerInfo() { };
};
#ifndef MIAMI
static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error");
#endif

View file

@ -32,6 +32,10 @@
#include "Replay.h"
#endif
#include "main.h"
#ifdef MIAMI
#include "ColStore.h"
#include "DMAudio.h"
#endif
bool CStreaming::ms_disableStreaming;
bool CStreaming::ms_bLoadingBigModel;
@ -53,7 +57,9 @@ int32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED];
int32 CStreaming::ms_lastVehicleDeleted;
CDirectory *CStreaming::ms_pExtraObjectsDir;
int32 CStreaming::ms_numPriorityRequests;
#ifndef MIAMI
bool CStreaming::ms_hasLoadedLODs;
#endif
int32 CStreaming::ms_currentPedGrp;
int32 CStreaming::ms_currentPedLoading;
int32 CStreaming::ms_lastCullZone;
@ -184,7 +190,9 @@ CStreaming::Init2(void)
ms_pExtraObjectsDir = new CDirectory(EXTRADIRSIZE);
ms_numPriorityRequests = 0;
#ifndef MIAMI
ms_hasLoadedLODs = true;
#endif
ms_currentPedGrp = -1;
ms_lastCullZone = -1; // unused because RemoveModelsNotVisibleFromCullzone is gone
ms_loadedGangs = 0;
@ -231,6 +239,7 @@ CStreaming::Init2(void)
CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd);
CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom);
#ifndef MIAMI
for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){
CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
if(building == nil)
@ -241,6 +250,7 @@ CStreaming::Init2(void)
if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building;
if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building;
}
#endif
}
void
@ -292,21 +302,35 @@ CStreaming::Update(void)
if(CTimer::GetIsPaused())
return;
#ifndef MIAMI
train = FindPlayerTrain();
if(train && train->GetPosition().z < 0.0f){
RequestSubway();
requestedSubway = true;
}else if(!ms_disableStreaming)
AddModelsToRequestList(TheCamera.GetPosition());
#else
LoadBigBuildingsWhenNeeded();
if(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f)
AddModelsToRequestList(TheCamera.GetPosition());
#endif
DeleteFarAwayRwObjects(TheCamera.GetPosition());
if(!ms_disableStreaming &&
#ifndef MIAMI
!CCutsceneMgr::IsRunning() &&
!requestedSubway &&
!CGame::playingIntro &&
#else
!CCutsceneMgr::IsCutsceneProcessing() &&
#endif
ms_numModelsRequested < 5 &&
!CRenderer::m_loadingPriority
#ifdef MIAMI
&& CGame::currArea == 0
// replay is also MIAMI
#endif
#ifdef FIX_BUGS
&& !CReplay::IsPlayingBack()
#endif
@ -317,6 +341,16 @@ CStreaming::Update(void)
LoadRequestedModels();
#ifdef MIAMI
if(CWorld::Players[0].m_pRemoteVehicle){
CColStore::AddCollisionNeededAtPosn(FindPlayerCoors());
CColStore::LoadCollision(CWorld::Players[0].m_pRemoteVehicle->GetPosition());
CColStore::EnsureCollisionIsInMemory(CWorld::Players[0].m_pRemoteVehicle->GetPosition());
}else{
CColStore::LoadCollision(FindPlayerCoors());
CColStore::EnsureCollisionIsInMemory(FindPlayerCoors());
}
#endif
for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
prev = si->m_prev;
@ -375,6 +409,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
imgSelector = n<<24;
assert(sizeof(direntry) == 32);
while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){
#ifndef MIAMI
dot = strchr(direntry.name, '.');
if(dot) *dot = '\0';
if(direntry.size > (uint32)ms_streamingBufferSize)
@ -417,6 +452,64 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
}
}else
lastID = -1;
#else
bool bAddToStreaming = false;
if(direntry.size > (uint32)ms_streamingBufferSize)
ms_streamingBufferSize = direntry.size;
direntry.name[23] = '\0';
dot = strchr(direntry.name, '.');
if(dot == nil || dot-direntry.name > 20){
debug("%s is too long\n", direntry.name);
lastID = -1;
continue;
}
*dot = '\0';
if(!CGeneral::faststricmp(dot+1, "DFF")){
if(CModelInfo::GetModelInfo(direntry.name, &modelId)){
bAddToStreaming = true;
}else{
#ifdef FIX_BUGS
// remember which cdimage this came from
ms_pExtraObjectsDir->AddItem(direntry, n);
#else
ms_pExtraObjectsDir->AddItem(direntry);
#endif
lastID = -1;
}
}else if(!CGeneral::faststricmp(dot+1, "TXD")){
modelId = CTxdStore::FindTxdSlot(direntry.name);
if(modelId == -1)
modelId = CTxdStore::AddTxdSlot(direntry.name);
modelId += STREAM_OFFSET_TXD;
bAddToStreaming = true;
}else if(!CGeneral::faststricmp(dot+1, "COL")){
modelId = CColStore::FindColSlot(direntry.name);
if(modelId == -1)
modelId = CColStore::AddColSlot(direntry.name);
modelId += STREAM_OFFSET_COL;
bAddToStreaming = true;
// TODO: IFP
}else{
*dot = '.';
lastID = -1;
}
if(bAddToStreaming){
if(ms_aInfoForModel[modelId].GetCdSize()){
debug("%s.%s appears more than once in %s\n", direntry.name, dot+1, dirname);
lastID = -1;
}else{
direntry.offset |= imgSelector;
ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size);
if(lastID != -1)
ms_aInfoForModel[lastID].m_nextID = modelId;
lastID = modelId;
}
}
#endif
}
CFileMgr::CloseFile(fd);
@ -440,6 +533,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);
if(streamId < STREAM_OFFSET_TXD){
//--MIAMI: also check animation
// Model
mi = CModelInfo::GetModelInfo(streamId);
@ -481,7 +575,11 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
RwStreamClose(stream, &mem);
return false;
}
#ifndef MIAMI
}else{
#else
}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){
#endif
// Txd
assert(streamId < NUMSTREAMINFO);
if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 &&
@ -506,10 +604,22 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
RwStreamClose(stream, &mem);
return false;
}
#ifdef MIAMI
}else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO){
if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){
debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL));
RemoveModel(streamId);
ReRequestModel(streamId);
RwStreamClose(stream, &mem);
return false;
}
// TODO: IFPs
#endif
}
RwStreamClose(stream, &mem);
#ifndef MIAMI
// We shouldn't even end up here unless load was successful
if(!success){
ReRequestModel(streamId);
@ -519,6 +629,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
debug("Failed to load %s.txd\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD));
return false;
}
#endif
if(streamId < STREAM_OFFSET_TXD){
// Model
@ -537,7 +648,11 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0)
ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);
}
#ifndef MIAMI
}else{
#else
}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ // TODO: animations
#endif
// Txd
if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0)
ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);
@ -552,10 +667,23 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
if(timeDiff > 5){
#ifndef MIAMI
if(streamId < STREAM_OFFSET_TXD)
debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff);
else
debug("txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff);
#else
// TODO: is this inlined?
static char objname[32];
if(streamId < STREAM_OFFSET_TXD)
sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName());
else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)
sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));
else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO)
sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL));
// TODO: IFP
debug("%s took %d ms\n", objname, timeDiff);
#endif
}
return true;
@ -713,7 +841,11 @@ CStreaming::RequestSubway(void)
}
}
#ifndef MIAMI
#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY
#else
#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE
#endif
void
CStreaming::RequestBigBuildings(eLevelName level)
@ -725,12 +857,54 @@ CStreaming::RequestBigBuildings(eLevelName level)
for(i = n; i >= 0; i--){
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding && b->m_level == level)
#ifdef MIAMI
if(!b->bStreamBIGBuilding)
#endif
RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);
}
RequestIslands(level);
#ifndef MIAMI
ms_hasLoadedLODs = false;
#endif
}
#ifdef MIAMI
void
CStreaming::RequestBigBuildings(eLevelName level, const CVector &pos)
{
int i, n;
CBuilding *b;
n = CPools::GetBuildingPool()->GetSize()-1;
for(i = n; i >= 0; i--){
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding && b->m_level == level)
if(b->bStreamBIGBuilding){
if(CRenderer::ShouldModelBeStreamed(b))
RequestModel(b->GetModelIndex(), 0);
}else
RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);
}
RequestIslands(level);
}
void
CStreaming::InstanceBigBuildings(eLevelName level, const CVector &pos)
{
int i, n;
CBuilding *b;
n = CPools::GetBuildingPool()->GetSize()-1;
for(i = n; i >= 0; i--){
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding && b->m_level == level &&
b->bStreamBIGBuilding && b->m_rwObject == nil)
if(CRenderer::ShouldModelBeStreamed(b))
b->CreateRwObject();
}
}
#endif
void
CStreaming::RequestIslands(eLevelName level)
{
@ -828,10 +1002,20 @@ CStreaming::RemoveModel(int32 id)
return;
if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){
#ifndef MIAMI
if(id < STREAM_OFFSET_TXD)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
#else
if(id < STREAM_OFFSET_TXD)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
// TODO: IFP
#endif
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
}
@ -850,15 +1034,26 @@ CStreaming::RemoveModel(int32 id)
}
if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){
#ifndef MIAMI
if(id < STREAM_OFFSET_TXD)
RpClumpGtaCancelStream();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
#else
if(id < STREAM_OFFSET_TXD)
RpClumpGtaCancelStream();
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
// TODO: IFP
#endif
}
ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;
}
//--MIAMI: change islands
void
CStreaming::RemoveUnusedBuildings(eLevelName level)
{
@ -870,6 +1065,7 @@ CStreaming::RemoveUnusedBuildings(eLevelName level)
RemoveBuildings(LEVEL_SUBURBAN);
}
//--MIAMI: done
void
CStreaming::RemoveBuildings(eLevelName level)
{
@ -930,6 +1126,7 @@ CStreaming::RemoveBuildings(eLevelName level)
}
}
//--MIAMI: change islands
void
CStreaming::RemoveUnusedBigBuildings(eLevelName level)
{
@ -958,6 +1155,21 @@ DeleteIsland(CEntity *island)
void
CStreaming::RemoveIslandsNotUsed(eLevelName level)
{
#ifdef MIAMI
int i;
if(pIslandLODindustEntity == nil)
for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){
CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
if(building == nil)
continue;
if(building->GetModelIndex() == islandLODindust) pIslandLODindustEntity = building;
if(building->GetModelIndex() == islandLODcomInd) pIslandLODcomIndEntity = building;
if(building->GetModelIndex() == islandLODcomSub) pIslandLODcomSubEntity = building;
if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building;
if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building;
}
#endif
switch(level){
case LEVEL_INDUSTRIAL:
DeleteIsland(pIslandLODindustEntity);
@ -984,6 +1196,7 @@ CStreaming::RemoveIslandsNotUsed(eLevelName level)
}
}
//--MIAMI: done
void
CStreaming::RemoveBigBuildings(eLevelName level)
{
@ -1187,6 +1400,7 @@ CStreaming::IsObjectInCdImage(int32 id)
return ms_aInfoForModel[id].GetCdPosnAndSize(posn, size);
}
#ifndef MIAMI
void
CStreaming::HaveAllBigBuildingsLoaded(eLevelName level)
{
@ -1221,6 +1435,7 @@ CStreaming::HaveAllBigBuildingsLoaded(eLevelName level)
RemoveUnusedBigBuildings(level);
ms_hasLoadedLODs = true;
}
#endif
void
CStreaming::SetModelIsDeletable(int32 id)
@ -1454,6 +1669,44 @@ CStreaming::RemoveCurrentZonesModels(void)
ms_loadedGangCars = 0;
}
#ifdef MIAMI
void
CStreaming::LoadBigBuildingsWhenNeeded(void)
{
// Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt
if(CCutsceneMgr::IsCutsceneProcessing())
return;
if(CTheZones::m_CurrLevel == LEVEL_NONE ||
CTheZones::m_CurrLevel == CGame::currLevel)
return;
CTimer::Suspend();
CGame::currLevel = CTheZones::m_CurrLevel;
DMAudio.SetEffectsFadeVol(0);
CPad::StopPadsShaking();
CCollision::LoadCollisionScreen(CGame::currLevel);
DMAudio.Service();
// CPopulation::DealWithZoneChange is unused in VC
RemoveUnusedBigBuildings(CGame::currLevel);
RemoveUnusedBuildings(CGame::currLevel);
RemoveUnusedModelsInLoadedList();
CGame::TidyUpMemory(true, true);
CReplay::EmptyReplayBuffer();
if(CGame::currLevel != LEVEL_NONE)
LoadSplash(GetLevelSplashScreen(CGame::currLevel));
CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition());
CStreaming::LoadAllRequestedModels(true);
CGame::TidyUpMemory(true, true);
CTimer::Resume();
DMAudio.SetEffectsFadeVol(127);
}
#endif
// Find starting offset of the cdimage we next want to read
// Not useful at all on PC...
@ -2438,11 +2691,33 @@ CStreaming::LoadScene(const CVector &pos)
CCullZones::ForceCullZoneCoors(pos);
#endif
DeleteAllRwObjects();
#ifndef MIAMI
AddModelsToRequestList(pos);
CRadar::StreamRadarSections(pos);
RemoveUnusedBigBuildings(level);
RequestBigBuildings(level);
LoadAllRequestedModels(false);
#else
if(level == LEVEL_NONE)
level = CGame::currLevel;
CGame::currLevel = level;
RemoveUnusedBigBuildings(level);
RequestBigBuildings(level, pos);
RequestBigBuildings(LEVEL_NONE, pos);
RemoveIslandsNotUsed(level);
LoadAllRequestedModels(false);
InstanceBigBuildings(level, pos);
InstanceBigBuildings(LEVEL_NONE, pos);
AddModelsToRequestList(pos);
CRadar::StreamRadarSections(pos);
// TODO: stream zone vehicles
LoadAllRequestedModels(false);
// TODO: InstanceLoadedModels
for(int i = 0; i < NUMSTREAMINFO; i++)
ms_aInfoForModel[i].m_flags &= ~STREAMFLAGS_20;
#endif
debug("End load scene\n");
}

View file

@ -4,7 +4,12 @@
enum {
STREAM_OFFSET_TXD = MODELINFOSIZE,
#ifndef MIAMI
NUMSTREAMINFO = STREAM_OFFSET_TXD+TXDSTORESIZE
#else
STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,
NUMSTREAMINFO = STREAM_OFFSET_COL+COLSTORESIZE
#endif
};
enum StreamFlags
@ -14,6 +19,9 @@ enum StreamFlags
STREAMFLAGS_DEPENDENCY = 0x04, // Is this right?
STREAMFLAGS_PRIORITY = 0x08,
STREAMFLAGS_NOFADE = 0x10,
#ifdef MIAMI
STREAMFLAGS_20 = 0x20,
#endif
STREAMFLAGS_CANT_REMOVE = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED,
STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY,
@ -94,7 +102,9 @@ public:
static int32 ms_lastVehicleDeleted;
static CDirectory *ms_pExtraObjectsDir;
static int32 ms_numPriorityRequests;
#ifndef MIAMI
static bool ms_hasLoadedLODs;
#endif
static int32 ms_currentPedGrp;
static int32 ms_lastCullZone;
static uint16 ms_loadedGangs;
@ -115,14 +125,28 @@ public:
static bool FinishLoadingLargeFile(int8 *buf, int32 streamId);
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }
#ifdef MIAMI
static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }
#endif
static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }
static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }
#ifdef MIAMI
static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }
#endif
static void RequestModel(int32 model, int32 flags);
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
#ifdef MIAMI
static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }
static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }
#endif
static void RequestSubway(void);
static void RequestBigBuildings(eLevelName level);
#ifdef MIAMI
static void RequestBigBuildings(eLevelName level, const CVector &pos);
static void InstanceBigBuildings(eLevelName level, const CVector &pos);
#endif
static void RequestIslands(eLevelName level);
static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags);
static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags);
@ -131,6 +155,9 @@ public:
static void DecrementRef(int32 id);
static void RemoveModel(int32 id);
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
#ifdef MIAMI
static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }
#endif
static void RemoveUnusedBuildings(eLevelName level);
static void RemoveBuildings(eLevelName level);
static void RemoveUnusedBigBuildings(eLevelName level);
@ -145,7 +172,9 @@ public:
static bool IsTxdUsedByRequestedModels(int32 txdId);
static bool AddToLoadedVehiclesList(int32 modelId);
static bool IsObjectInCdImage(int32 id);
#ifndef MIAMI
static void HaveAllBigBuildingsLoaded(eLevelName level);
#endif
static void SetModelIsDeletable(int32 id);
static void SetModelTxdIsDeletable(int32 id);
static void SetMissionDoesntRequireModel(int32 id);
@ -154,6 +183,9 @@ public:
static void StreamVehiclesAndPeds(void);
static void StreamZoneModels(const CVector &pos);
static void RemoveCurrentZonesModels(void);
#ifdef MIAMI
static void LoadBigBuildingsWhenNeeded(void);
#endif
static int32 GetCdImageOffset(int32 lastPosn);
static int32 GetNextFileOnCd(int32 position, bool priority);

View file

@ -122,4 +122,9 @@ public:
static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set);
static void CompressIndicesArray() {};// todo
#ifdef MIAMI
//--MIAMI: TODO
static bool PoliceAbandonCars(void) { return false; }
#endif
};

View file

@ -7,8 +7,14 @@ enum Config {
MAX_CDIMAGES = 8, // additional cdimages
MAX_CDCHANNELS = 5,
#ifndef MIAMI
MODELINFOSIZE = 5500,
TXDSTORESIZE = 850,
#else
MODELINFOSIZE = 6500,
TXDSTORESIZE = 1385,
COLSTORESIZE = 31,
#endif
EXTRADIRSIZE = 128,
CUTSCENEDIRSIZE = 512,
@ -41,10 +47,17 @@ enum Config {
NUMTEMPOBJECTS = 30,
// Path data
#ifndef MIAMI
NUM_PATHNODES = 4930,
NUM_CARPATHLINKS = 2076,
NUM_MAPOBJECTS = 1250,
NUM_PATHCONNECTIONS = 10260,
#else
NUM_PATHNODES = 9650,
NUM_CARPATHLINKS = 3500,
NUM_MAPOBJECTS = 1250,
NUM_PATHCONNECTIONS = 20400,
#endif
// Link list lengths
NUMALPHALIST = 20,
@ -110,7 +123,11 @@ enum Config {
NUMMODELSPERPEDGROUP = 8,
NUMSHOTINFOS = 100,
#ifndef MIAMI
NUMROADBLOCKS = 600,
#else
NUMROADBLOCKS = 300,
#endif
NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150,

View file

@ -39,13 +39,20 @@ public:
m_entries = (U*)malloc(sizeof(U)*size);
m_flags = (Flags*)malloc(sizeof(Flags)*size);
m_size = size;
#ifndef MIAMI
m_allocPtr = 0;
#else
m_allocPtr = -1;
#endif
for(int i = 0; i < size; i++){
m_flags[i].id = 0;
m_flags[i].free = 1;
}
}
#ifdef MIAMI
CPool(int size, const char *name)
: CPool(size) {}
#endif
~CPool() {
Flush();
}

View file

@ -52,6 +52,9 @@ CEntity::CEntity(void)
bRenderScorched = false;
bHasBlip = false;
bIsBIGBuilding = false;
#ifdef MIAMI
bStreamBIGBuilding = false;
#endif
bRenderDamaged = false;
bBulletProof = false;
@ -345,6 +348,11 @@ CEntity::SetupBigBuilding(void)
bStreamingDontDelete = true;
bUsesCollision = false;
m_level = CTheZones::GetLevelFromPosition(GetPosition());
#ifdef MIAMI
if(mi->m_lodDistances[0] <= 2000.0f)
bStreamBIGBuilding = true;
// TODO: the stuff down there isn't right yet
#endif
if(m_level == LEVEL_NONE){
if(mi->GetTxdSlot() != CTxdStore::FindTxdSlot("generic")){
mi->SetTexDictionary("generic");

View file

@ -59,6 +59,9 @@ public:
uint32 bRenderScorched : 1;
uint32 bHasBlip : 1;
uint32 bIsBIGBuilding : 1; // Set if this entity is a big building
#ifdef MIAMI
uint32 bStreamBIGBuilding : 1; // set when draw dist <= 2000
#endif
uint32 bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage
// flagsC
@ -90,7 +93,12 @@ public:
uint16 m_scanCode;
uint16 m_randomSeed;
int16 m_modelIndex;
#ifndef MIAMI
uint16 m_level; // int16
#else
int8 m_level;
int8 m_area;
#endif
CReference *m_pFirstReference;
public:

View file

@ -267,6 +267,7 @@ void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{
if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
#ifndef MIAMI
CTreadable *t = (CTreadable*)ent;
if(t->m_nodeIndices[PATH_PED][0] >= 0 ||
t->m_nodeIndices[PATH_PED][1] >= 0 ||
@ -278,6 +279,7 @@ CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
t->m_nodeIndices[PATH_CAR][2] >= 0 ||
t->m_nodeIndices[PATH_CAR][3] >= 0)
m_treadable[PATH_CAR] = t;
#endif
}
}

View file

@ -8,8 +8,12 @@ public:
static void *operator new(size_t);
static void operator delete(void*, size_t);
#ifndef MIAMI
int16 m_nodeIndices[2][12]; // first car, then ped
#endif
bool GetIsATreadable(void) { return true; }
};
#ifndef MIAMI
static_assert(sizeof(CTreadable) == 0x94, "CTreadable: error");
#endif

View file

@ -200,6 +200,20 @@ CModelInfo::GetModelInfo(const char *name, int *id)
return nil;
}
#ifdef MIAMI
CBaseModelInfo*
CModelInfo::GetModelInfo(const char *name, int minIndex, int maxIndex)
{
CBaseModelInfo *modelinfo;
for(int i = minIndex; i <= maxIndex; i++){
modelinfo = CModelInfo::ms_modelInfoPtrs[i];
if(modelinfo && !CGeneral::faststricmp(modelinfo->GetName(), name))
return modelinfo;
}
return nil;
}
#endif
bool
CModelInfo::IsBoatModel(int32 id)
{
@ -214,6 +228,7 @@ CModelInfo::IsBikeModel(int32 id)
((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE;
}
#ifndef MIAMI
void
CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
{
@ -230,6 +245,7 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
}
}
}
#endif
void
CModelInfo::ConstructMloClumps()

View file

@ -42,6 +42,9 @@ public:
static CBaseModelInfo *GetModelInfo(int id){
return ms_modelInfoPtrs[id];
}
#ifdef MIAMI
static CBaseModelInfo *GetModelInfo(const char *name, int minIndex, int maxIndex);
#endif
static bool IsBoatModel(int32 id);
static bool IsBikeModel(int32 id);

View file

@ -130,6 +130,16 @@ CSimpleModelInfo::GetAtomicFromDistance(float dist)
return nil;
}
#ifdef MIAMI
RpAtomic*
CSimpleModelInfo::GetFirstAtomicFromDistance(float dist)
{
if(dist < m_lodDistances[0] * TheCamera.LODDistMultiplier)
return m_atomics[0];
return nil;
}
#endif
void
CSimpleModelInfo::FindRelatedModel(void)
{

View file

@ -40,6 +40,9 @@ public:
float GetNearDistance(void);
float GetLargestLodDistance(void);
RpAtomic *GetAtomicFromDistance(float dist);
#ifdef MIAMI
RpAtomic *GetFirstAtomicFromDistance(float dist); // inline
#endif
void FindRelatedModel(void);
void SetupBigBuilding(void);

View file

@ -187,8 +187,10 @@ CCivilianPed::CivilianAI(void)
void
CCivilianPed::ProcessControl(void)
{
#ifndef MIAMI
if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
return;
#endif
CPed::ProcessControl();

View file

@ -425,8 +425,14 @@ CCopPed::CopAI(void)
#ifdef VC_PED_PORTS
float dotProd;
if (m_nRoadblockNode != -1) {
#ifndef MIAMI
CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
#else
// TODO: check this, i'm only getting this compile here....
CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]];
dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition());
#endif
} else
dotProd = -1.0f;
@ -559,8 +565,10 @@ CCopPed::CopAI(void)
void
CCopPed::ProcessControl(void)
{
#ifndef MIAMI
if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
return;
#endif
CPed::ProcessControl();
if (bWasPostponed)

View file

@ -44,8 +44,10 @@ CEmergencyPed::InRange(CPed *victim)
void
CEmergencyPed::ProcessControl(void)
{
#ifndef MIAMI
if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
return;
#endif
CPed::ProcessControl();
if (bWasPostponed)

View file

@ -9397,8 +9397,10 @@ CPed::ProcessControl(void)
CColPoint foundCol;
CEntity *foundEnt = nil;
#ifndef MIAMI
if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
return;
#endif
int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
if (!bFadeOut) {

View file

@ -858,6 +858,7 @@ CPopulation::AddPedInCar(CVehicle* car)
void
CPopulation::MoveCarsAndPedsOutOfAbandonedZones()
{
#ifndef MIAMI
eLevelName level;
int zone;
int frame = CTimer::GetFrameCounter() & 7;
@ -940,6 +941,7 @@ CPopulation::MoveCarsAndPedsOutOfAbandonedZones()
}
}
}
#endif
}
void

View file

@ -194,6 +194,7 @@ CRenderer::RenderRoads(void)
t = (CTreadable*)ms_aVisibleEntityPtrs[i];
if(t->IsBuilding() && t->GetIsATreadable()){
#ifndef MASTER
#ifndef MIAMI
if(gbShowCarRoadGroups || gbShowPedRoadGroups){
int ind = 0;
if(gbShowCarRoadGroups)
@ -202,6 +203,7 @@ CRenderer::RenderRoads(void)
ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group;
SetAmbientColoursToIndicateRoadGroup(ind);
}
#endif
#endif
RenderOneRoad(t);
#ifndef MASTER
@ -326,6 +328,7 @@ enum Visbility
int32
CRenderer::SetupEntityVisibility(CEntity *ent)
{
#ifndef MIAMI
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);
CTimeModelInfo *ti;
int32 other;
@ -471,11 +474,164 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
ent->bDistanceFade = true;
return VIS_OFFSCREEN; // Why this?
}
#else
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);
CTimeModelInfo *ti;
int32 other;
float dist;
bool request = true;
if(mi->GetModelType() == MITYPE_TIME){
ti = (CTimeModelInfo*)mi;
other = ti->GetOtherTimeModel();
if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){
// don't fade in, or between time objects
if(CANTIMECULL)
ti->m_alpha = 255;
}else{
// Hide if possible
if(CANTIMECULL)
return VIS_INVISIBLE;
// can't cull, so we'll try to draw this one, but don't request
// it since what we really want is the other one.
request = false;
}
}else{
// TODO(MIAMI): weapon
if(mi->GetModelType() != MITYPE_SIMPLE){
if(FindPlayerVehicle() == ent &&
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){
// Player's vehicle in first person mode
if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD ||
ent->GetModelIndex() == MI_RHINO ||
ent->GetModelIndex() == MI_COACH ||
TheCamera.m_bInATunnelAndABigVehicle){
ent->bNoBrightHeadLights = true;
}else{
m_pFirstPersonVehicle = (CVehicle*)ent;
ent->bNoBrightHeadLights = false;
}
return VIS_OFFSCREEN;
}else{
// All sorts of Clumps
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
// TODO(MIAMI): occlusion
if(!ent->GetIsOnScreen())
return VIS_OFFSCREEN;
if(ent->bDrawLast){
dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = false;
return VIS_INVISIBLE;
}else
return VIS_VISIBLE;
}
return VIS_INVISIBLE;
}
// TODO(MIAMI): this is different
if(ent->IsObject() &&
((CObject*)ent)->ObjectCreatedBy == TEMP_OBJECT){
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
return ent->GetIsOnScreen() ? VIS_VISIBLE : VIS_OFFSCREEN;
}
}
// Simple ModelInfo
// TODO(MIAMI): area
dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();
if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE)
dist += mi->GetLargestLodDistance() - 300.0f;
if(ent->IsObject() && ent->bRenderDamaged)
mi->m_isDamaged = true;
RpAtomic *a = mi->GetAtomicFromDistance(dist);
if(a){
mi->m_isDamaged = false;
if(ent->m_rwObject == nil)
ent->CreateRwObject();
assert(ent->m_rwObject);
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
// Make sure our atomic uses the right geometry and not
// that of an atomic for another draw distance.
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
mi->IncreaseAlpha();
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
if(!ent->GetIsOnScreen()){
mi->m_alpha = 255;
return VIS_OFFSCREEN;
}
if(mi->m_alpha != 255){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = true;
return VIS_INVISIBLE;
}
if(mi->m_drawLast || ent->bDrawLast){
if(CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist)){
ent->bDistanceFade = false;
return VIS_INVISIBLE;
}
}
return VIS_VISIBLE;
}
// Object is not loaded, figure out what to do
if(mi->m_noFade){
mi->m_isDamaged = false;
// request model
if(dist - STREAM_DISTANCE < mi->GetLargestLodDistance() && request)
return VIS_STREAMME;
return VIS_INVISIBLE;
}
// We might be fading
a = mi->GetAtomicFromDistance(dist - FADE_DISTANCE);
mi->m_isDamaged = false;
if(a == nil){
// request model
if(dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance() && request)
return VIS_STREAMME;
return VIS_INVISIBLE;
}
if(ent->m_rwObject == nil)
ent->CreateRwObject();
assert(ent->m_rwObject);
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
mi->IncreaseAlpha();
if(ent->m_rwObject == nil || !ent->bIsVisible)
return VIS_INVISIBLE;
// TODO(MIAMI): occlusion
if(!ent->GetIsOnScreen()){
mi->m_alpha = 255;
return VIS_OFFSCREEN;
}else{
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = true;
return VIS_OFFSCREEN; // Why this?
}
#endif
}
int32
CRenderer::SetupBigBuildingVisibility(CEntity *ent)
{
#ifndef MIAMI
CSimpleModelInfo *mi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());
CTimeModelInfo *ti;
int32 other;
@ -557,6 +713,121 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
if(ent->IsVisibleComplex())
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
return VIS_INVISIBLE;
#else
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);
CTimeModelInfo *ti;
int32 other;
// TODO(MIAMI): area
bool request = true;
if(mi->GetModelType() == MITYPE_TIME){
ti = (CTimeModelInfo*)mi;
other = ti->GetOtherTimeModel();
if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){
// don't fade in, or between time objects
if(CANTIMECULL)
ti->m_alpha = 255;
}else{
// Hide if possible
if(CANTIMECULL){
ent->DeleteRwObject();
return VIS_INVISIBLE;
}
// can't cull, so we'll try to draw this one, but don't request
// it since what we really want is the other one.
request = false;
}
}else if(mi->GetModelType() == MITYPE_VEHICLE)
return ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE;
float dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude();
CSimpleModelInfo *nonLOD = mi->GetRelatedModel();
// Find out whether to draw below near distance.
// This is only the case if there is a non-LOD which is either not
// loaded or not completely faded in yet.
if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE){
// No non-LOD or non-LOD is completely visible.
if(nonLOD == nil ||
nonLOD->GetRwObject() && nonLOD->m_alpha == 255)
return VIS_INVISIBLE;
// But if it is a time object, we'd rather draw the wrong
// non-LOD than the right LOD.
if(nonLOD->GetModelType() == MITYPE_TIME){
ti = (CTimeModelInfo*)nonLOD;
other = ti->GetOtherTimeModel();
if(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject())
return VIS_INVISIBLE;
}
}
RpAtomic *a = mi->GetFirstAtomicFromDistance(dist);
if(a){
if(ent->m_rwObject == nil)
ent->CreateRwObject();
assert(ent->m_rwObject);
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
// Make sure our atomic uses the right geometry and not
// that of an atomic for another draw distance.
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
mi->IncreaseAlpha();
// TODO(MIAMI): occlusion
if(!ent->IsVisibleComplex()){
mi->m_alpha = 255;
return VIS_INVISIBLE;
}
if(mi->m_alpha != 255){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = true;
return VIS_INVISIBLE;
}
if(mi->m_drawLast){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = false;
return VIS_INVISIBLE;
}
return VIS_VISIBLE;
}
if(mi->m_noFade){
ent->DeleteRwObject();
return VIS_INVISIBLE;
}
// get faded atomic
a = mi->GetFirstAtomicFromDistance(dist - FADE_DISTANCE);
if(a == nil){
if(ent->bStreamBIGBuilding && dist-STREAM_DISTANCE < mi->GetLodDistance(0) && request){
return ent->GetIsOnScreen() ? VIS_STREAMME : VIS_INVISIBLE;
}else{
ent->DeleteRwObject();
return VIS_INVISIBLE;
}
}
// Fade...
if(ent->m_rwObject == nil)
ent->CreateRwObject();
assert(ent->m_rwObject);
RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;
if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))
RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
mi->IncreaseAlpha();
// TODO(MIAMI): occlusion
if(ent->IsVisibleComplex()){
CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);
ent->bDistanceFade = true;
}else
mi->m_alpha = 255;
return VIS_INVISIBLE;
#endif
}
void
@ -703,7 +974,11 @@ CRenderer::ScanWorld(void)
}
ScanSectorPoly(poly, 3, ScanSectorList);
#ifndef MIAMI
ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory));
#else
ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel));
#endif
ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_NONE));
}
}
@ -948,11 +1223,27 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
CPtrNode *node;
CEntity *ent;
#ifndef MIAMI
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
}
#else
// TODO(MIAMI): some flags and such
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
switch(SetupBigBuildingVisibility(ent)){
case VIS_VISIBLE:
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
break;
case VIS_STREAMME:
if(!CStreaming::ms_disableStreaming)
CStreaming::RequestModel(ent->GetModelIndex(), 0);
break;
}
}
#endif
}
void

View file

@ -543,11 +543,13 @@ RestoreForStartLoad()
ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z);
CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
CStreaming::RemoveUnusedBuildings(CGame::currLevel);
#ifndef MIAMI
CCollision::SortOutCollisionAfterLoad();
CStreaming::RequestBigBuildings(CGame::currLevel);
CStreaming::LoadAllRequestedModels(false);
CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
CGame::TidyUpMemory(true, false);
#endif
if (CloseFile(file)) {
return true;

View file

@ -229,9 +229,11 @@ CAutomobile::ProcessControl(void)
colModel = GetColModel();
bWarnedPeds = false;
#ifndef MIAMI
// skip if the collision isn't for the current level
if(colModel->level > LEVEL_NONE && colModel->level != CCollision::ms_collisionInMemory)
return;
#endif
// Improve grip of vehicles in certain cases
bool strongGrip1 = false;

View file

@ -197,8 +197,6 @@ public:
static void SetAllTaxiLights(bool set);
};
static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error");
inline uint8 GetCarDoorFlag(int32 carnode) {
switch (carnode) {
case CAR_DOOR_LF:

View file

@ -109,8 +109,10 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
void
CBoat::ProcessControl(void)
{
#ifndef MIAMI
if(m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
return;
#endif
bool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f;

View file

@ -72,8 +72,6 @@ public:
};
static_assert(sizeof(CBoat) == 0x484, "CBoat: error");
extern float MAX_WAKE_LENGTH;
extern float MIN_WAKE_INTERVAL;
extern float WAKE_LIFETIME;

View file

@ -95,4 +95,3 @@ public:
static void ActivateHeli(bool activate);
};
static_assert(sizeof(CHeli) == 0x33C, "CHeli: error");

View file

@ -63,7 +63,6 @@ public:
static bool HasCesnaBeenDestroyed(void);
static bool HasDropOffCesnaBeenShotDown(void);
};
static_assert(sizeof(CPlane) == 0x29C, "CPlane: error");
extern float LandingPoint;
extern float TakeOffPoint;

View file

@ -91,4 +91,3 @@ public:
float *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail);
static void UpdateTrains(void);
};
static_assert(sizeof(CTrain) == 0x2E4, "CTrain: error");

View file

@ -99,6 +99,9 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_bSirenOrAlarm = 0;
m_nCarHornTimer = 0;
m_nCarHornPattern = 0;
#ifdef MIAMI
bParking = false;
#endif
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
m_nLastWeaponDamage = -1;
@ -118,6 +121,9 @@ CVehicle::CVehicle(uint8 CreatedBy)
AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
AutoPilot.m_bStayInCurrentLevel = false;
AutoPilot.m_bIgnorePathfinding = false;
#ifdef MIAMI
AutoPilot.m_nSwitchDistance = 20;
#endif
}
CVehicle::~CVehicle()
@ -1347,3 +1353,23 @@ CVehicle::Load(uint8*& buf)
SkipSaveBuf(buf, 99);
}
#endif
#ifdef MIAMI
eVehicleAppearance
//--MIAMI: TODO, implement VC version, appearance != type
// This would work for cars, boats and bikes but not for planes and helis
CVehicle::GetVehicleAppearance(void)
{
if (IsCar())
return VEHICLE_CAR;
if (IsBoat())
return VEHICLE_BOAT;
if (IsBike())
return VEHICLE_BIKE;
if (IsPlane())
return VEHICLE_PLANE;
if (IsHeli())
return VEHICLE_HELI;
return VEHICLE_NONE;
}
#endif

View file

@ -109,6 +109,18 @@ enum eFlightModel
FLIGHT_MODEL_SEAPLANE
};
#ifdef MIAMI
enum eVehicleAppearance
{
VEHICLE_NONE,
VEHICLE_CAR,
VEHICLE_BIKE,
VEHICLE_HELI,
VEHICLE_BOAT,
VEHICLE_PLANE,
};
#endif
// Or Weapon.h?
void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage);
@ -172,6 +184,10 @@ public:
uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command
uint8 bHasAlreadyBeenRecorded : 1; // Used for replays
#ifdef MIAMI
uint8 bParking : 1;
#endif;
int8 m_numPedsUseItAsCover;
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
int8 m_nPacManPickupsCarried;
@ -236,6 +252,9 @@ public:
virtual void Load(uint8*& buf);
#endif
#ifdef MIAMI
eVehicleAppearance GetVehicleAppearance(void);
#endif
bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; }
bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; }
bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
@ -291,9 +310,4 @@ public:
static bool m_bDisableMouseSteering;
};
static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error");
static_assert(offsetof(CVehicle, m_pCurGroundEntity) == 0x1E0, "CVehicle: error");
static_assert(offsetof(CVehicle, m_nAlarmState) == 0x1A0, "CVehicle: error");
static_assert(offsetof(CVehicle, m_nLastWeaponDamage) == 0x228, "CVehicle: error");
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);