aboutsummaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
Diffstat (limited to 'src/control')
-rw-r--r--src/control/AutoPilot.cpp8
-rw-r--r--src/control/AutoPilot.h14
-rw-r--r--src/control/Bridge.cpp14
-rw-r--r--src/control/CarAI.cpp258
-rw-r--r--src/control/CarAI.h5
-rw-r--r--src/control/CarCtrl.cpp1290
-rw-r--r--src/control/CarCtrl.h69
-rw-r--r--src/control/Curves.cpp28
-rw-r--r--src/control/Darkel.cpp199
-rw-r--r--src/control/Darkel.h4
-rw-r--r--src/control/GameLogic.cpp346
-rw-r--r--src/control/GameLogic.h38
-rw-r--r--src/control/Garages.cpp1201
-rw-r--r--src/control/Garages.h100
-rw-r--r--src/control/OnscreenTimer.cpp166
-rw-r--r--src/control/OnscreenTimer.h36
-rw-r--r--src/control/PathFind.cpp1117
-rw-r--r--src/control/PathFind.h196
-rw-r--r--src/control/Phones.cpp125
-rw-r--r--src/control/Phones.h10
-rw-r--r--src/control/Pickups.cpp1436
-rw-r--r--src/control/Pickups.h50
-rw-r--r--src/control/Record.cpp430
-rw-r--r--src/control/Remote.cpp19
-rw-r--r--src/control/Remote.h2
-rw-r--r--src/control/Replay.cpp540
-rw-r--r--src/control/Replay.h126
-rw-r--r--src/control/Restart.cpp9
-rw-r--r--src/control/RoadBlocks.cpp263
-rw-r--r--src/control/RoadBlocks.h18
-rw-r--r--src/control/SceneEdit.cpp10
-rw-r--r--src/control/Script.cpp650
-rw-r--r--src/control/Script.h123
-rw-r--r--src/control/Script2.cpp356
-rw-r--r--src/control/Script3.cpp255
-rw-r--r--src/control/Script4.cpp406
-rw-r--r--src/control/Script5.cpp318
-rw-r--r--src/control/Script6.cpp648
-rw-r--r--src/control/Script7.cpp1404
-rw-r--r--src/control/Script8.cpp618
-rw-r--r--src/control/ScriptCommands.h330
-rw-r--r--src/control/ScriptDebug.cpp436
-rw-r--r--src/control/SetPieces.cpp325
-rw-r--r--src/control/SetPieces.h48
-rw-r--r--src/control/TrafficLights.cpp486
-rw-r--r--src/control/TrafficLights.h7
46 files changed, 10214 insertions, 4323 deletions
diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp
index 5af4071a..d7c17a68 100644
--- a/src/control/AutoPilot.cpp
+++ b/src/control/AutoPilot.cpp
@@ -71,6 +71,9 @@ void CAutoPilot::Save(uint8*& buf)
WriteSaveBuf(buf, m_nTimeTempAction);
WriteSaveBuf(buf, m_fMaxTrafficSpeed);
WriteSaveBuf(buf, m_nCruiseSpeed);
+ WriteSaveBuf(buf, m_nCruiseSpeedMultiplierType);
+ ZeroSaveBuf(buf, 2);
+ WriteSaveBuf(buf, m_fCruiseSpeedMultiplier);
uint8 flags = 0;
if (m_bSlowedDownBecauseOfCars) flags |= BIT(0);
if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1);
@@ -78,6 +81,7 @@ void CAutoPilot::Save(uint8*& buf)
if (m_bStayInFastLane) flags |= BIT(3);
if (m_bIgnorePathfinding) flags |= BIT(4);
WriteSaveBuf(buf, flags);
+ WriteSaveBuf(buf, m_nSwitchDistance);
ZeroSaveBuf(buf, 2);
WriteSaveBuf(buf, m_vecDestinationCoors.x);
WriteSaveBuf(buf, m_vecDestinationCoors.y);
@@ -110,6 +114,9 @@ void CAutoPilot::Load(uint8*& buf)
ReadSaveBuf(&m_nTimeTempAction, buf);
ReadSaveBuf(&m_fMaxTrafficSpeed, buf);
ReadSaveBuf(&m_nCruiseSpeed, buf);
+ ReadSaveBuf(&m_nCruiseSpeedMultiplierType, buf);
+ SkipSaveBuf(buf, 2);
+ ReadSaveBuf(&m_fCruiseSpeedMultiplier, buf);
uint8 flags;
ReadSaveBuf(&flags, buf);
m_bSlowedDownBecauseOfCars = !!(flags & BIT(0));
@@ -117,6 +124,7 @@ void CAutoPilot::Load(uint8*& buf)
m_bStayInCurrentLevel = !!(flags & BIT(2));
m_bStayInFastLane = !!(flags & BIT(3));
m_bIgnorePathfinding = !!(flags & BIT(4));
+ ReadSaveBuf(&m_nSwitchDistance, buf);
SkipSaveBuf(buf, 2);
ReadSaveBuf(&m_vecDestinationCoors.x, buf);
ReadSaveBuf(&m_vecDestinationCoors.y, buf);
diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h
index c7707ed6..ec3bb8d8 100644
--- a/src/control/AutoPilot.h
+++ b/src/control/AutoPilot.h
@@ -26,6 +26,13 @@ enum eCarMission
MISSION_BLOCKCAR_FARAWAY,
MISSION_BLOCKCAR_CLOSE,
MISSION_BLOCKCAR_HANDBRAKESTOP,
+ 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
};
enum eCarTempAction
@@ -75,11 +82,14 @@ public:
uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed;
+ uint8 m_nCruiseSpeedMultiplierType;
+ float m_fCruiseSpeedMultiplier;
uint8 m_bSlowedDownBecauseOfCars : 1;
uint8 m_bSlowedDownBecauseOfPeds : 1;
uint8 m_bStayInCurrentLevel : 1;
uint8 m_bStayInFastLane : 1;
uint8 m_bIgnorePathfinding : 1;
+ uint8 m_nSwitchDistance;
CVector m_vecDestinationCoors;
CPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT];
int16 m_nPathFindNodesCount;
@@ -109,6 +119,8 @@ public:
m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
m_nAntiReverseTimer = m_nTimeToStartMission;
m_bStayInFastLane = false;
+ m_nCruiseSpeedMultiplierType = 0;
+ m_fCruiseSpeedMultiplier = 1.0f;
}
void ModifySpeed(float);
@@ -118,6 +130,8 @@ public:
void Load(uint8*& buf);
#endif
+ float GetCruiseSpeed(void) { return m_nCruiseSpeed * m_fCruiseSpeedMultiplier; }
+
};
VALIDATE_SIZE(CAutoPilot, 0x70);
diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp
index e873062b..1e63cf30 100644
--- a/src/control/Bridge.cpp
+++ b/src/control/Bridge.cpp
@@ -23,6 +23,7 @@ uint32 CBridge::TimeOfBridgeBecomingOperational;
void CBridge::Init()
{
+#ifdef GTA_BRIDGE
FindBridgeEntities();
OldLift = -1.0f;
if (pLiftPart && pWeight)
@@ -35,10 +36,12 @@ void CBridge::Init()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
}
+#endif
}
void CBridge::Update()
{
+#ifdef GTA_BRIDGE
if (!pLiftPart || !pWeight)
return;
@@ -113,15 +116,21 @@ void CBridge::Update()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false);
+#endif
}
bool CBridge::ShouldLightsBeFlashing()
{
+#ifdef GTA_BRIDGE
return State != STATE_LIFT_PART_IS_DOWN;
+#else
+ return false;
+#endif
}
void CBridge::FindBridgeEntities()
{
+#ifdef GTA_BRIDGE
pWeight = nil;
pLiftRoad = nil;
pLiftPart = nil;
@@ -138,12 +147,17 @@ void CBridge::FindBridgeEntities()
pWeight = entry;
}
}
+#endif
}
bool CBridge::ThisIsABridgeObjectMovingUp(int index)
{
+#ifdef GTA_BRIDGE
if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT)
return false;
return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP;
+#else
+ return false;
+#endif
}
diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp
index d2a82121..8e79fee1 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -13,6 +13,7 @@
#include "DMAudio.h"
#include "Fire.h"
#include "Pools.h"
+#include "Population.h"
#include "Timer.h"
#include "TrafficLights.h"
#include "Vehicle.h"
@@ -23,7 +24,7 @@
float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)
{
- return 30.0f;
+ return pVehicle->AutoPilot.m_nSwitchDistance;
}
float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle)
@@ -38,6 +39,19 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
return FindSwitchDistanceFarNormalVehicle(pVehicle);
}
+void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle)
+{
+ if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
+ (FindPlayerPed()->m_pWanted->GetWantedLevel() == 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;
+ }
+}
+
void CCarAI::UpdateCarAI(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer){
@@ -64,18 +78,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
pVehicle->AutoPilot.m_bIgnorePathfinding) {
pVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_CLOSE;
- if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
+ if (pVehicle->UsesSiren())
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->GetWantedLevel() == 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;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_RAMPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -120,40 +126,23 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->GetWantedLevel() == 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;
- }
-
- else if (pVehicle->bIsLawEnforcer)
+ if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_FARAWAY:
if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
pVehicle->AutoPilot.m_bIgnorePathfinding) {
pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;
- if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
+ if (pVehicle->UsesSiren())
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->GetWantedLevel() == 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;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
pVehicle->AutoPilot.m_bIgnorePathfinding) {
- if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f)
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f)
#ifdef FIX_BUGS
pVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();
#else
@@ -162,7 +151,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
else
pVehicle->m_nTimeBlocked = 0;
if (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() ||
- FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
+ FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
if (pVehicle->bIsLawEnforcer &&
(pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) &&
(FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) {
@@ -178,20 +167,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->GetWantedLevel() == 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;
- }
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_GOTOCOORDS:
- if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < DISTANCE_TO_SWITCH_DISTANCE_GOTO ||
+ if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
break;
@@ -200,9 +181,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
float distance = (pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D();
if ((pVehicle->bIsAmbulanceOnDuty || pVehicle->bIsFireTruckOnDuty) && distance < 20.0f)
pVehicle->AutoPilot.m_nCarMission = MISSION_EMERGENCYVEHICLE_STOP;
- if (distance < 5.0f){
+ if (distance < 3.0f){
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -249,8 +234,8 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
}
break;
case MISSION_GOTOCOORDS_ACCURATE:
- if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < 20.0f ||
- pVehicle->AutoPilot.m_bIgnorePathfinding)
+ if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
+ pVehicle->AutoPilot.m_bIgnorePathfinding)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
break;
case MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:
@@ -259,6 +244,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 1.0f) {
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -278,23 +267,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
break;
case MISSION_RAMCAR_CLOSE:
if (pVehicle->AutoPilot.m_pTargetCar){
- if
-#ifdef FIX_BUGS
- (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar &&
-#endif
- (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->GetWantedLevel() == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice()))
-#ifdef FIX_BUGS
- )
+#ifdef FIX_BUGS // btw fixed in SA
+ if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar)
#endif
- {
- 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;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding){
if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){
@@ -316,7 +292,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding){
pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_CLOSE;
- if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
+ if (pVehicle->UsesSiren())
pVehicle->m_bSirenOrAlarm = true;
}
}else{
@@ -336,6 +312,41 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
break;
+ 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->GetWantedLevel() == 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);
+ break;
+ }
default:
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 && !CCullZones::NoPolice()){
if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f ||
@@ -343,7 +354,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nCarMission =
- FindPoliceCarMissionForWantedLevel();
+ pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel();
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
}else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){
@@ -364,6 +375,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
break;
}
+ if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->GetWantedLevel() >= 1 && CCullZones::PoliceAbandonCars()) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
float flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D();
if (flatSpeed > SQR(0.018f)){
pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
@@ -372,9 +388,12 @@ 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 &&
+ pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP &&
pVehicle->AutoPilot.m_nCruiseSpeed != 0 &&
(pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){
if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS
+ && pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS ||
+ pVehicle->VehicleCreatedBy == MISSION_VEHICLE
) {
if (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500)
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
@@ -406,6 +425,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400;
}
}
+ if (pVehicle->bIsLawEnforcer) {
+ if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||
+ pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;
+ }
+ }
if (pVehicle->GetUp().z < -0.7f){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
@@ -446,6 +472,34 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD)
pVehicle->m_nCarHornTimer = 45;
}
+ 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->GetWantedLevel() > 0) {
+ if (!FindPlayerVehicle() ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||
+ pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ }
}
void CCarAI::CarHasReasonToStop(CVehicle* pVehicle)
@@ -470,13 +524,21 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
}
+float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget)
+{
+ GetCarToGoToCoors(pVehicle, pTarget);
+ pVehicle->bParking = true;
+ pVehicle->AutoPilot.m_nCruiseSpeed = 10;
+ return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
+}
+
void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
{
if (pVehicle->bOccupantsHaveBeenGenerated)
return;
pVehicle->bOccupantsHaveBeenGenerated = true;
switch (pVehicle->GetModelIndex()){
- case MI_FBICAR:
+ case MI_FBIRANCH:
case MI_ENFORCER:
pVehicle->SetUpDriver();
for (int i = 0; i < 3; i++)
@@ -489,6 +551,18 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
if (FindPlayerPed()->m_pWanted->GetWantedLevel() > 1)
pVehicle->SetupPassenger(0);
return;
+ case MI_PREDATOR:
+ pVehicle->SetUpDriver();
+ return;
+ case MI_VICECHEE:
+ {
+ pVehicle->SetUpDriver()->bMiamiViceCop = true;
+ pVehicle->SetupPassenger(0)->bMiamiViceCop = true;
+ CPopulation::NumMiamiViceCops += 2;
+ CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
+ CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
default:
return;
}
@@ -516,7 +590,26 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
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_LEAVE_CAR, pVehicle);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
+ }
+ }
+}
+
+void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)
+{
+ if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_ON_FOOT_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_ON_FOOT_TILL_SAFE);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
}
}
}
@@ -553,6 +646,20 @@ uint8 CCarAI::FindPoliceCarMissionForWantedLevel()
}
}
+uint8 CCarAI::FindPoliceBoatMissionForWantedLevel()
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {
+ 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;
+ }
+}
+
int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {
@@ -605,6 +712,23 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 34;
}
}
+ if (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) {
+ if ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f)
+ pVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed);
+ }
+}
+
+void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle)
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {
+ 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;
+ }
}
void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
@@ -629,6 +753,8 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
continue;
if (vehicle == pVehicle)
continue;
+ if (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
+ return;
if (Abs(pVehicle->GetPosition().z - vehicle->GetPosition().z) >= 5.0f)
continue;
CVector2D distance = vehicle->GetPosition() - pVehicle->GetPosition();
diff --git a/src/control/CarAI.h b/src/control/CarAI.h
index 9b731ad5..dcd76d78 100644
--- a/src/control/CarAI.h
+++ b/src/control/CarAI.h
@@ -10,17 +10,22 @@ public:
static float FindSwitchDistanceClose(CVehicle*);
static float FindSwitchDistanceFarNormalVehicle(CVehicle*);
static float FindSwitchDistanceFar(CVehicle*);
+ static void BackToCruisingIfNoWantedLevel(CVehicle*);
static void UpdateCarAI(CVehicle*);
static void CarHasReasonToStop(CVehicle*);
static float GetCarToGoToCoors(CVehicle*, CVector*);
+ static float GetCarToParkAtCoors(CVehicle*, CVector*);
static void AddPoliceCarOccupants(CVehicle*);
static void AddAmbulanceOccupants(CVehicle*);
static void AddFiretruckOccupants(CVehicle*);
static void TellOccupantsToLeaveCar(CVehicle*);
+ static void TellOccupantsToFleeCar(CVehicle*);
static void TellCarToRamOtherCar(CVehicle*, CVehicle*);
static void TellCarToBlockOtherCar(CVehicle*, CVehicle*);
static uint8 FindPoliceCarMissionForWantedLevel();
+ static uint8 FindPoliceBoatMissionForWantedLevel();
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static void MellowOutChaseSpeed(CVehicle*);
+ static void MellowOutChaseSpeedBoat(CVehicle*);
static void MakeWayForCarWithSiren(CVehicle *veh);
};
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index ca83603f..1cf09a9f 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -4,6 +4,7 @@
#include "Accident.h"
#include "Automobile.h"
+#include "Bike.h"
#include "Camera.h"
#include "CarAI.h"
#include "CarGen.h"
@@ -11,6 +12,7 @@
#include "Curves.h"
#include "CutsceneMgr.h"
#include "Gangs.h"
+#include "Game.h"
#include "Garages.h"
#include "General.h"
#include "IniFile.h"
@@ -19,6 +21,7 @@
#include "Ped.h"
#include "PlayerInfo.h"
#include "PlayerPed.h"
+#include "Population.h"
#include "Wanted.h"
#include "Pools.h"
#include "Renderer.h"
@@ -29,44 +32,58 @@
#include "VisibilityPlugins.h"
#include "Vehicle.h"
#include "Fire.h"
+#include "WaterLevel.h"
#include "World.h"
#include "Zones.h"
-
-#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS 51.0f
-#define DISTANCE_TO_SCAN_FOR_DANGER 11.0f
-#define SAFE_DISTANCE_TO_PED 3.0f
-#define INFINITE_Z 1000000000.0f
-
-#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING 8.0f
-#define WIDTH_COEF_TO_WEAVE_SAFELY 1.2f
-#define OBJECT_WIDTH_TO_WEAVE 0.3f
-#define PED_WIDTH_TO_WEAVE 0.8f
-
-#define PATH_DIRECTION_NONE 0
-#define PATH_DIRECTION_STRAIGHT 1
-#define PATH_DIRECTION_RIGHT 2
-#define PATH_DIRECTION_LEFT 4
-
-#define ATTEMPTS_TO_FIND_NEXT_NODE 15
-
-#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP 5.0f
-#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK 10.0f
-#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING 0.13f
-#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN 40.0f
-#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED 0.2f
-#define MIN_SPEED_TO_START_LIMITING_STEER 0.45f
-#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW 5.0f
-#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW 8.0f
-#define DEFAULT_MAX_STEER_ANGLE 0.5f
-#define MIN_LOWERING_SPEED_COEFFICIENT 0.4f
-#define MAX_ANGLE_FOR_SPEED_LIMITING 1.2f
-#define MIN_ANGLE_FOR_SPEED_LIMITING 0.4f
-#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES 0.1f
-#define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f
-#define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f
-
+#include "Pickups.h"
+
+#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f)
+#define DISTANCE_TO_SCAN_FOR_DANGER (14.0f)
+#define DISTANCE_TO_SCAN_FOR_PED_DANGER (11.0f)
+#define SAFE_DISTANCE_TO_PED (3.0f)
+#define INFINITE_Z (1000000000.0f)
+
+#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING (8.0f)
+#define WIDTH_COEF_TO_WEAVE_SAFELY (1.2f)
+#define OBJECT_WIDTH_TO_WEAVE (0.3f)
+#define PED_WIDTH_TO_WEAVE (0.8f)
+
+#define PATH_DIRECTION_NONE (0)
+#define PATH_DIRECTION_STRAIGHT (1)
+#define PATH_DIRECTION_RIGHT (2)
+#define PATH_DIRECTION_LEFT (4)
+
+#define ATTEMPTS_TO_FIND_NEXT_NODE (15)
+
+#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP (5.0f)
+#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK (10.0f)
+#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING (0.13f)
+#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN (40.0f)
+#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED (0.2f)
+#define MIN_SPEED_TO_START_LIMITING_STEER (0.45f)
+#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW (5.0f)
+#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW (8.0f)
+#define DEFAULT_MAX_STEER_ANGLE (0.5f)
+#define MIN_LOWERING_SPEED_COEFFICIENT (0.4f)
+#define MAX_ANGLE_FOR_SPEED_LIMITING (1.2f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING (0.4f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES (0.1f)
+#define MIN_ANGLE_TO_APPLY_HANDBRAKE (0.7f)
+#define MIN_SPEED_TO_APPLY_HANDBRAKE (0.3f)
+
+#define PROBABILITY_OF_DEAD_PED_ACCIDENT (0.005f)
+#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f)
+#define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f)
+
+#define ONSCREEN_DESPAWN_RANGE (120.0f)
+#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f)
+#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2)
+#define OFFSCREEN_DESPAWN_RANGE (40.0f)
+#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)
+
+bool CCarCtrl::bMadDriversCheat;
int CCarCtrl::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty;
int CCarCtrl::NumFiretrucksOnDuty;
@@ -81,23 +98,29 @@ int32 CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS;
uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated;
+int32 CCarCtrl::MiamiViceCycle;
+uint32 CCarCtrl::LastTimeMiamiViceGenerated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
-int32 CCarCtrl::NextCarOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];
void
CCarCtrl::GenerateRandomCars()
{
- if (CCutsceneMgr::IsRunning())
+ if (CCutsceneMgr::IsRunning()) {
+ CountDownToCarsAtStart = 2;
return;
+ }
if (NumRandomCars < 30){
- if (CountDownToCarsAtStart == 0){
+ if (CountDownToCarsAtStart == 0)
GenerateOneRandomCar();
- }
else if (--CountDownToCarsAtStart == 0) {
- for (int i = 0; i < 50; i++)
+ for (int i = 0; i < 100; i++)
GenerateOneRandomCar();
CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20;
}
@@ -111,6 +134,7 @@ void
CCarCtrl::GenerateOneRandomCar()
{
static int32 unk = 0;
+ bool bTopDownCamera = false;
CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
CVector vecTargetPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
CVector2D vecPlayerSpeed = FindPlayerSpeed();
@@ -125,7 +149,7 @@ CCarCtrl::GenerateOneRandomCar()
int carClass;
int carModel;
if (pWanted->GetWantedLevel() > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
- pWanted->m_CurrentCops < pWanted->m_MaxCops && (
+ pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
pWanted->GetWantedLevel() > 3 ||
pWanted->GetWantedLevel() > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
pWanted->GetWantedLevel() > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
@@ -134,8 +158,8 @@ CCarCtrl::GenerateOneRandomCar()
carClass = COPS;
carModel = ChoosePoliceCarModel();
}else{
- carModel = ChooseModel(&zone, &vecTargetPos, &carClass);
- if (carClass == COPS && pWanted->GetWantedLevel() >= 1)
+ carModel = ChooseModel(&zone, &carClass);
+ if (carModel == -1 || (carClass == COPS && pWanted->GetWantedLevel() >= 1))
/* All cop spawns with wanted level are handled by condition above. */
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
return;
@@ -159,8 +183,9 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn essentially anywhere. */
frontX = frontY = 0.707f; /* 45 degrees */
angleLimit = -1.0f;
+ bTopDownCamera = true;
invertAngleLimitTest = true;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f;
/* BUG: testForCollision not initialized in original game. */
testForCollision = false;
}else if (!pPlayerVehicle){
@@ -174,14 +199,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */
@@ -196,21 +221,21 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 3:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */
@@ -224,14 +249,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
case 3:
@@ -239,7 +264,7 @@ CCarCtrl::GenerateOneRandomCar()
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else{
@@ -254,32 +279,60 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}
- if (!ThePaths.NewGenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY,
+ if (!ThePaths.GenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY,
preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId,
&positionBetweenNodes, carClass == COPS && pWanted->GetWantedLevel() >= 1))
return;
+ CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
+ CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+ bool bBoatGenerated = false;
+ if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))
+ return;
+ if (pCurNode->bWaterPath) {
+ bBoatGenerated = true;
+ if (carClass == COPS) {
+ carModel = MI_PREDATOR;
+ carClass = COPS_BOAT;
+ if (!CStreaming::HasModelLoaded(MI_PREDATOR)) {
+ CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY);
+ return;
+ }
+ }
+ else {
+ int i;
+ carModel = -1;
+ for (i = 10; i > 0 && (carModel == -1 || !CStreaming::HasModelLoaded(carModel)); i--) {
+ carModel = ChooseBoatModel(ChooseBoatRating(&zone));
+ }
+ if (i == 0)
+ return;
+ }
+ if (pCurNode->bOnlySmallBoats || pNextNode->bOnlySmallBoats) {
+ if (BoatWithTallMast(carModel))
+ return;
+ }
+ }
int16 colliding;
- CWorld::FindObjectsKindaColliding(spawnPosition, 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ CWorld::FindObjectsKindaColliding(spawnPosition, bBoatGenerated ? 40.0f : 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
if (colliding)
/* If something is already present in spawn position, do not create vehicle*/
return;
- if (!ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
+ if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
/* Testing if spawn position can reach target position via valid path. */
return;
int16 idInNode = 0;
- CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
- CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+
while (idInNode < pCurNode->numLinks &&
ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)
idInNode++;
@@ -287,48 +340,20 @@ CCarCtrl::GenerateOneRandomCar()
CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];
int16 lanesOnCurrentRoad = pPathLink->pathNodeIndex == nextNodeId ? pPathLink->numLeftLanes : pPathLink->numRightLanes;
CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel);
- if (lanesOnCurrentRoad == 0 || pModelInfo->m_vehicleType == VEHICLE_TYPE_BIKE)
+ if (lanesOnCurrentRoad == 0)
/* Not spawning vehicle if road is one way and intended direction is opposide to that way. */
- /* Also not spawning bikes but they don't exist in final game. */
return;
- CAutomobile* pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
+ CVehicle* pVehicle;
+ if (CModelInfo::IsBoatModel(carModel))
+ pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
+ else if (CModelInfo::IsBikeModel(carModel))
+ pVehicle = new CBike(carModel, RANDOM_VEHICLE);
+ else
+ pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;
pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- {
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
- if (carClass == EXEC)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
- else if (carClass == POOR || carClass == SPECIAL)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
- CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo();
- if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
- pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
- pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
- }
- pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- break;
- }
case COPS:
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel() != 0){
@@ -342,19 +367,40 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
}
- if (carModel == MI_FBICAR){
+ if (carModel == MI_FBIRANCH){
pVehicle->m_currentColour1 = 0;
pVehicle->m_currentColour2 = 0;
- /* FBI cars are gray in carcols, but we want them black if they going after player. */
}
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
+ case COPS_BOAT:
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4, 16);
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
default:
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
+ if (carClass == EXEC)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
+ else if (carClass == POOR)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
+ if (pVehicle->GetColModel()->boundingBox.max.y - pVehicle->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
+ pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
+ pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
+ }
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
break;
}
if (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP)
pVehicle->m_bSirenOrAlarm = true;
pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;
pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
- CColBox* boundingBox = &CModelInfo::GetColModel(pVehicle->GetModelIndex())->boundingBox;
+ CBox* boundingBox = &CModelInfo::GetColModel(pVehicle->GetModelIndex())->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();
/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */
@@ -478,6 +524,7 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;
#endif
+
CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);
CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);
CVector positionIncludingCurve;
@@ -499,62 +546,69 @@ CCarCtrl::GenerateOneRandomCar()
float groundZ = INFINITE_Z;
CColPoint colPoint;
CEntity* pEntity;
- if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
- groundZ = colPoint.point.z;
- if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)){
- if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ if (bBoatGenerated) {
+ if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) {
+ delete pVehicle;
+ return;
+ }
+ }
+ else {
+ if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
groundZ = colPoint.point.z;
+ if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {
+ if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ groundZ = colPoint.point.z;
+ }
}
if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) {
/* Failed to find ground or too far from expected position. */
delete pVehicle;
return;
}
- finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
+ if (CModelInfo::IsBoatModel(carModel)) {
+ finalPosition.z = groundZ;
+ pVehicle->bExtendedRange = true;
+ }
+ else
+ finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
pVehicle->SetPosition(finalPosition);
pVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);
CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed;
CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- pVehicle->SetStatus(STATUS_SIMPLE);
- break;
case COPS:
pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);
pVehicle->ChangeLawEnforcerState(1);
break;
+ case COPS_BOAT:
+ pVehicle->ChangeLawEnforcerState(1);
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ break;
default:
+ bBoatGenerated ? pVehicle->SetStatus(STATUS_PHYSICS) : pVehicle->SetStatus(STATUS_SIMPLE);
break;
}
CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
if (!pVehicle->GetIsOnScreen()){
- if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > 50.0f) {
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > OFFSCREEN_DESPAWN_RANGE * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f)) {
/* Too far away cars that are not visible aren't needed. */
delete pVehicle;
return;
}
- }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f ||
- (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){
- delete pVehicle;
- return;
- }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){
- delete pVehicle;
- return;
+ }else{
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||
+ (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {
+ delete pVehicle;
+ return;
+ }
+ if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
+ delete pVehicle;
+ return;
+ }
+ if (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?
+ delete pVehicle;
+ return;
+ }
}
CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
@@ -577,59 +631,156 @@ CCarCtrl::GenerateOneRandomCar()
}
pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2);
CWorld::Add(pVehicle);
- if (carClass == COPS)
+ if (carClass == COPS || carClass == COPS_BOAT)
CCarAI::AddPoliceCarOccupants(pVehicle);
- else
+ else {
pVehicle->SetUpDriver();
- if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */
+ int32 passengers = 0;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
+ passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
+ if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
+ passengers = 1;
+ for (int i = 0; i < passengers; i++) {
+ CPed* pPassenger = pVehicle->SetupPassenger(i);
+ if (pPassenger) {
+ ++CPopulation::ms_nTotalCarPassengerPeds;
+ pPassenger->bCarPassenger = true;
+ }
+ }
+ }
+ int nMadDrivers;
+ switch (pVehicle->GetVehicleAppearance()) {
+ case VEHICLE_APPEARANCE_BIKE:
+ nMadDrivers = 30;
+ break;
+ case VEHICLE_APPEARANCE_BOAT:
+ nMadDrivers = 40;
+ break;
+ default:
+ nMadDrivers = 6;
+ break;
+ }
+ if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers || bMadDriversCheat) {
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
pVehicle->AutoPilot.m_nCruiseSpeed += 10;
}
if (carClass == COPS)
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
+ if (pVehicle->GetModelIndex() == MI_CADDY) {
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ if (carClass == COPS && pVehicle->GetModelIndex() == MI_VICECHEE) {
+ CVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_VICECHEE);
+ switch (MiamiViceCycle) {
+ case 0:
+ pVehicleModel->SetVehicleColour(53, 77);
+ break;
+ case 1:
+ pVehicleModel->SetVehicleColour(15, 77);
+ break;
+ case 2:
+ pVehicleModel->SetVehicleColour(41, 77);
+ break;
+ case 3:
+ pVehicleModel->SetVehicleColour(61, 77);
+ break;
+ default:
+ break;
+ }
+ }
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= (1 - PROBABILITY_OF_DEAD_PED_ACCIDENT)) {
+ if (CModelInfo::IsCarModel(pVehicle->GetModelIndex()) && !pVehicle->bIsLawEnforcer) {
+ if (CPopulation::AddDeadPedInFrontOfCar(pVehicle->GetPosition() + pVehicle->GetForward() * DISTANCE_BETWEEN_CAR_AND_DEAD_PED, pVehicle)) {
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < pVehicle->m_nNumPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
+ pVehicle->pPassengers[i]->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pPassengers[i]->m_vehicleInAccident = pVehicle;
+ pVehicle->pPassengers[i]->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pPassengers[i]->m_vehicleInAccident);
+ }
+ }
+ if (pVehicle->pDriver) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
+ pVehicle->pDriver->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pDriver->m_vehicleInAccident = pVehicle;
+ pVehicle->pDriver->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pDriver->m_vehicleInAccident);
+ }
+ }
+ }
+ }
+}
+
+bool
+CCarCtrl::BoatWithTallMast(int32 mi)
+{
+ return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
+}
+
+int32
+CCarCtrl::ChooseBoatModel(int32 rating)
+{
+ ++NumRequestsOfCarRating[rating];
+ return ChooseCarModel(rating);
+}
+
+int32
+CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_BOAT_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->boatThreshold[i])
+ return FIRST_BOAT_RATING + i;
+ }
+ return FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1;
+}
+
+int32
+CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_CAR_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->carThreshold[i])
+ return i;
+ }
+ return FIRST_CAR_RATING + NUM_CAR_CLASSES - 1;
}
int32
-CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) {
+CCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {
int32 model = -1;
- while (model == -1 || !CStreaming::HasModelLoaded(model)){
+ int32 i;
+ for (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
- if (rnd < pZone->carThreshold[0])
- model = CCarCtrl::ChooseCarModel((*pClass = POOR));
- else if (rnd < pZone->carThreshold[1])
- model = CCarCtrl::ChooseCarModel((*pClass = RICH));
- else if (rnd < pZone->carThreshold[2])
- model = CCarCtrl::ChooseCarModel((*pClass = EXEC));
- else if (rnd < pZone->carThreshold[3])
- model = CCarCtrl::ChooseCarModel((*pClass = WORKER));
- else if (rnd < pZone->carThreshold[4])
- model = CCarCtrl::ChooseCarModel((*pClass = SPECIAL));
- else if (rnd < pZone->carThreshold[5])
- model = CCarCtrl::ChooseCarModel((*pClass = BIG));
- else if (rnd < pZone->copThreshold)
- *pClass = COPS, model = CCarCtrl::ChoosePoliceCarModel();
- else if (rnd < pZone->gangThreshold[0])
- model = CCarCtrl::ChooseGangCarModel((*pClass = MAFIA) - MAFIA);
- else if (rnd < pZone->gangThreshold[1])
- model = CCarCtrl::ChooseGangCarModel((*pClass = TRIAD) - MAFIA);
- else if (rnd < pZone->gangThreshold[2])
- model = CCarCtrl::ChooseGangCarModel((*pClass = DIABLO) - MAFIA);
- else if (rnd < pZone->gangThreshold[3])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YAKUZA) - MAFIA);
- else if (rnd < pZone->gangThreshold[4])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YARDIE) - MAFIA);
- else if (rnd < pZone->gangThreshold[5])
- model = CCarCtrl::ChooseGangCarModel((*pClass = COLOMB) - MAFIA);
- else if (rnd < pZone->gangThreshold[6])
- model = CCarCtrl::ChooseGangCarModel((*pClass = NINES) - MAFIA);
- else if (rnd < pZone->gangThreshold[7])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG8) - MAFIA);
- else if (rnd < pZone->gangThreshold[8])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG9) - MAFIA);
- else
- model = CCarCtrl::ChooseCarModel((*pClass = TAXI));
+
+ if (rnd < pZone->copThreshold) {
+ *pClass = COPS;
+ model = ChoosePoliceCarModel();
+ continue;
+ }
+
+ int32 j;
+ for (j = 0; j < NUM_GANG_CAR_CLASSES; j++) {
+ if (rnd < pZone->gangThreshold[j]) {
+ *pClass = j + FIRST_GANG_CAR_RATING;
+ model = ChooseGangCarModel(j);
+ break;
+ }
+ }
+
+ if (j != NUM_GANG_CAR_CLASSES)
+ continue;
+
+ *pClass = ChooseCarRating(pZone);
+ model = ChooseCarModel(*pClass);
}
+ if (i == 0)
+ return -1;
return model;
}
@@ -637,42 +788,94 @@ int32
CCarCtrl::ChooseCarModel(int32 vehclass)
{
int32 model = -1;
- switch (vehclass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- {
- if (TotalNumOfCarsOfRating[vehclass] == 0)
- debug("ChooseCarModel : No cars of type %d have been declared\n", vehclass);
- model = CarArrays[vehclass][NextCarOfRating[vehclass]];
- int32 total = TotalNumOfCarsOfRating[vehclass];
- NextCarOfRating[vehclass] += CGeneral::GetRandomNumberInRange(1, total);
- while (NextCarOfRating[vehclass] >= total)
- NextCarOfRating[vehclass] -= total;
- //NextCarOfRating[vehclass] %= total;
- TotalNumOfCarsOfRating[vehclass] = total; /* why... */
- }
- default:
- break;
- }
- return model;
+ ++NumRequestsOfCarRating[vehclass];
+ if (NumOfLoadedCarsOfRating[vehclass] == 0)
+ return -1;
+ int32 rnd = CGeneral::GetRandomNumberInRange(0, CarFreqArrays[vehclass][NumOfLoadedCarsOfRating[vehclass] - 1]);
+ int32 index = 0;
+ while (rnd > CarFreqArrays[vehclass][index])
+ index++;
+ assert(LoadedCarsArray[vehclass][index]);
+ return LoadedCarsArray[vehclass][index];
+}
+
+void
+CCarCtrl::AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq)
+{
+ LoadedCarsArray[rating][NumOfLoadedCarsOfRating[rating]] = mi;
+ assert(mi >= 130);
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] = freq;
+ if (NumOfLoadedCarsOfRating[rating])
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] += CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating] - 1];
+ NumOfLoadedCarsOfRating[rating]++;
+}
+
+void
+CCarCtrl::RemoveFromLoadedVehicleArray(int mi, int32 rating)
+{
+ int index = 0;
+ while (LoadedCarsArray[rating][index] != -1) {
+ if (LoadedCarsArray[rating][index] == mi)
+ break;
+ index++;
+ }
+ assert(LoadedCarsArray[rating][index] == mi);
+ int32 freq = CarFreqArrays[rating][index];
+ if (index > 0)
+ freq -= CarFreqArrays[rating][index - 1];
+ while (LoadedCarsArray[rating][index + 1] != -1) {
+ LoadedCarsArray[rating][index] = LoadedCarsArray[rating][index + 1];
+ CarFreqArrays[rating][index] = CarFreqArrays[rating][index + 1] - freq;
+ index++;
+ }
+ --NumOfLoadedCarsOfRating[rating];
+}
+
+int32
+CCarCtrl::ChooseCarModelToLoad(int rating)
+{
+ return CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])];
}
int32
CCarCtrl::ChoosePoliceCarModel(void)
{
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired() &&
+#ifdef FIX_BUGS
+ (CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 || LastTimeMiamiViceGenerated == 0) &&
+#else
+ CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 &&
+#endif
+ CStreaming::HasModelLoaded(MI_VICECHEE)) {
+ switch (MiamiViceCycle) {
+ case 0:
+ if (CStreaming::HasModelLoaded(MI_VICE1) && CStreaming::HasModelLoaded(MI_VICE2))
+ return MI_VICECHEE;
+ break;
+ case 1:
+ if (CStreaming::HasModelLoaded(MI_VICE3) && CStreaming::HasModelLoaded(MI_VICE4))
+ return MI_VICECHEE;
+ break;
+ case 2:
+ if (CStreaming::HasModelLoaded(MI_VICE5) && CStreaming::HasModelLoaded(MI_VICE6))
+ return MI_VICECHEE;
+ break;
+ case 3:
+ if (CStreaming::HasModelLoaded(MI_VICE7) && CStreaming::HasModelLoaded(MI_VICE8))
+ return MI_VICECHEE;
+ break;
+ default:
+ break;
+ }
+ }
if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE))
return ((CGeneral::GetRandomNumber() & 0xF) == 0) ? MI_ENFORCER : MI_POLICE;
if (FindPlayerPed()->m_pWanted->AreFbiRequired() &&
- CStreaming::HasModelLoaded(MI_FBICAR) &&
+ CStreaming::HasModelLoaded(MI_FBIRANCH) &&
CStreaming::HasModelLoaded(MI_FBI))
- return MI_FBICAR;
+ return MI_FBIRANCH;
if (FindPlayerPed()->m_pWanted->AreArmyRequired() &&
CStreaming::HasModelLoaded(MI_RHINO) &&
CStreaming::HasModelLoaded(MI_BARRACKS) &&
@@ -684,8 +887,7 @@ CCarCtrl::ChoosePoliceCarModel(void)
int32
CCarCtrl::ChooseGangCarModel(int32 gang)
{
- if (CStreaming::HasModelLoaded(MI_GANG01 + 2 * gang) &&
- CStreaming::HasModelLoaded(MI_GANG02 + 2 * gang))
+ if (CGangs::HaveGangModelsLoaded(gang))
return CGangs::GetGangVehicleModel(gang);
return -1;
}
@@ -693,6 +895,7 @@ CCarCtrl::ChooseGangCarModel(int32 gang)
void
CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
{
+ assert(TotalNumOfCarsOfRating[vehclass] < MAX_CAR_MODELS_IN_ARRAY);
CarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;
}
@@ -706,7 +909,7 @@ CCarCtrl::RemoveDistantCars()
PossiblyRemoveVehicle(pVehicle);
if (pVehicle->bCreateRoadBlockPeds){
if ((pVehicle->GetPosition() - FindPlayerCentreOfWorld(CWorld::PlayerInFocus)).Magnitude2D() < DISTANCE_TO_SPAWN_ROADBLOCK_PEDS) {
- CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType, pVehicle->m_nRoadblockNode);
+ CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType);
pVehicle->bCreateRoadBlockPeds = false;
}
}
@@ -714,6 +917,36 @@ CCarCtrl::RemoveDistantCars()
}
void
+CCarCtrl::RemoveCarsIfThePoolGetsFull(void)
+{
+ if ((CTimer::GetFrameCounter() & 7) != 3)
+ return;
+ if (CPools::GetVehiclePool()->GetNoOfFreeSpaces() >= 8)
+ return;
+ int i = CPools::GetVehiclePool()->GetSize();
+ float md = 10000000.f;
+ CVehicle* pClosestVehicle = nil;
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (IsThisVehicleInteresting(pVehicle) || pVehicle->bIsLocked)
+ continue;
+ if (!pVehicle->CanBeDeleted() || CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle))
+ continue;
+ float distance = (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude();
+ if (distance < md) {
+ md = distance;
+ pClosestVehicle = pVehicle;
+ }
+ }
+ if (pClosestVehicle) {
+ CWorld::Remove(pClosestVehicle);
+ delete pClosestVehicle;
+ }
+}
+
+void
CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
{
#ifdef FIX_BUGS
@@ -730,7 +963,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
- float threshold = 50.0f;
+ float threshold = OFFSCREEN_DESPAWN_RANGE;
#ifndef EXTENDED_OFFSCREEN_DESPAWN_RANGE
if (pVehicle->GetIsOnScreen() ||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
@@ -741,16 +974,21 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
pVehicle->GetModelIndex() == MI_AMBULAN ||
pVehicle->GetModelIndex() == MI_FIRETRUCK ||
pVehicle->bIsLawEnforcer ||
- pVehicle->bIsCarParkVehicle
+ pVehicle->bIsCarParkVehicle ||
+ CTimer::GetTimeInMilliseconds() < pVehicle->m_nSetPieceExtendedRangeTime
)
#endif
{
- threshold = 130.0f * TheCamera.GenerationDistMultiplier;
+ threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier;
}
+#ifndef EXTENDED_OFFSCREEN_DESPAWN_RANGE
+ if (TheCamera.GetForward().z < -0.9f)
+ threshold = 70.0f;
+#endif
if (pVehicle->bExtendedRange)
- threshold *= 1.5f;
+ threshold *= EXTENDED_RANGE_DESPAWN_MULTIPLIER;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) {
+ if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
@@ -759,10 +997,11 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
}
- if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) &&
+ if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS &&
+ (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)) &&
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 &&
!pVehicle->GetIsOnScreen() &&
- (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f &&
+ (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 22.0f &&
!IsThisVehicleInteresting(pVehicle) &&
!pVehicle->bIsLocked &&
pVehicle->CanBeDeleted() &&
@@ -776,7 +1015,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
return;
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
- !(pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) ){
+ !pVehicle->GetIsOnScreen()){
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
@@ -800,6 +1039,16 @@ CCarCtrl::CountCarsOfType(int32 mi)
return total;
}
+static CVector GetRandomOffsetForVehicle(CVehicle* pVehicle, bool bNext)
+{
+ CVector offset;
+ int32 seed = ((bNext ? pVehicle->AutoPilot.m_nNextPathNodeInfo : pVehicle->AutoPilot.m_nCurrentPathNodeInfo) + pVehicle->m_randomSeed) & 7;
+ offset.x = (seed - 3) * 0.009f;
+ offset.y = ((seed >> 3) - 3) * 0.009f;
+ offset.z = 0.0f;
+ return offset;
+}
+
void
CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
{
@@ -832,8 +1081,12 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
- CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
- CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ CVector directionCurrentLink = GetRandomOffsetForVehicle(pVehicle, false);
+ directionCurrentLink += CVector(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
+ directionCurrentLink.Normalise();
+ CVector directionNextLink = GetRandomOffsetForVehicle(pVehicle, true);
+ directionNextLink += CVector(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ directionNextLink.Normalise();
CVector positionIncludingCurve;
CVector directionIncludingCurve;
CCurves::CalcCurvePoint(
@@ -856,7 +1109,7 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
{
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS ||
pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH)
- return pVehicle->AutoPilot.m_nCruiseSpeed;
+ return pVehicle->AutoPilot.GetCruiseSpeed();
float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER;
float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER;
float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;
@@ -868,33 +1121,33 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
assert(xstart <= xend);
assert(ystart <= yend);
- float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ float maxSpeed = pVehicle->AutoPilot.GetCruiseSpeed();
CWorld::AdvanceCurrentScanCode();
for (int y = ystart; y <= yend; y++){
for (int x = xstart; x <= xend; x++){
CSector* s = CWorld::GetSector(x, y);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
}
}
pVehicle->bWarnedPeds = true;
- if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS)
+ if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)
return maxSpeed;
- return (maxSpeed + pVehicle->AutoPilot.m_nCruiseSpeed) / 2;
+ return (maxSpeed + pVehicle->AutoPilot.GetCruiseSpeed()) / 2;
}
void
CCarCtrl::ScanForPedDanger(CVehicle* pVehicle)
{
bool storedSlowDownFlag = pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds;
- float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER;
- float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER;
- float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;
- float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER;
+ float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_PED_DANGER;
+ float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_PED_DANGER;
+ float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_PED_DANGER;
+ float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_PED_DANGER;
int xstart = Max(0, CWorld::GetSectorIndexX(left));
int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
int ystart = Max(0, CWorld::GetSectorIndexY(top));
@@ -935,7 +1188,7 @@ CCarCtrl::SlowCarOnRailsDownForTrafficAndLights(CVehicle* pVehicle)
if (curSpeed < 0.1f)
pVehicle->AutoPilot.ModifySpeed(0.0f);
else
- pVehicle->AutoPilot.ModifySpeed(Max(maxSpeed, curSpeed - 0.5f * CTimer::GetTimeStep()));
+ pVehicle->AutoPilot.ModifySpeed(Max(maxSpeed, curSpeed - 0.7f * CTimer::GetTimeStep()));
}
}
@@ -981,14 +1234,12 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f
if (pVehicle->GetModelIndex() == MI_RCBANDIT){
if (dotVelocity * GAME_SPEED_TO_METERS_PER_SECOND / 2 > distanceUntilHit)
pPed->SetEvasiveStep(pVehicle, 0);
- }
- else if (dotVelocity > 0.3f) {
+ }else if (dotVelocity > 0.3f) {
if (sideLength + 0.1f < sidewaysDistance)
pPed->SetEvasiveStep(pVehicle, 0);
else
pPed->SetEvasiveDive(pVehicle, 0);
- }
- else if (dotVelocity > 0.1f) {
+ }else if (dotVelocity > 0.1f) {
if (sideLength - 0.5f < sidewaysDistance)
pPed->SetEvasiveStep(pVehicle, 0);
else
@@ -1038,7 +1289,7 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f
if (distanceUntilHit < 10.0f){
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS ||
pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_SLOW_DOWN_FOR_CARS){
- *pSpeed = Min(*pSpeed, ABS(distanceUntilHit - 1.0f) * 0.1f * curSpeed);
+ *pSpeed = Min(*pSpeed, ABS(distanceUntilHit - 1.0f) / 10.0f * curSpeed);
pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = true;
if (distanceUntilHit < 2.0f){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
@@ -1073,11 +1324,11 @@ void CCarCtrl::SlowCarDownForCarsSectorList(CPtrList& lst, CVehicle* pVehicle, f
void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pSpeed, float curSpeed)
{
CVector forwardA = pVehicle->GetForward();
- ((CVector2D)forwardA).NormaliseSafe();
+ ((CVector2D)forwardA).Normalise();
if (DotProduct2D(pOtherEntity->GetPosition() - pVehicle->GetPosition(), forwardA) < 0.0f)
return;
CVector forwardB = pOtherEntity->GetForward();
- ((CVector2D)forwardB).NormaliseSafe();
+ ((CVector2D)forwardB).Normalise();
forwardA.z = forwardB.z = 0.0f;
CVehicle* pOtherVehicle = (CVehicle*)pOtherEntity;
/* why is the argument CEntity if it's always CVehicle anyway and is casted? */
@@ -1088,8 +1339,8 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle,
float proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0);
float proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1);
float minProximity = Min(proximityA, proximityB);
- if (minProximity >= 0.0f && minProximity < 1.0f){
- minProximity = Max(0.0f, (minProximity - 0.2f) * 1.25f);
+ if (minProximity >= 0.0f && minProximity < 1.5f){
+ minProximity = Max(0.0f, (minProximity - 0.2f) / 1.3f);
pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;
*pSpeed = Min(*pSpeed, minProximity * curSpeed);
}
@@ -1236,7 +1487,7 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle*
float CCarCtrl::FindAngleToWeaveThroughTraffic(CVehicle* pVehicle, CPhysical* pTarget, float angleToTarget, float angleForward)
{
- float distanceToTest = Min(2.0f, pVehicle->GetMoveSpeed().Magnitude2D() * 2.5f + 1.0f) * 12.0f;
+ float distanceToTest = Min(2.0f, pVehicle->GetMoveSpeed().Magnitude2D() / 0.4f + 1.0f) * 12.0f;
float left = pVehicle->GetPosition().x - distanceToTest;
float right = pVehicle->GetPosition().x + distanceToTest;
float top = pVehicle->GetPosition().y - distanceToTest;
@@ -1315,22 +1566,24 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)
{
+ CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
+ if (pVehicle->bPartOfConvoy && pOtherCar->bPartOfConvoy)
+ return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle())
return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)
return;
- CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
CVector2D vecDiff = pOtherCar->GetPosition() - pVehicle->GetPosition();
float angleBetweenVehicles = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
if (distance < 1.0f)
return;
if (DotProduct2D(pVehicle->GetMoveSpeed() - pOtherCar->GetMoveSpeed(), vecDiff) * 110.0f -
- pOtherCar->GetModelInfo()->GetColModel()->boundingSphere.radius -
- pVehicle->GetModelInfo()->GetColModel()->boundingSphere.radius < distance)
+ pOtherCar->GetColModel()->boundingSphere.radius -
+ pVehicle->GetColModel()->boundingSphere.radius < distance)
return;
CVector2D forward = pVehicle->GetForward();
- forward.NormaliseSafe();
+ forward.Normalise();
float forwardAngle = CGeneral::GetATanOfXY(forward.x, forward.y);
float angleDiff = angleBetweenVehicles - forwardAngle;
float lenProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.y * Sin(angleDiff));
@@ -1370,7 +1623,7 @@ void CCarCtrl::WeaveThroughPedsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
continue;
if (Abs(pPed->GetPosition().z - pVehicle->GetPosition().z) >= PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING)
continue;
- if (pPed->m_pCurSurface != pVehicle)
+ if (pPed->m_pCurSurface != pVehicle && pPed->m_attachedTo != pVehicle)
WeaveForPed(pPed, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight);
}
@@ -1475,6 +1728,7 @@ void CCarCtrl::WeaveForObject(CEntity* pOtherEntity, CVehicle* pVehicle, float*
bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)
{
+ pVehicle->AutoPilot.m_nCruiseSpeedMultiplierType = ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode].speedLimit;
switch (pVehicle->AutoPilot.m_nCarMission){
case MISSION_RAMPLAYER_FARAWAY:
case MISSION_BLOCKPLAYER_FARAWAY:
@@ -1501,23 +1755,30 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)
return false;
default:
PickNextNodeRandomly(pVehicle);
+ if (ThePaths.GetNode(pVehicle->AutoPilot.m_nNextRouteNode)->bOnlySmallBoats && BoatWithTallMast(pVehicle->GetModelIndex()))
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
return false;
}
}
void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode;
uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks;
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
-#ifdef FIX_BUGS
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numLeftLanes : pCurLink->numRightLanes;
-#else
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numRightLanes : pCurLink->numLeftLanes;
-#endif
+ uint8 lanesOnCurrentPath;
+ bool isOnOneWayRoad;
+ if (pCurLink->pathNodeIndex == curNode) {
+ lanesOnCurrentPath = pCurLink->numLeftLanes;
+ isOnOneWayRoad = pCurLink->numRightLanes == 0;
+ }
+ else {
+ lanesOnCurrentPath = pCurLink->numRightLanes;
+ isOnOneWayRoad = pCurLink->numLeftLanes == 0;
+ }
uint8 allowedDirections = PATH_DIRECTION_NONE;
uint8 nextLane = pVehicle->AutoPilot.m_nNextLane;
if (nextLane == 0)
@@ -1539,6 +1800,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
CCarPathLink* pNextLink;
CPathNode* pNextPathNode;
bool goingAgainstOneWayRoad;
+ bool nextNodeIsOneWayRoad;
uint8 direction;
for(attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++){
if (attempt != 0){
@@ -1548,7 +1810,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if ((!pNextPathNode->bDeadEnd || pPrevPathNode->bDeadEnd) &&
(!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&
(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) &&
- !goingAgainstOneWayRoad)
+ !goingAgainstOneWayRoad && (!isOnOneWayRoad || !nextNodeIsOneWayRoad))
break;
}
}
@@ -1558,9 +1820,10 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode);
pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;
+ nextNodeIsOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numLeftLanes == 0 : pNextLink->numRightLanes == 0;
}
if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {
- /* If we failed 15 times, then remove dead end and current lane limitations */
+ /* If we failed 15 times, then remove dead end, one way road and current lane limitations */
for (attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++) {
if (attempt != 0) {
if (pVehicle->AutoPilot.m_nNextRouteNode != prevNode) {
@@ -1705,74 +1968,57 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float targetY, CVehicle* pTarget)
#endif
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode];
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
- CPathNode* pTargetNode;
+ CPathNode* pTargetNode[2];
int16 numNodes;
float distanceToTargetNode;
- if (pTarget && pTarget->m_pCurGroundEntity &&
- pTarget->m_pCurGroundEntity->IsBuilding() &&
- ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() &&
- ((CTreadable*)pTarget->m_pCurGroundEntity)->m_nodeIndices[0][0] >= 0){
- CTreadable* pCurrentMapObject = (CTreadable*)pTarget->m_pCurGroundEntity;
- int closestNode = -1;
- float minDist = 100000.0f;
- for (int i = 0; i < 12; i++){
- int node = pCurrentMapObject->m_nodeIndices[0][i];
- if (node < 0)
- break;
- float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude();
- if (dist < minDist){
- minDist = dist;
- closestNode = node;
- }
- }
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
-#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
-#else
- CVector(targetX, targetY, 0.0f),
-#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
- }else
- {
-
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
+ ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
+ CVector(targetX, targetY, targetZ),
#else
- CVector(targetX, targetY, 0.0f),
+ CVector(targetX, targetY, 0.0f),
#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
- }
+ pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);
int newNextNode;
int nextLink;
- if (numNodes != 1 || pTargetNode == pCurNode){
- float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
- nextLink = 0;
- float lowestAngleChange = 10.0f;
- int numLinks = pCurNode->numLinks;
- newNextNode = 0;
- for (int i = 0; i < numLinks; i++){
- int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
- if (conNode == prevNode && i > 1)
- continue;
- CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
- float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
- angle = LimitRadianAngle(angle - currentAngle);
- angle = ABS(angle);
- if (angle < lowestAngleChange){
- lowestAngleChange = angle;
- newNextNode = conNode;
- nextLink = i;
+ if (numNodes != 1 && numNodes != 2 || pTargetNode[0] == pCurNode){
+ if (numNodes != 2 || pTargetNode[1] == pCurNode) {
+ float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ nextLink = 0;
+ float lowestAngleChange = 10.0f;
+ int numLinks = pCurNode->numLinks;
+ newNextNode = 0;
+ for (int i = 0; i < numLinks; i++) {
+ int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
+ if (conNode == prevNode && i > 1)
+ continue;
+ CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
+ float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
+ angle = LimitRadianAngle(angle - currentAngle);
+ angle = ABS(angle);
+ if (angle < lowestAngleChange) {
+ lowestAngleChange = angle;
+ newNextNode = conNode;
+ nextLink = i;
+ }
}
}
- }else{
+ else {
+ nextLink = 0;
+ newNextNode = pTargetNode[1] - ThePaths.m_pathNodes;
+ for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
+ ;
+ }
+ }
+ else {
nextLink = 0;
- newNextNode = pTargetNode - ThePaths.m_pathNodes;
+ newNextNode = pTargetNode[0] - ThePaths.m_pathNodes;
for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
;
}
@@ -1792,11 +2038,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
int8 lanesOnNextNode;
if (curNode >= pVehicle->AutoPilot.m_nNextRouteNode) {
pVehicle->AutoPilot.m_nNextDirection = 1;
- lanesOnNextNode = pNextLink->numLeftLanes;
+ lanesOnNextNode = pNextLink->numRightLanes;
}
else {
pVehicle->AutoPilot.m_nNextDirection = -1;
- lanesOnNextNode = pNextLink->numRightLanes;
+ lanesOnNextNode = pNextLink->numLeftLanes;
}
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();
@@ -1851,6 +2097,8 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
if (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){
@@ -1858,8 +2106,9 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
pVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,
pVehicle, nil, 999999.9f, -1);
- if (pVehicle->AutoPilot.m_nPathFindNodesCount < 1)
+ if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2)
return true;
+ pVehicle->AutoPilot.RemoveOnePathNode();
}
CPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
@@ -1943,6 +2192,7 @@ void CCarCtrl::Init(void)
LastTimeAmbulanceCreated = 0;
#ifdef FIX_BUGS
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
bCarsGeneratedAroundCamera = false;
CountDownToCarsAtStart = 2;
@@ -1950,9 +2200,11 @@ void CCarCtrl::Init(void)
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++){
- for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++)
- CarArrays[i][j] = 0;
- NextCarOfRating[i] = 0;
+ for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++) {
+ LoadedCarsArray[i][j] = -1;
+ }
+ NumOfLoadedCarsOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
TotalNumOfCarsOfRating[i] = 0;
}
}
@@ -1970,13 +2222,14 @@ void CCarCtrl::ReInit(void)
LastTimeFireTruckCreated = 0;
LastTimeAmbulanceCreated = 0;
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
CountDownToCarsAtStart = 2;
CarDensityMultiplier = 1.0f;
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++)
- NextCarOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
}
void CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint)
@@ -2086,7 +2339,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNLEFT:
- swerve = -1.0f; // It seems like this should be swerve = 1.0f (fixed in VC)
+ swerve = 1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2094,7 +2347,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNRIGHT:
- swerve = 1.0f; // It seems like this should be swerve = -1.0f (fixed in VC)
+ swerve = -1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2170,7 +2423,13 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
case MISSION_GOTOCOORDS_ACCURATE:
case MISSION_RAMCAR_FARAWAY:
case MISSION_BLOCKCAR_FARAWAY:
- SteerAICarWithPhysicsFollowPath(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ if (pVehicle->AutoPilot.m_bIgnorePathfinding) {
+ *pSwerve = 0.0f;
+ *pAccel = 1.0f;
+ *pBrake = 0.0f;
+ *pHandbrake = false;
+ }else
+ SteerAICarWithPhysicsFollowPath(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
return;
case MISSION_RAMPLAYER_CLOSE:
{
@@ -2205,6 +2464,9 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
SteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle, FindPlayerCoors().x, FindPlayerCoors().y,
FindPlayerSpeed().x, FindPlayerSpeed().y, pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_WAITFORDELETION:
+ case MISSION_HELI_LAND:
+ return;
case MISSION_GOTOCOORDS_STRAIGHT:
case MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
@@ -2218,6 +2480,12 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
*pHandbrake = true;
*pBrake = 0.5f;
return;
+ case MISSION_GOTOCOORDS_ASTHECROWSWIMS:
+ SteerAIBoatWithPhysicsHeadingForTarget(pVehicle,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake);
+ *pHandbrake = false;
+ return;
case MISSION_RAMCAR_CLOSE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, pVehicle->AutoPilot.m_pTargetCar,
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x, pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
@@ -2239,26 +2507,132 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
pVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().y,
pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_HELI_FLYTOCOORS:
+ SteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_ATTACKPLAYER:
+ SteerAIBoatWithPhysicsAttackingPlayer(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_PLANE_FLYTOCOORS:
+ SteerAIPlaneTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, FindPlayerCoors().x, FindPlayerCoors().y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_BLOCKPLAYER_FORWARDANDBACK:
+ SteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
default:
+ assert(0);
+ return;
+ }
+}
+
+void CCarCtrl::SteerAICarBlockingPlayerForwardAndBack(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
+{
+ *pSwerve = 0.0f;
+ *pHandbrake = false;
+ CVector player = FindPlayerSpeed() + 0.1f * FindPlayerEntity()->GetForward();
+ player.z = 0.0f;
+ CVector right(pVehicle->GetRight().x, pVehicle->GetRight().y, 0.0f);
+ right.Normalise();
+ CVector forward(pVehicle->GetForward().x, pVehicle->GetForward().y, 0.0f);
+ forward.Normalise();
+ float dpPlayerAndRight = DotProduct(player, right);
+ if (dpPlayerAndRight == 0.0f)
+ dpPlayerAndRight = 0.01f;
+ float dpDiffAndRight = -DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), right) / dpPlayerAndRight;
+ if (dpDiffAndRight < 0.0f) {
+ *pAccel = 0.0f;
+ *pBrake = 0.0f;
return;
}
+ float dpSpeedAndForward = DotProduct(pVehicle->GetMoveSpeed(), forward);
+ float dpPlayerAndForward = DotProduct(player, forward);
+ float dpDiffAndForward = DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), forward);
+ float multiplier = dpPlayerAndForward * dpDiffAndRight + dpDiffAndForward - dpSpeedAndForward * dpDiffAndRight;
+ if (multiplier > 0) {
+ *pAccel = Min(1.0f, 0.1f * multiplier);
+ *pBrake = 0.0f;
+ }
+ else if (dpSpeedAndForward > 0) {
+ *pAccel = 0.0f;
+ *pBrake = Min(1.0f, -0.1f * multiplier);
+ if (*pBrake > 0.95f)
+ *pHandbrake = true;
+ }
+ else {
+ *pAccel = Max(-1.0f, 0.1f * multiplier);
+ *pBrake = 0.0f;
+ }
+}
+
+void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
+{
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+ steerAngle = Clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
+ steerAngle *= -1;
+ }
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
+ }
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
}
-void CCarCtrl::SteerAIBoatWithPhysics(CBoat* pBoat)
+void CCarCtrl::SteerAIBoatWithPhysicsAttackingPlayer(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
- if (pBoat->AutoPilot.m_nCarMission == MISSION_GOTOCOORDS_ASTHECROWSWIMS){
- SteerAIBoatWithPhysicsHeadingForTarget(pBoat,
- pBoat->AutoPilot.m_vecDestinationCoors.x, pBoat->AutoPilot.m_vecDestinationCoors.y,
- &pBoat->m_fSteeringLeftRight, &pBoat->m_fAccelerate, &pBoat->m_fBrake);
- }else if (pBoat->AutoPilot.m_nCarMission == MISSION_NONE){
- pBoat->m_fSteeringLeftRight = 0.0f;
- pBoat->m_fAccelerate = 0.0f;
- pBoat->m_fBrake = 0.0f;
+ float distanceToPlayer = (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
+ float projection = Min(distanceToPlayer / 20.0f, 2.0f);
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ CVector2D vecToProjection = FindPlayerCoors() + FindPlayerSpeed() * projection * GAME_SPEED_TO_CARAI_SPEED;
+ float angleToTarget = CGeneral::GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
}
- pBoat->m_fSteerAngle = pBoat->m_fSteeringLeftRight;
- pBoat->m_fGasPedal = pBoat->m_fAccelerate;
- pBoat->m_fBrakePedal = pBoat->m_fBrake;
- pBoat->bIsHandbrakeOn = false;
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
+ }
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
+ *pHandbrake = false;
+ if (pVehicle->GetModelIndex() == MI_PREDATOR && distanceToPlayer < 40.0f && steerAngle < 0.15f)
+ pVehicle->FireFixedMachineGuns();
}
float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
@@ -2266,10 +2640,151 @@ float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
return pVehicle->GetModelIndex() == MI_ENFORCER ? 0.7f : DEFAULT_MAX_STEER_ANGLE;
}
+void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli)
+{
+ if (pHeli->m_aWheelSpeed[1] < 0.22f)
+ pHeli->m_aWheelSpeed[1] += 0.001f;
+ if (pHeli->m_aWheelSpeed[1] < 0.15f)
+ return;
+ CVector2D vecToTarget = pHeli->AutoPilot.m_vecDestinationCoors - pHeli->GetPosition();
+ float distanceToTarget = vecToTarget.Magnitude();
+#ifdef FIX_BUGS
+ float speed = pHeli->AutoPilot.GetCruiseSpeed() * 0.01f;
+#else
+ float speed = pHeli->AutoPilot.m_nCruiseSpeed * 0.01f;
+#endif
+ if (distanceToTarget <= 100.0f)
+ {
+ if (distanceToTarget > 75.0f)
+ speed *= 0.7f;
+ else if (distanceToTarget > 10.0f)
+ speed *= 0.4f;
+ else
+ speed *= 0.2f;
+ }
+ vecToTarget.Normalise();
+ CVector2D vecAdvanceThisFrame(vecToTarget * speed);
+ float resistance = Pow(0.997f, CTimer::GetTimeStep());
+ pHeli->m_vecMoveSpeed.x *= resistance;
+ pHeli->m_vecMoveSpeed.y *= resistance;
+ CVector2D vecSpeedDirection = vecAdvanceThisFrame - pHeli->m_vecMoveSpeed;
+ float vecSpeedChangeLength = vecSpeedDirection.Magnitude();
+ vecSpeedDirection.Normalise();
+ float changeMultiplier = 0.002f * CTimer::GetTimeStep();
+ if (distanceToTarget < 5.0f)
+ changeMultiplier /= 5.0f;
+ if (vecSpeedChangeLength < changeMultiplier)
+ pHeli->SetMoveSpeed(vecAdvanceThisFrame.x, vecAdvanceThisFrame.y, pHeli->GetMoveSpeed().z);
+ else
+ pHeli->AddToMoveSpeed(vecSpeedDirection * changeMultiplier);
+ pHeli->GetMatrix().Translate(CTimer::GetTimeStep() * pHeli->GetMoveSpeed().x, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().y, 0.0f);
+ float ZTarget = pHeli->AutoPilot.m_vecDestinationCoors.z;
+ if (CTimer::GetTimeInMilliseconds() & 0x800) // switch every ~2 seconds
+ ZTarget += 2.0f;
+ float ZSpeedTarget = (ZTarget - pHeli->GetPosition().z) * 0.01f;
+ float ZSpeedChangeTarget = ZSpeedTarget - pHeli->GetMoveSpeed().z;
+ float ZSpeedChangeMax = 0.001f * CTimer::GetTimeStep();
+ if (!pHeli->bHeliDestroyed) {
+ if (Abs(ZSpeedChangeTarget) < ZSpeedChangeMax)
+ pHeli->SetMoveSpeed(pHeli->GetMoveSpeed().x, pHeli->GetMoveSpeed().y, ZSpeedTarget);
+ else if (ZSpeedChangeTarget < 0.0f)
+ pHeli->AddToMoveSpeed(0.0f, 0.0f, -ZSpeedChangeMax);
+ else
+ pHeli->AddToMoveSpeed(0.0f, 0.0f, 1.5f * ZSpeedChangeMax);
+ }
+ pHeli->GetMatrix().Translate(0.0f, 0.0f, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().z);
+ pHeli->m_vecTurnSpeed.z *= Pow(0.99f, CTimer::GetTimeStep());
+ float ZTurnSpeedTarget;
+ if (distanceToTarget < 8.0f && pHeli->m_fHeliOrientation < 0.0f)
+ ZTurnSpeedTarget = 0.0f;
+ else {
+ float fAngleTarget = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y) + PI;
+ if (pHeli->m_fHeliOrientation >= 0.0f)
+ fAngleTarget = pHeli->m_fHeliOrientation;
+ fAngleTarget -= pHeli->m_fOrientation;
+ while (fAngleTarget < -PI)
+ fAngleTarget += TWOPI;
+ while (fAngleTarget > PI)
+ fAngleTarget -= TWOPI;
+ if (Abs(fAngleTarget) <= 0.4f)
+ ZTurnSpeedTarget = 0.0f;
+ else if (fAngleTarget < 0.0f)
+ ZTurnSpeedTarget = -0.03f;
+ else
+ ZTurnSpeedTarget = 0.03f;
+ }
+ float ZTurnSpeedChangeTarget = ZTurnSpeedTarget - pHeli->GetTurnSpeed().z;
+ float ZTurnSpeedLimit = 0.0002f * CTimer::GetTimeStep();
+ if (Abs(ZTurnSpeedChangeTarget) < ZTurnSpeedLimit)
+ pHeli->m_vecTurnSpeed.z = ZTurnSpeedTarget;
+ else if (ZTurnSpeedChangeTarget < 0.0f)
+ pHeli->m_vecTurnSpeed.z -= ZTurnSpeedLimit;
+ else
+ pHeli->m_vecTurnSpeed.z += ZTurnSpeedLimit;
+ pHeli->m_fOrientation += pHeli->GetTurnSpeed().z * CTimer::GetTimeStep();
+ CVector up;
+ if (pHeli->bHeliMinimumTilt)
+ up = CVector(0.5f * pHeli->GetMoveSpeed().x, 0.5f * pHeli->GetMoveSpeed().y, 1.0f);
+ else
+ up = CVector(3.0f * pHeli->GetMoveSpeed().x, 3.0f * pHeli->GetMoveSpeed().y, 1.0f);
+ up.Normalise();
+ CVector forward(Cos(pHeli->m_fOrientation), Sin(pHeli->m_fOrientation), 0.0f);
+ CVector right = CrossProduct(up, forward);
+ forward = CrossProduct(up, right);
+ pHeli->GetMatrix().GetRight() = right;
+ pHeli->GetMatrix().GetForward() = forward;
+ pHeli->GetMatrix().GetUp() = up;
+}
+
+void CCarCtrl::SteerAIPlaneTowardsTargetCoors(CAutomobile* pPlane)
+{
+ CVector2D vecToTarget = pPlane->AutoPilot.m_vecDestinationCoors - pPlane->GetPosition();
+ float fForwardZ = (pPlane->AutoPilot.m_vecDestinationCoors.z - pPlane->GetPosition().z) / vecToTarget.Magnitude();
+ fForwardZ = Clamp(fForwardZ, -0.3f, 0.3f);
+ float angle = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y);
+ while (angle > TWOPI)
+ angle -= TWOPI;
+ float difference = LimitRadianAngle(angle - pPlane->m_fOrientation);
+ float steer = difference > 0.0f ? 0.04f : -0.04f;
+ if (Abs(difference) < 0.2f)
+ steer *= 5.0f * Abs(difference);
+ pPlane->m_fPlaneSteer *= Pow(0.96f, CTimer::GetTimeStep());
+ float steerChange = steer - pPlane->m_fPlaneSteer;
+ float maxChange = 0.003f * CTimer::GetTimeStep();
+ if (Abs(steerChange) < maxChange)
+ pPlane->m_fPlaneSteer = steer;
+ else if (steerChange < 0.0f)
+ pPlane->m_fPlaneSteer -= maxChange;
+ else
+ pPlane->m_fPlaneSteer += maxChange;
+ pPlane->m_fOrientation += pPlane->m_fPlaneSteer * CTimer::GetTimeStep();
+ CVector up(0.0f, 0.0f, 1.0f);
+ up.Normalise();
+ CVector forward(Cos(pPlane->m_fOrientation), Sin(pPlane->m_fOrientation), fForwardZ);
+ forward.Normalise();
+ CVector right = CrossProduct(up, forward);
+ right.z -= 5.0f * pPlane->m_fPlaneSteer;
+ right.Normalise();
+ up = CrossProduct(forward, right);
+ up.Normalise();
+ right = CrossProduct(forward, up);
+ pPlane->GetMatrix().GetRight() = right;
+ pPlane->GetMatrix().GetForward() = forward;
+ pPlane->GetMatrix().GetUp() = up;
+ float newSplit = 1.0f - Pow(0.95f, CTimer::GetTimeStep());
+ float oldSplit = 1.0f - newSplit;
+#ifdef FIX_BUGS
+ pPlane->m_vecMoveSpeed = pPlane->m_vecMoveSpeed * oldSplit + pPlane->AutoPilot.GetCruiseSpeed() * 0.01f * forward * newSplit;
+#else
+ pPlane->m_vecMoveSpeed = pPlane->m_vecMoveSpeed * oldSplit + pPlane->AutoPilot.m_nCruiseSpeed * 0.01f * forward * newSplit;
+#endif
+ pPlane->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+}
+
void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
CVector2D forward = pVehicle->GetForward();
- forward.NormaliseSafe();
+ forward.Normalise();
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
CVector2D currentPathLinkForward(pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection,
@@ -2294,17 +2809,13 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
switch (pVehicle->AutoPilot.m_nCarMission){
case MISSION_GOTOCOORDS:
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
case MISSION_GOTOCOORDS_ACCURATE:
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
default: break;
}
@@ -2341,11 +2852,14 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
switch (pVehicle->AutoPilot.m_nDrivingStyle) {
case DRIVINGSTYLE_STOP_FOR_CARS:
case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:
+ case DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS:
speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle);
#ifdef FIX_BUGS
- if (pVehicle->AutoPilot.m_nCruiseSpeed != 0)
+ if (pVehicle->AutoPilot.GetCruiseSpeed() != 0)
+ speedStyleMultiplier /= pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ speedStyleMultiplier /= pVehicle->AutoPilot.m_nCruiseSpeed;
#endif
- speedStyleMultiplier /= pVehicle->AutoPilot.m_nCruiseSpeed;
break;
default:
speedStyleMultiplier = 1.0f;
@@ -2407,7 +2921,7 @@ void CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysic
{
*pHandbrake = false;
CVector2D forward = pVehicle->GetForward();
- forward.NormaliseSafe();
+ forward.Normalise();
float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
@@ -2425,7 +2939,7 @@ void CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysic
float speedDiff = speedTarget - currentSpeed;
if (speedDiff <= 0.0f){
*pAccel = 0.0f;
- *pBrake = Min(0.5f, -speedDiff * 0.05f);
+ *pBrake = Min(0.5f, -speedDiff / 20.0f);
}else if (currentSpeed < 25.0f){
*pAccel = Min(1.0f, speedDiff * 0.1f);
*pBrake = 0.0f;
@@ -2450,6 +2964,7 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget(CVehicle* pVehicle, floa
pVehicle->AutoPilot.m_nCarMission = (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_CLOSE) ?
MISSION_BLOCKCAR_HANDBRAKESTOP : MISSION_BLOCKPLAYER_HANDBRAKESTOP;
}
+
void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle, float targetX, float targetY, float targetSpeedX, float targetSpeedY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
*pSwerve = 0.0f;
@@ -2491,26 +3006,6 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle,
}
}
-void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CBoat* pBoat, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
-{
- CVector2D forward(pBoat->GetForward());
- forward.NormaliseSafe();
- CVector2D distanceToTarget = CVector2D(targetX, targetY) - pBoat->GetPosition();
- float angleToTarget = CGeneral::GetATanOfXY(distanceToTarget.x, distanceToTarget.y);
- float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
- float angleDiff = LimitRadianAngle(angleToTarget - angleForward);
- angleDiff = Min(DEFAULT_MAX_STEER_ANGLE, Max(-DEFAULT_MAX_STEER_ANGLE, angleDiff));
- float currentSpeed = pBoat->GetMoveSpeed().Magnitude2D(); // +0.0f for some reason
- float speedDiff = pBoat->AutoPilot.m_nCruiseSpeed - currentSpeed * 60.0f;
- if (speedDiff > 0.0f){
- float accRemaining = speedDiff / pBoat->AutoPilot.m_nCruiseSpeed;
- *pAccel = (accRemaining > 0.25f) ? 1.0f : 1.0f - (0.25f - accRemaining) * 4.0f;
- }else
- *pAccel = (speedDiff < -5.0f) ? -0.2f : -0.1f;
- *pBrake = 0.0f;
- *pSwerve = angleDiff;
-}
-
void
CCarCtrl::RegisterVehicleOfInterest(CVehicle* pVehicle)
{
@@ -2618,6 +3113,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
pVehicle->AutoPilot.m_aPathFindNodesInfo, &pVehicle->AutoPilot.m_nPathFindNodesCount);
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2){
pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0;
+ pVehicle->AutoPilot.m_nPathFindNodesCount = 0;
return true;
}
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
@@ -2632,6 +3128,8 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int nextLink;
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
for (nextLink = 0; nextLink < 12; nextLink++)
@@ -2645,11 +3143,23 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
curLink = 0;
curConnection = ThePaths.m_carPathConnections[pCurNode->firstLink];
}else{
- curConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo;
- while (curConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){
- curLink = CGeneral::GetRandomNumber() % pCurNode->numLinks;
- curConnection = ThePaths.m_carPathConnections[curLink + pCurNode->firstLink];
+ int closestLink = -1;
+ float md = 999999.9f;
+
+ for (curLink = 0; curLink < pCurNode->numLinks; curLink++) {
+ int node = ThePaths.ConnectedNode(curLink + pCurNode->firstLink);
+ CPathNode* pNode = &ThePaths.m_pathNodes[node];
+ if (node == pVehicle->AutoPilot.m_nNextRouteNode)
+ continue;
+ CVector vCurPos = pCurNode->GetPosition();
+ CVector vNextPos = pNode->GetPosition();
+ float dist = CCollision::DistToLine(&vCurPos, &vNextPos, &pVehicle->GetPosition());
+ if (dist < md) {
+ md = dist;
+ closestLink = curLink;
+ }
}
+ curConnection = ThePaths.m_carPathConnections[closestLink + pCurNode->firstLink];
}
pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection;
pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1;
@@ -2659,6 +3169,8 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
{
if (FindPlayerPed()->m_pWanted->GetWantedLevel() > 3)
return;
+ if (CGame::IsInInterior())
+ return;
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +
NumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)
return;
@@ -2674,8 +3186,9 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
CStreaming::RequestModel(MI_AMBULAN, STREAMFLAGS_DEPENDENCY);
CStreaming::RequestModel(MI_MEDIC, STREAMFLAGS_DONT_REMOVE);
if (CStreaming::HasModelLoaded(MI_AMBULAN) && CStreaming::HasModelLoaded(MI_MEDIC)){
- if (GenerateOneEmergencyServicesCar(MI_AMBULAN, pNearestAccident->m_pVictim->GetPosition()))
+ if (GenerateOneEmergencyServicesCar(MI_AMBULAN, pNearestAccident->m_pVictim->GetPosition())){
LastTimeAmbulanceCreated = CTimer::GetTimeInMilliseconds();
+ }
}
}
}
@@ -2693,8 +3206,15 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
CStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY);
CStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE);
if (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){
- if (GenerateOneEmergencyServicesCar(MI_FIRETRUCK, pNearestFire->m_vecPos))
+ if (GenerateOneEmergencyServicesCar(MI_FIRETRUCK, pNearestFire->m_vecPos)){
LastTimeFireTruckCreated = CTimer::GetTimeInMilliseconds();
+#ifdef SECUROM
+ if ((myrand() & 7) == 5){
+ // if pirated game
+ CPickups::Init();
+ }
+#endif
+ }
}
}
}
@@ -2711,12 +3231,14 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
int curNode, nextNode;
float posBetweenNodes;
while (!created && attempts < 5){
- if (ThePaths.NewGenerateCarCreationCoors(pPlayerPos.x, pPlayerPos.y, 0.707f, 0.707f,
- 120.0f, -1.0f, true, &spawnPos, &curNode, &nextNode, &posBetweenNodes, false)){
+ if (ThePaths.GenerateCarCreationCoors(pPlayerPos.x, pPlayerPos.y, 0.707f, 0.707f,
+ REQUEST_ONSCREEN_DISTANCE, -1.0f, true, &spawnPos, &curNode, &nextNode, &posBetweenNodes, false)){
int16 colliding[2];
- CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
- if (colliding[0] == 0)
- created = true;
+ if (!ThePaths.GetNode(curNode)->bWaterPath) {
+ CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
+ if (colliding[0] == 0)
+ created = true;
+ }
}
attempts += 1;
}
@@ -2730,7 +3252,7 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
CVector2D direction = vecPos - spawnPos;
- direction.NormaliseSafe();
+ direction.Normalise();
pVehicle->GetForward() = CVector(direction.x, direction.y, 0.0f);
pVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f);
pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);
@@ -2775,18 +3297,24 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
if (remove){
switch (pVehicle->VehicleCreatedBy){
case RANDOM_VEHICLE:
- if (pVehicle->bIsLawEnforcer)
- --NumLawEnforcerCars;
- --NumRandomCars;
+ if (pVehicle->bIsLawEnforcer) {
+ if (--NumLawEnforcerCars < 0)
+ NumLawEnforcerCars = 0;
+ }
+ if (--NumRandomCars < 0)
+ NumRandomCars = 0;
return;
case MISSION_VEHICLE:
- --NumMissionCars;
+ if (--NumMissionCars < 0)
+ NumMissionCars = 0;
return;
case PARKED_VEHICLE:
- --NumParkedCars;
+ if (--NumParkedCars < 0)
+ NumParkedCars = 0;
return;
case PERMANENT_VEHICLE:
- --NumPermanentCars;;
+ if (--NumPermanentCars < 0)
+ NumPermanentCars = 0;
return;
}
}
@@ -2804,7 +3332,7 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
++NumParkedCars;
return;
case PERMANENT_VEHICLE:
- ++NumPermanentCars;;
+ ++NumPermanentCars;
return;
}
}
@@ -2812,12 +3340,30 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)
{
+#ifdef GTA_BRIDGE
return mi == MI_BRIDGELIFT || mi == MI_BRIDGEROADSEGMENT;
+#else
+ return false;
+#endif
}
bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
{
+#ifdef GTA_BRIDGE // actually they forgot that in VC...
// bridge moves up and down
return x > -342.0f && x < -219.0f &&
y > -677.0f && y < -580.0f;
+#else
+ return false;
+#endif
+}
+
+float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
+{
+ switch (type)
+ {
+ case 1: return 1.5f;
+ case 2: return 2.0f;
+ }
+ return 1.0f;
}
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 457224fb..5efbe275 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -9,14 +9,13 @@
#define TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING 2500
class CZoneInfo;
+class CAutomobile;
enum{
MAX_CARS_TO_KEEP = 2,
- MAX_CAR_MODELS_IN_ARRAY = 256,
+ MAX_CAR_MODELS_IN_ARRAY = 25,
};
-#define LANE_WIDTH 5.0f
-
#ifdef FIX_BUGS
#define FIX_PATHFIND_BUG
#endif
@@ -25,24 +24,37 @@ class CCarCtrl
{
public:
enum eCarClass {
- POOR = 0,
+ NORMAL = 0,
+ POOR,
RICH,
EXEC,
WORKER,
- SPECIAL,
BIG,
TAXI,
- TOTAL_CUSTOM_CLASSES,
- MAFIA,
- TRIAD,
- DIABLO,
- YAKUZA,
- YARDIE,
- COLOMB,
- NINES,
- GANG8,
+ MOPED,
+ MOTORBIKE,
+
+ LEISUREBOAT,
+ WORKERBOAT,
+
+ COPS,
+ CUBAN,
+ HAITIAN,
+ STREET,
+ DIAZ,
+ BIKER,
+ SECURITY,
+ PLAYER,
+ GOLFERS,
GANG9,
- COPS
+ COPS_BOAT,
+ FIRST_CAR_RATING = NORMAL,
+ FIRST_BOAT_RATING = LEISUREBOAT,
+ FIRST_GANG_CAR_RATING = CUBAN,
+ NUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1,
+ NUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1,
+ NUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1,
+ TOTAL_CUSTOM_CLASSES = NUM_CAR_CLASSES + NUM_BOAT_CLASSES
};
static void SwitchVehicleToRealPhysics(CVehicle*);
@@ -58,7 +70,7 @@ public:
static void GenerateRandomCars(void);
static void GenerateOneRandomCar(void);
static void GenerateEmergencyServicesCar(void);
- static int32 ChooseModel(CZoneInfo*, CVector*, int*);
+ static int32 ChooseModel(CZoneInfo*, int*);
static int32 ChoosePoliceCarModel(void);
static int32 ChooseGangCarModel(int32 gang);
static void RemoveDistantCars(void);
@@ -94,17 +106,29 @@ public:
static float FindSpeedMultiplier(float, float, float, float);
static void SteerAICarWithPhysics(CVehicle*);
static void SteerAICarWithPhysics_OnlyMission(CVehicle*, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysics(CBoat*);
static float FindMaxSteerAngle(CVehicle*);
static void SteerAICarWithPhysicsFollowPath(CVehicle*, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsHeadingForTarget(CVehicle*, CPhysical*, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysicsHeadingForTarget(CBoat*, float, float, float*, float*, float*);
static bool ThisRoadObjectCouldMove(int16);
static void ClearInterestingVehicleList();
static void FindLinksToGoWithTheseNodes(CVehicle*);
static bool GenerateOneEmergencyServicesCar(uint32, CVector);
+ static float FindSpeedMultiplierWithSpeedFromNodes(int8);
+ static int32 ChooseBoatModel(int32);
+ static int32 ChooseBoatRating(CZoneInfo* pZoneInfo);
+ static int32 ChooseCarRating(CZoneInfo* pZoneInfo);
+ static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);
+ static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating);
+ static int32 ChooseCarModelToLoad(int32 rating);
+ static bool BoatWithTallMast(int32 mi);
+ static void RemoveCarsIfThePoolGetsFull(void);
+ static void SteerAIBoatWithPhysicsHeadingForTarget(CVehicle*, float, float, float*, float*, float*);
+ static void SteerAIHeliTowardsTargetCoors(CAutomobile*);
+ static void SteerAIPlaneTowardsTargetCoors(CAutomobile*);
+ static void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*);
+ static void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
@@ -121,6 +145,7 @@ public:
return angle;
}
+ static bool bMadDriversCheat;
static int32 NumLawEnforcerCars;
static int32 NumAmbulancesOnDuty;
static int32 NumFiretrucksOnDuty;
@@ -136,8 +161,14 @@ public:
static uint32 LastTimeFireTruckCreated;
static uint32 LastTimeAmbulanceCreated;
static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
- static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+
+ static int32 MiamiViceCycle;
+ static uint32 LastTimeMiamiViceGenerated;
+ static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+ static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+ static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+ static int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
};
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file
diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp
index 0a01a7aa..5b590440 100644
--- a/src/control/Curves.cpp
+++ b/src/control/Curves.cpp
@@ -11,7 +11,7 @@ float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float di
if (dp > 0.9f)
return distance + Abs((pPoint1->x * dir1Y - pPoint1->y * dir1X) - (pPoint2->x * dir1Y - pPoint2->y * dir1X));
else
- return ((1.0f - dp) * 0.2f + 1.0f) * distance;
+ return ((1.0f - dp) * 0.25f + 1.0f) * distance;
}
void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVector* pDir2, float between, int32 timeOnCurve, CVector* pOutPos, CVector* pOutDir)
@@ -19,7 +19,31 @@ void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVe
float actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y);
CVector2D dir1 = *pDir1 * actualFactor;
CVector2D dir2 = *pDir2 * actualFactor;
- float curveCoef = 0.5f - 0.5f * Cos(3.1415f * between);
+ float t1 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir1));
+ float t2 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir2));
+ float curveCoef;
+ if (t1 > t2) {
+ float coef = (t1 - t2) / (t1 + t2);
+#ifdef FIX_BUGS
+ if (between <= coef)
+#else
+ if (between < coef)
+#endif
+ curveCoef = 0.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * (between - coef) * (t1 + t2) / (2 * t2));
+ }
+ else {
+ float coef = 2 * t1 / (t1 + t2);
+#ifdef FIX_BUGS
+ if (coef <= between)
+#else
+ if (coef < between)
+#endif
+ curveCoef = 1.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1));
+ }
*pOutPos = CVector(
(pPos1->x + between * dir1.x) * (1.0f - curveCoef) + (pPos2->x - (1 - between) * dir2.x) * curveCoef,
(pPos1->y + between * dir1.y) * (1.0f - curveCoef) + (pPos2->y - (1 - between) * dir2.y) * curveCoef,
diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp
index 9f6809df..a6aca57e 100644
--- a/src/control/Darkel.cpp
+++ b/src/control/Darkel.cpp
@@ -7,15 +7,14 @@
#include "Timer.h"
#include "DMAudio.h"
#include "Population.h"
+#include "Replay.h"
#include "Weapon.h"
#include "World.h"
#include "Stats.h"
#include "Font.h"
#include "Text.h"
#include "Vehicle.h"
-#ifdef FIX_BUGS
-#include "Replay.h"
-#endif
+#include "GameLogic.h"
#define FRENZY_ANY_PED -1
#define FRENZY_ANY_CAR -2
@@ -26,9 +25,11 @@ int32 CDarkel::TimeOfFrenzyStart;
int32 CDarkel::WeaponType;
int32 CDarkel::AmmoInterruptedWeapon;
int32 CDarkel::KillsNeeded;
-int8 CDarkel::InterruptedWeapon;
+int32 CDarkel::InterruptedWeaponType;
+int32 CDarkel::InterruptedWeaponSelected;
/*
+ * TODO: Collect timer/kill counter RGBA colors on top like in Hud/Frontend.
* bStandardSoundAndMessages is a completely beta thing,
* makes game handle sounds & messages instead of SCM (just like in GTA2)
* but it's never been used in the game. Has unused sliding text when frenzy completed etc.
@@ -59,14 +60,12 @@ CDarkel::CalcFade(uint32 time, uint32 start, uint32 end)
return 0;
}
-// Screen positions taken from VC
void
CDarkel::DrawMessages()
{
-#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
-#endif
+
switch (Status) {
case KILLFRENZY_ONGOING:
{
@@ -79,8 +78,8 @@ CDarkel::DrawMessages()
#endif
CFont::SetCentreOn();
CFont::SetPropOn();
- uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart;
- if (CDarkel::bStandardSoundAndMessages) {
+ uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;
+ if (bStandardSoundAndMessages) {
if (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) {
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));
@@ -89,7 +88,7 @@ CDarkel::DrawMessages()
#endif
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000)));
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
if (pStartMessage) {
CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);
}
@@ -103,7 +102,7 @@ CDarkel::DrawMessages()
#endif
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000)));
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
if (pStartMessage) {
CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);
}
@@ -117,53 +116,30 @@ CDarkel::DrawMessages()
CFont::SetCentreOff();
CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING);
- if (CDarkel::TimeLimit >= 0) {
- uint32 timeLeft = CDarkel::TimeLimit - (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart);
+ if (TimeLimit >= 0) {
+ uint32 timeLeft = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart);
sprintf(gString, "%d:%02d", timeLeft / 60000, timeLeft % 60000 / 1000);
AsciiToUnicode(gString, gUString);
if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) {
CFont::SetColor(CRGBA(0, 0, 0, 255));
-#if defined(PS2_HUD) || defined(FIX_BUGS)
- #ifdef FIX_BUGS
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f - 1.0f), SCREEN_SCALE_Y(108.0f + 1.0f), gUString);
- #else
- CFont::PrintString(SCREEN_WIDTH-(34.0f - 1.0f), 108.0f + 1.0f, gUString);
- #endif
-#else
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f + 1.0f), SCREEN_SCALE_Y(108.0f + 1.0f), gUString);
-#endif
- CFont::SetColor(CRGBA(150, 100, 255, 255));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString);
+ CFont::SetColor(CRGBA(0, 207, 133, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString);
}
}
- sprintf(gString, "%d", (CDarkel::KillsNeeded >= 0 ? CDarkel::KillsNeeded : 0));
+ sprintf(gString, "%d", (KillsNeeded >= 0 ? KillsNeeded : 0));
AsciiToUnicode(gString, gUString);
CFont::SetColor(CRGBA(0, 0, 0, 255));
-#ifdef FIX_BUGS
-#define DARKEL_COUNTER_HEIGHT 143.0f
-#else
-#define DARKEL_COUNTER_HEIGHT 128.0f
-#endif
-
-#if defined(PS2_HUD) || defined(FIX_BUGS)
- #ifdef FIX_BUGS
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f - 1.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT + 1.0f), gUString);
- #else
- CFont::PrintString(SCREEN_WIDTH-(34.0f - 1.0f), DARKEL_COUNTER_HEIGHT + 1.0f, gUString);
- #endif
-#else
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f + 1.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT + 1.0f), gUString);
-#endif
- CFont::SetColor(CRGBA(255, 128, 128, 255));
- CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT), gUString);
-#undef DARKEL_COUNTER_HEIGHT
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(144.0f), gUString);
+ CFont::SetColor(CRGBA(156, 91, 40, 255));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(143.0f), gUString);
break;
}
case KILLFRENZY_PASSED:
{
- if (CDarkel::bStandardSoundAndMessages) {
- uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart;
- if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) {
+ if (bStandardSoundAndMessages) {
+ uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;
+ if (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart < 5000) {
CFont::SetBackgroundOff();
#ifdef FIX_BUGS
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
@@ -178,7 +154,7 @@ CDarkel::DrawMessages()
#endif
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000)));
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
#ifdef FIX_BUGS
int y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f);
#else
@@ -235,7 +211,20 @@ CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle)
}
}
RegisteredKills[vehicle->GetModelIndex()]++;
- CStats::CarsExploded++;
+ switch (vehicle->GetVehicleAppearance()) {
+ case VEHICLE_APPEARANCE_CAR:
+ case VEHICLE_APPEARANCE_BIKE:
+ CStats::CarsExploded++;;
+ break;
+ case VEHICLE_APPEARANCE_HELI:
+ case VEHICLE_APPEARANCE_PLANE:
+ CStats::HelisDestroyed++;
+ break;
+ case VEHICLE_APPEARANCE_BOAT:
+ CStats::BoatsExploded++;
+ break;
+ }
+
}
void
@@ -294,28 +283,14 @@ CDarkel::ResetOnPlayerDeath()
Status = KILLFRENZY_FAILED;
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
- eWeaponType fixedWeapon;
- if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
- fixedWeapon = WEAPONTYPE_UZI;
- else
- fixedWeapon = (eWeaponType)WeaponType;
-
- CPlayerPed *player = FindPlayerPed();
- if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
- player->m_nSelectedWepSlot = InterruptedWeapon;
- player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon;
- }
-
- if (FindPlayerVehicle()) {
- player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);
- player->m_currentWeapon = player->m_nSelectedWepSlot;
- player->MakeChangesForNewWeapon(player->m_currentWeapon);
- }
+ DealWithWeaponChangeAtEndOfFrenzy();
}
void
CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot)
{
+ CGameLogic::ClearShortCut();
+ CGameLogic::RemoveShortCutDropOffPointForMission();
eWeaponType fixedWeapon;
if (weaponType == WEAPONTYPE_UZI_DRIVEBY)
fixedWeapon = WEAPONTYPE_UZI;
@@ -345,16 +320,24 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode
CPlayerPed *player = FindPlayerPed();
if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
- InterruptedWeapon = player->m_currentWeapon;
- player->GiveWeapon(fixedWeapon, 0);
+ InterruptedWeaponSelected = player->GetWeapon()->m_eWeaponType;
+#if (defined FIX_BUGS || !defined GTA_PS2)
+ player->RemoveWeaponAnims(InterruptedWeaponSelected, -1000.0f);
+#endif
+ InterruptedWeaponType = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_eWeaponType;
AmmoInterruptedWeapon = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal;
+ if (InterruptedWeaponType)
+ CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->AddRef();
+#if (!defined FIX_BUGS && defined GTA_PS2)
+ player->RemoveWeaponAnims(InterruptedWeaponSelected, -1000.0f);
+#endif
player->GiveWeapon(fixedWeapon, 30000);
- player->m_nSelectedWepSlot = player->GetWeaponSlot(fixedWeapon);
+ player->SetCurrentWeapon(fixedWeapon);
player->MakeChangesForNewWeapon(player->m_nSelectedWepSlot);
if (FindPlayerVehicle()) {
- player->m_currentWeapon = player->m_nSelectedWepSlot;
- player->GetWeapon()->m_nAmmoInClip = Min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition);
+ player->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);
+ player->SetAmmo(fixedWeapon, Min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition));
player->ClearWeaponTarget();
}
}
@@ -390,24 +373,7 @@ CDarkel::Update()
CPopulation::m_AllRandomPedsThisType = -1;
Status = KILLFRENZY_FAILED;
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
-
- eWeaponType fixedWeapon;
- if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
- fixedWeapon = WEAPONTYPE_UZI;
- else
- fixedWeapon = (eWeaponType)WeaponType;
-
- CPlayerPed *player = FindPlayerPed();
- if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
- player->m_nSelectedWepSlot = InterruptedWeapon;
- player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon;
- }
-
- if (FindPlayerVehicle()) {
- player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);
- player->m_currentWeapon = player->m_nSelectedWepSlot;
- player->MakeChangesForNewWeapon(player->m_currentWeapon);
- }
+ DealWithWeaponChangeAtEndOfFrenzy();
if (bStandardSoundAndMessages)
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_FAILED, 0);
@@ -424,25 +390,50 @@ CDarkel::Update()
FindPlayerPed()->m_pWanted->SetWantedLevel(0);
- eWeaponType fixedWeapon;
- if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
- fixedWeapon = WEAPONTYPE_UZI;
- else
- fixedWeapon = (eWeaponType)WeaponType;
-
- CPlayerPed* player = FindPlayerPed();
- if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
- player->m_nSelectedWepSlot = InterruptedWeapon;
- player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon;
- }
-
- if (FindPlayerVehicle()) {
- player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);
- player->m_currentWeapon = player->m_nSelectedWepSlot;
- player->MakeChangesForNewWeapon(player->m_currentWeapon);
- }
+ DealWithWeaponChangeAtEndOfFrenzy();
if (bStandardSoundAndMessages)
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_PASSED, 0);
}
}
+
+void
+CDarkel::DealWithWeaponChangeAtEndOfFrenzy()
+{
+ eWeaponType fixedWeapon;
+ if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
+ fixedWeapon = WEAPONTYPE_UZI;
+ else
+ fixedWeapon = (eWeaponType)WeaponType;
+
+ if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS && InterruptedWeaponType)
+ CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->RemoveRef();
+
+ if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
+ int slot = CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nWeaponSlot;
+ FindPlayerPed()->RemoveWeaponModel(FindPlayerPed()->GetWeapon(slot).GetInfo()->m_nModelId);
+ FindPlayerPed()->GetWeapon(slot).m_eWeaponType = WEAPONTYPE_UNARMED;
+ FindPlayerPed()->GetWeapon(slot).m_nAmmoTotal = 0;
+ FindPlayerPed()->GetWeapon(slot).m_nAmmoInClip = 0;
+ FindPlayerPed()->GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
+ FindPlayerPed()->RemoveWeaponAnims(fixedWeapon, -1000.0f);
+ CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nModelId)->RemoveRef();
+ }
+
+ CPlayerPed* player = FindPlayerPed();
+ if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
+ player->m_nSelectedWepSlot = CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponSelected)->m_nWeaponSlot;
+ player->GiveWeapon((eWeaponType)InterruptedWeaponType, AmmoInterruptedWeapon, true);
+ }
+
+ if (FindPlayerVehicle()) {
+ player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);
+ if (FindPlayerPed()->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType)
+ FindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_SUBMACHINEGUN;
+ else
+ FindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
+ player->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);
+ player->MakeChangesForNewWeapon(player->m_currentWeapon);
+ player->RemoveDrivebyAnims();
+ }
+}
diff --git a/src/control/Darkel.h b/src/control/Darkel.h
index 0f5c2329..91955479 100644
--- a/src/control/Darkel.h
+++ b/src/control/Darkel.h
@@ -23,7 +23,8 @@ private:
static int32 WeaponType;
static int32 AmmoInterruptedWeapon;
static int32 KillsNeeded;
- static int8 InterruptedWeapon;
+ static int32 InterruptedWeaponType;
+ static int32 InterruptedWeaponSelected;
static bool bStandardSoundAndMessages;
static bool bNeedHeadShot;
static bool bProperKillFrenzy;
@@ -49,5 +50,6 @@ public:
static void ResetOnPlayerDeath();
static void StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot);
static void Update();
+ static void DealWithWeaponChangeAtEndOfFrenzy();
};
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index 19e0f83d..63c685d1 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -19,14 +19,44 @@
#include "Fire.h"
#include "Script.h"
#include "Garages.h"
+#include "Population.h"
+#include "General.h"
+#include "DMAudio.h"
+#include "Radar.h"
+#include "Pools.h"
+#include "Hud.h"
+#include "Particle.h"
+#include "ColStore.h"
+#include "Automobile.h"
+#include "MBlur.h"
#include "screendroplets.h"
+#include "SaveBuf.h"
uint8 CGameLogic::ActivePlayers;
+uint8 CGameLogic::ShortCutState;
+CAutomobile* CGameLogic::pShortCutTaxi;
+uint32 CGameLogic::NumAfterDeathStartPoints;
+CVector CGameLogic::ShortCutStart;
+float CGameLogic::ShortCutStartOrientation;
+CVector CGameLogic::ShortCutDestination;
+float CGameLogic::ShortCutDestinationOrientation;
+uint32 CGameLogic::ShortCutTimer;
+CVector CGameLogic::AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];
+float CGameLogic::AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];
+CVector CGameLogic::ShortCutDropOffForMission;
+float CGameLogic::ShortCutDropOffOrientationForMission;
+bool CGameLogic::MissionDropOffReadyToBeUsed;
+
+#define SHORTCUT_TAXI_COST (9)
+#define TOTAL_BUSTED_AUDIO (28)
void
CGameLogic::InitAtStartOfGame()
{
ActivePlayers = 1;
+ ShortCutState = SHORTCUT_NONE;
+ pShortCutTaxi = nil;
+ NumAfterDeathStartPoints = 0;
}
void
@@ -59,7 +89,10 @@ CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
CStreaming::DeleteRwObjectsAfterDeath(pos);
CStreaming::RemoveUnusedModelsInLoadedList();
CGame::DrasticTidyUpMemory(true);
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress("player");
+ CStreaming::LoadSceneCollision(pos);
CStreaming::LoadScene(pos);
+ CWorld::Players[CWorld::PlayerInFocus].m_pPed->Dress();
CTimer::Update();
}
@@ -69,9 +102,20 @@ CGameLogic::Update()
CVector vecRestartPos;
float fRestartFloat;
+#ifdef MISSION_REPLAY
+ // what a place to check!
+ if (gbTryingPorn4Again) {
+ CRunningScript* pScript = CTheScripts::pActiveScripts;
+ if (pScript && !CGeneral::faststricmp(pScript->m_abScriptName, "porno4"))
+ gbTryingPorn4Again = false;
+ }
+#endif
+
if (CCutsceneMgr::IsCutsceneProcessing()) return;
+ UpdateShortCut();
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
+
switch (pPlayerInfo.m_WBState) {
case WBSTATE_PLAYING:
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
@@ -102,7 +146,7 @@ CGameLogic::Update()
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
pPlayerInfo.m_bGetOutOfHospitalFree = false;
} else {
- pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 1000);
+ pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 100);
pPlayerInfo.m_pPed->ClearWeapons();
}
@@ -123,23 +167,26 @@ CGameLogic::Update()
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ AfterDeathArrestSetUpShortCutTaxi();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextDeath) {
TheCamera.SetFadeColour(200, 200, 200);
TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextDeath = true;
+ } else
+ CRestart::bFadeInAfterNextDeath = true;
}
break;
case WBSTATE_BUSTED:
@@ -151,11 +198,35 @@ CGameLogic::Update()
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(2.0f, FADE_OUT);
}
+
+
+ if (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_NONE) {
+ if (CGeneral::GetRandomNumberInRange(0, 4) == 0)
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;
+ else {
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_LOADING;
+ char name[12];
+ sprintf(name, pPlayerInfo.m_nCurrentBustedAudio >= 10 ? "bust_%d" : "bust_0%d", pPlayerInfo.m_nCurrentBustedAudio);
+ DMAudio.ClearMissionAudio(0);
+ DMAudio.PreloadMissionAudio(0, name);
+ pPlayerInfo.m_nCurrentBustedAudio = pPlayerInfo.m_nCurrentBustedAudio % TOTAL_BUSTED_AUDIO + 1;
+ }
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 4000 &&
+ pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_LOADING &&
+ DMAudio.GetMissionAudioLoadingStatus(0) == 1) {
+ DMAudio.PlayLoadedMissionAudio(0);
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;
+ }
+
#ifdef MISSION_REPLAY
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) {
#else
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
#endif
+#ifdef FIX_BUGS
+ pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_NONE;
+#endif
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
int takeMoney;
@@ -205,24 +276,27 @@ CGameLogic::Update()
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
PassTime(720);
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ AfterDeathArrestSetUpShortCutTaxi();
pPlayerInfo.m_pPed->ClearWeapons();
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
TheCamera.m_fCamShakeForce = 0.0f;
TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
if (CRestart::bFadeInAfterNextArrest) {
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextArrest = true;
+ } else
+ CRestart::bFadeInAfterNextArrest = true;
}
break;
case WBSTATE_FAILED_CRITICAL_MISSION:
@@ -257,7 +331,7 @@ CGameLogic::Update()
#endif
CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
@@ -267,7 +341,8 @@ CGameLogic::Update()
TheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);
CPad::GetPad(0)->StopShaking(0);
CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
+ CPopulation::m_CountDownToPedsAtStart = 10;
+ CCarCtrl::CountDownToCarsAtStart = 10;
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
TheCamera.SetFadeColour(0, 0, 0);
TheCamera.Fade(4.0f, FADE_IN);
@@ -281,11 +356,17 @@ CGameLogic::Update()
void
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
{
- pPlayerPed->m_fHealth = 100.0f;
+ ClearShortCut();
+ CPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed();
+ pPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth;
pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false;
+ pPlayerPed->m_nDrunkenness = 0;
+ pPlayerPed->m_nFadeDrunkenness = 0;
+ CMBlur::ClearDrunkBlur();
+ pPlayerPed->m_nDrunkCountdown = 0;
pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
if (pPlayerPed->m_pFire)
@@ -294,27 +375,258 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector
pPlayerPed->m_pMyVehicle = nil;
pPlayerPed->m_pVehicleAnim = nil;
pPlayerPed->m_pWanted->Reset();
+ pPlayerPed->bCancelEnteringCar = false;
pPlayerPed->RestartNonPartialAnims();
- pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
+ pPlayerInfo->MakePlayerSafe(false);
pPlayerPed->bRemoveFromWorld = false;
pPlayerPed->ClearWeaponTarget();
pPlayerPed->SetInitialState();
CCarCtrl::ClearInterestingVehicleList();
-
- pos.z += 1.0f;
- pPlayerPed->Teleport(pos);
- pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
-
+ pPlayerPed->Teleport(pos + CVector(0.0f, 0.0f, 1.0f));
+ pPlayerPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
- CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
+ CWorld::ClearExcitingStuffFromArea(pos, 4000.0f, true);
pPlayerPed->RestoreHeadingRate();
+ CGame::currArea = AREA_MAIN_MAP;
+ CStreaming::RemoveBuildingsNotInArea(AREA_MAIN_MAP);
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
+ TheCamera.Restore();
CReferences::RemoveReferencesToPlayer();
CGarages::PlayerArrestedOrDied();
CStats::CheckPointReachedUnsuccessfully();
CWorld::Remove(pPlayerPed);
CWorld::Add(pPlayerPed);
+ CHud::ResetWastedText();
+ CStreaming::StreamZoneModels(pos);
+ clearWaterDrop = true;
+}
+
+void
+CGameLogic::ClearShortCut()
+{
+ if (pShortCutTaxi) {
+ if (pShortCutTaxi->VehicleCreatedBy == MISSION_VEHICLE) {
+ pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;
+ --CCarCtrl::NumMissionCars;
+ ++CCarCtrl::NumRandomCars;
+ }
+ CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));
+ pShortCutTaxi = nil;
+ }
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+}
+
+void
+CGameLogic::SetUpShortCut(CVector vStartPos, float fStartAngle, CVector vEndPos, float fEndAngle)
+{
+ ClearShortCut();
+ ShortCutState = SHORTCUT_INIT;
+ ShortCutStart = vStartPos;
+ ShortCutStartOrientation = fStartAngle;
+ ShortCutDestination = vEndPos;
+ ShortCutDestinationOrientation = fEndAngle;
+ CStreaming::RequestModel(MI_KAUFMAN, 0);
+}
+
+void
+CGameLogic::AbandonShortCutIfTaxiHasBeenMessedWith()
+{
+ if (!pShortCutTaxi)
+ return;
+ if (pShortCutTaxi->pDriver == nil ||
+ pShortCutTaxi->pDriver->DyingOrDead() ||
+ pShortCutTaxi->pDriver->GetPedState() == PED_DRAG_FROM_CAR ||
+ pShortCutTaxi->pDriver->GetPedState() == PED_ON_FIRE ||
+ pShortCutTaxi->pDriver->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
+ pShortCutTaxi->m_fHealth < 250.0f ||
+ pShortCutTaxi->bRenderScorched)
+ ClearShortCut();
+}
+
+void
+CGameLogic::AbandonShortCutIfPlayerMilesAway()
+{
+ if (!pShortCutTaxi)
+ return;
+ if ((FindPlayerCoors() - pShortCutTaxi->GetPosition()).Magnitude() > 120.0f)
+ ClearShortCut();
+}
+
+void
+CGameLogic::UpdateShortCut()
+{
+ switch (ShortCutState) {
+ case SHORTCUT_INIT:
+ if (!CStreaming::HasModelLoaded(MI_KAUFMAN)) {
+ CStreaming::RequestModel(MI_KAUFMAN, 0);
+ return;
+ }
+ pShortCutTaxi = new CAutomobile(MI_KAUFMAN, RANDOM_VEHICLE);
+ if (!pShortCutTaxi)
+ return;
+ pShortCutTaxi->SetPosition(ShortCutStart);
+ pShortCutTaxi->SetHeading(DEGTORAD(ShortCutStartOrientation));
+ pShortCutTaxi->PlaceOnRoadProperly();
+ pShortCutTaxi->SetStatus(STATUS_PHYSICS);
+ pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 0;
+ pShortCutTaxi->SetUpDriver();
+ pShortCutTaxi->VehicleCreatedBy = MISSION_VEHICLE;
+ ++CCarCtrl::NumMissionCars;
+ --CCarCtrl::NumRandomCars;
+ CTheScripts::ClearSpaceForMissionEntity(ShortCutStart, pShortCutTaxi);
+ CWorld::Add(pShortCutTaxi);
+ CRadar::SetEntityBlip(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi), 0, BLIP_DISPLAY_MARKER_ONLY);
+ ShortCutState = SHORTCUT_IDLE;
+ break;
+ case SHORTCUT_IDLE:
+ if (FindPlayerPed()->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && FindPlayerPed()->m_carInObjective == pShortCutTaxi) {
+ CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+ FindPlayerPed()->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pShortCutTaxi);
+ ShortCutState = SHORTCUT_GETTING_IN;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ AbandonShortCutIfPlayerMilesAway();
+ break;
+ case SHORTCUT_GETTING_IN:
+ if (pShortCutTaxi->pPassengers[0] == FindPlayerPed() ||
+ pShortCutTaxi->pPassengers[1] == FindPlayerPed() ||
+ pShortCutTaxi->pPassengers[2] == FindPlayerPed()) {
+ pShortCutTaxi->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pShortCutTaxi->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2500;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.5f, FADE_OUT);
+ ShortCutState = SHORTCUT_TRANSITION;
+ ShortCutTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ CMessages::AddBigMessage(TheText.Get("TAXI"), 4500, 1);
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ case SHORTCUT_TRANSITION:
+ if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {
+ CTimer::Suspend();
+ CColStore::RequestCollision(ShortCutDestination);
+ CStreaming::LoadSceneCollision(ShortCutDestination);
+ CStreaming::LoadScene(ShortCutDestination);
+ CTheScripts::ClearSpaceForMissionEntity(ShortCutDestination, pShortCutTaxi);
+ pShortCutTaxi->Teleport(ShortCutDestination);
+ pShortCutTaxi->SetHeading(DEGTORAD(ShortCutDestinationOrientation));
+ pShortCutTaxi->PlaceOnRoadProperly();
+ pShortCutTaxi->SetMoveSpeed(pShortCutTaxi->GetForward() * 0.4f);
+ ShortCutTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(1.0f, FADE_IN);
+ ShortCutState = SHORTCUT_ARRIVING;
+ CTimer::Resume();
+ }
+ break;
+ case SHORTCUT_ARRIVING:
+ if (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - SHORTCUT_TAXI_COST);
+ FindPlayerPed()->SetObjective(OBJECTIVE_LEAVE_CAR, pShortCutTaxi);
+ FindPlayerPed()->m_carInObjective = pShortCutTaxi;
+ ShortCutState = SHORTCUT_GETTING_OUT;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ case SHORTCUT_GETTING_OUT:
+ if (pShortCutTaxi->pPassengers[0] != FindPlayerPed() &&
+ pShortCutTaxi->pPassengers[1] != FindPlayerPed() &&
+ pShortCutTaxi->pPassengers[2] != FindPlayerPed()) {
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);
+ pShortCutTaxi->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pShortCutTaxi->AutoPilot.m_nCruiseSpeed = 18;
+ CCarCtrl::JoinCarWithRoadSystem(pShortCutTaxi);
+ pShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;
+ ++CCarCtrl::NumRandomCars;
+ --CCarCtrl::NumMissionCars;
+ CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));
+ ShortCutState = SHORTCUT_NONE;
+ pShortCutTaxi = nil;
+ }
+ AbandonShortCutIfTaxiHasBeenMessedWith();
+ break;
+ }
+}
+
+void
+CGameLogic::AddShortCutPointAfterDeath(CVector point, float angle)
+{
+ if (NumAfterDeathStartPoints >= NUM_SHORTCUT_START_POINTS)
+ return;
+ AfterDeathStartPoints[NumAfterDeathStartPoints] = point;
+ AfterDeathStartPointOrientation[NumAfterDeathStartPoints] = angle;
+ NumAfterDeathStartPoints++;
+}
+
+void
+CGameLogic::AddShortCutDropOffPointForMission(CVector point, float angle)
+{
+ ShortCutDropOffForMission = point;
+ ShortCutDropOffOrientationForMission = angle;
+ MissionDropOffReadyToBeUsed = true;
+}
+
+void
+CGameLogic::RemoveShortCutDropOffPointForMission()
+{
+ MissionDropOffReadyToBeUsed = false;
+}
+
+void
+CGameLogic::AfterDeathArrestSetUpShortCutTaxi()
+{
+ if (!MissionDropOffReadyToBeUsed)
+ return;
+ int nClosestPoint = -1;
+ float fDistanceToPoint = 999999.9f;
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ float dist = (AfterDeathStartPoints[i] - FindPlayerCoors()).Magnitude();
+ if (dist < fDistanceToPoint) {
+ fDistanceToPoint = dist;
+ nClosestPoint = i;
+ }
+ }
+ if (fDistanceToPoint < 100.0f)
+ SetUpShortCut(AfterDeathStartPoints[nClosestPoint],
+ AfterDeathStartPointOrientation[nClosestPoint],
+ ShortCutDropOffForMission,
+ ShortCutDropOffOrientationForMission);
+ MissionDropOffReadyToBeUsed = false;
+}
+
+void
+CGameLogic::Save(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ WriteSaveBuf(buf, NumAfterDeathStartPoints);
+ *size += sizeof(NumAfterDeathStartPoints);
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].x);
+ *size += sizeof(AfterDeathStartPoints[i].x);
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].y);
+ *size += sizeof(AfterDeathStartPoints[i].y);
+ WriteSaveBuf(buf, AfterDeathStartPoints[i].z);
+ *size += sizeof(AfterDeathStartPoints[i].z);
+ WriteSaveBuf(buf, AfterDeathStartPointOrientation[i]);
+ *size += sizeof(AfterDeathStartPointOrientation[i]);
+ }
+VALIDATESAVEBUF(*size)
+}
+
+void
+CGameLogic::Load(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ ReadSaveBuf(&NumAfterDeathStartPoints, buf);
+ for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
+ ReadSaveBuf(&AfterDeathStartPoints[i].x, buf);
+ ReadSaveBuf(&AfterDeathStartPoints[i].y, buf);
+ ReadSaveBuf(&AfterDeathStartPoints[i].z, buf);
+ ReadSaveBuf(&AfterDeathStartPointOrientation[i], buf);
+ }
+VALIDATESAVEBUF(size)
}
diff --git a/src/control/GameLogic.h b/src/control/GameLogic.h
index 43e244a3..9b774cc7 100644
--- a/src/control/GameLogic.h
+++ b/src/control/GameLogic.h
@@ -1,13 +1,51 @@
#pragma once
+class CAutomobile;
+
class CGameLogic
{
public:
+ enum {
+ SHORTCUT_NONE = 0,
+ SHORTCUT_INIT,
+ SHORTCUT_IDLE,
+ SHORTCUT_GETTING_IN,
+ SHORTCUT_TRANSITION,
+ SHORTCUT_ARRIVING,
+ SHORTCUT_GETTING_OUT
+ };
+
static void InitAtStartOfGame();
static void PassTime(uint32 time);
static void SortOutStreamingAndMemory(const CVector &pos);
static void Update();
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
+ static void ClearShortCut();
+ static void SetUpShortCut(CVector, float, CVector, float);
+ static void AbandonShortCutIfTaxiHasBeenMessedWith();
+ static void AbandonShortCutIfPlayerMilesAway();
+ static void UpdateShortCut();
+ static void AddShortCutPointAfterDeath(CVector, float);
+ static void AddShortCutDropOffPointForMission(CVector, float);
+ static void RemoveShortCutDropOffPointForMission();
+ static void AfterDeathArrestSetUpShortCutTaxi();
+
+ static void Save(uint8*, uint32*);
+ static void Load(uint8*, uint32);
+
static uint8 ActivePlayers;
+ static uint8 ShortCutState;
+ static CAutomobile* pShortCutTaxi;
+ static uint32 NumAfterDeathStartPoints;
+ static CVector ShortCutStart;
+ static float ShortCutStartOrientation;
+ static CVector ShortCutDestination;
+ static float ShortCutDestinationOrientation;
+ static uint32 ShortCutTimer;
+ static CVector AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];
+ static float AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];
+ static CVector ShortCutDropOffForMission;
+ static float ShortCutDropOffOrientationForMission;
+ static bool MissionDropOffReadyToBeUsed;
}; \ No newline at end of file
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index bb919eae..b24c9122 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -3,9 +3,8 @@
#include "Garages.h"
#include "main.h"
-#ifdef FIX_BUGS
+#include "Bike.h"
#include "Boat.h"
-#endif
#include "DMAudio.h"
#include "General.h"
#include "Font.h"
@@ -24,6 +23,7 @@
#include "Vehicle.h"
#include "Wanted.h"
#include "World.h"
+#include "VarConsole.h"
#include "SaveBuf.h"
#define ROTATED_DOOR_OPEN_SPEED (0.015f)
@@ -33,21 +33,21 @@
#define CRUSHER_CRANE_SPEED (0.005f)
// Prices
-#define BOMB_PRICE (1000)
-#define RESPRAY_PRICE (1000)
+#define BOMB_PRICE (500)
+#define RESPRAY_PRICE (100)
// Distances
#define DISTANCE_TO_CALL_OFF_CHASE (10.0f)
-#define DISTANCE_FOR_MRWHOOP_HACK (4.0f)
+#define DISTANCE_FOR_MRWHOOP_HACK (0.5f)
#define DISTANCE_TO_ACTIVATE_GARAGE (8.0f)
#define DISTANCE_TO_ACTIVATE_KEEPCAR_GARAGE (17.0f)
#define DISTANCE_TO_CLOSE_MISSION_GARAGE (30.0f)
#define DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE (25.0f)
#define DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE (40.0f)
-#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (2.2f)
+#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (3.2f)
#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR (15.0f)
#define DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE (70.0f)
-#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (1.7f)
+#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (2.8f)
#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR (10.0f)
#define DISTANCE_TO_SHOW_HIDEOUT_MESSAGE (5.0f)
@@ -62,7 +62,7 @@
// Respray stuff
#define FREE_RESPRAY_HEALTH_THRESHOLD (970.0f)
#define NUM_PARTICLES_IN_RESPRAY (200)
-#define RESPRAY_CENTERING_COEFFICIENT (0.75f)
+#define RESPRAY_CENTERING_COEFFICIENT (0.4f)
// Bomb stuff
#define KGS_OF_EXPLOSIVES_IN_BOMB (10)
@@ -75,8 +75,8 @@
// Collect cars stuff
#define MAX_SPEED_TO_SHOW_COLLECTED_MESSAGE (0.03f)
-#define IMPORT_REWARD (1000)
-#define IMPORT_ALLCARS_REWARD (200000)
+#define IMPORT_REWARD (500)
+#define IMPORT_ALLCARS_REWARD (20500)
// Crusher stuff
#define CRUSHER_VEHICLE_TEST_SPAN (8)
@@ -85,24 +85,19 @@
#define CRUSHER_REWARD_COEFFICIENT (1.0f/500000)
// Hideout stuff
-#define MAX_STORED_CARS_IN_INDUSTRIAL (1)
-#define MAX_STORED_CARS_IN_COMMERCIAL (NUM_GARAGE_STORED_CARS)
-#define MAX_STORED_CARS_IN_SUBURBAN (NUM_GARAGE_STORED_CARS)
-#define LIMIT_CARS_IN_INDUSTRIAL (1)
-#define LIMIT_CARS_IN_COMMERCIAL (2)
-#define LIMIT_CARS_IN_SUBURBAN (3)
#define HIDEOUT_DOOR_SPEED_COEFFICIENT (1.7f)
#define TIME_BETWEEN_HIDEOUT_MESSAGES (18000)
// Camera stuff
-#define MARGIN_FOR_CAMERA_COLLECTCARS (1.3f)
-#define MARGIN_FOR_CAMERA_DEFAULT (4.0f)
+#define MARGIN_FOR_CAMERA_COLLECTCARS (0.5f)
+#define MARGIN_FOR_CAMERA_DEFAULT (0.5f)
const int32 gaCarsToCollectInCraigsGarages[TOTAL_COLLECTCARS_GARAGES][TOTAL_COLLECTCARS_CARS] =
{
- { MI_SECURICA, MI_MOONBEAM, MI_COACH, MI_FLATBED, MI_LINERUN, MI_TRASH, MI_PATRIOT, MI_MRWHOOP, MI_BLISTA, MI_MULE, MI_YANKEE, MI_BOBCAT, MI_DODO, MI_BUS, MI_RUMPO, MI_PONY },
- { MI_SENTINEL, MI_CHEETAH, MI_BANSHEE, MI_IDAHO, MI_INFERNUS, MI_TAXI, MI_KURUMA, MI_STRETCH, MI_PEREN, MI_STINGER, MI_MANANA, MI_LANDSTAL, MI_STALLION, MI_BFINJECT, MI_CABBIE, MI_ESPERANT },
- { MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO }
+ { MI_LANDSTAL, MI_IDAHO, MI_ESPERANT, MI_STALLION, MI_RANCHER, MI_BLISTAC },
+ { MI_SABRE, MI_VIRGO, MI_SENTINEL, MI_STRETCH, MI_WASHING, MI_ADMIRAL },
+ { MI_CHEETAH, MI_INFERNUS, MI_BANSHEE, MI_PHEONIX, MI_COMET, MI_STINGER },
+ { MI_VOODOO, MI_CUBAN, MI_CADDY, MI_BAGGAGE, MI_MRWHOOP, MI_PIZZABOY }
};
const int32 gaCarsToCollectIn60Seconds[] = { MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO };
@@ -122,15 +117,20 @@ uint32 CGarages::MessageEndTime;
uint32 CGarages::NumGarages;
bool CGarages::PlayerInGarage;
int32 CGarages::PoliceCarsCollected;
-CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+CStoredCar CGarages::aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];
int32 hGarages = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
+#ifndef MASTER
+bool bPrintNearestObject;
+#endif
+
void CGarages::Init(void)
{
+#ifndef MASTER
+ VarConsole.Add("Print nearest object", &bPrintNearestObject, true);
+#endif
CrushedCarId = -1;
NumGarages = 0;
MessageEndTime = 0;
@@ -146,22 +146,15 @@ void CGarages::Init(void)
for (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)
CarTypesCollected[i] = 0;
LastTimeHelpMessage = 0;
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse1[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse2[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse3[i].Init();
+ for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++)
+ aCarsInSafeHouses[j][i].Init();
+ }
hGarages = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
if (hGarages >= 0)
DMAudio.SetEntityStatus(hGarages, TRUE);
- AddOne(
- CVector(CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1),
- CVector(CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2),
- GARAGE_CRUSHER, 0);
}
-#ifndef PS2
void CGarages::Shutdown(void)
{
NumGarages = 0;
@@ -170,23 +163,34 @@ void CGarages::Shutdown(void)
DMAudio.DestroyEntity(hGarages);
hGarages = AEHANDLE_NONE;
}
-#endif
void CGarages::Update(void)
{
- static int GarageToBeTidied = 0;
+ static uint32 GarageToBeTidied = 0;
if (CReplay::IsPlayingBack())
return;
+#ifdef SECUROM
+ extern uint8 gameProcessPirateCheck;
+ if (gameProcessPirateCheck == 2) return;
+#endif
bCamShouldBeOutisde = false;
TheCamera.pToGarageWeAreIn = nil;
TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = nil;
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
if (aGarages[i].IsUsed())
aGarages[i].Update();
}
if ((CTimer::GetFrameCounter() & 0xF) != 0xC)
return;
+#ifdef FIX_BUGS
+ if (++GarageToBeTidied >= NumGarages)
+#else
if (++GarageToBeTidied >= NUM_GARAGES)
+#endif
GarageToBeTidied = 0;
if (!aGarages[GarageToBeTidied].IsUsed())
return;
@@ -196,23 +200,31 @@ void CGarages::Update(void)
aGarages[GarageToBeTidied].TidyUpGarage();
}
-int16 CGarages::AddOne(CVector p1, CVector p2, uint8 type, int32 targetId)
+int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, uint8 type, int32 targetId)
{
if (NumGarages >= NUM_GARAGES) {
assert(0);
return NumGarages++;
}
CGarage* pGarage = &aGarages[NumGarages];
- pGarage->m_fX1 = Min(p1.x, p2.x);
- pGarage->m_fX2 = Max(p1.x, p2.x);
- pGarage->m_fY1 = Min(p1.y, p2.y);
- pGarage->m_fY2 = Max(p1.y, p2.y);
- pGarage->m_fZ1 = Min(p1.z, p2.z);
- pGarage->m_fZ2 = Max(p1.z, p2.z);
+ pGarage->m_fInfX = Min(Min(Min(X1, X2), X3), X2 + X3 - X1);
+ pGarage->m_fSupX = Max(Max(X1, X2), X3);
+ pGarage->m_fInfY = Min(Min(Min(Y1, Y2), Y3), Y2 + Y3 - Y1);
+ pGarage->m_fSupY = Max(Max(Y1, Y2), Y3);
+ pGarage->m_vecCorner1 = CVector(X1, Y1, Z1);
+ pGarage->m_fInfZ = Z1;
+ pGarage->m_vDir1 = CVector2D(X2 - X1, Y2 - Y1);
+ pGarage->m_vDir2 = CVector2D(X3 - X1, Y3 - Y1);
+ pGarage->m_fSupZ = Z2;
+ pGarage->m_nMaxStoredCars = NUM_GARAGE_STORED_CARS;
+ pGarage->m_fDir1Len = pGarage->m_vDir1.Magnitude();
+ pGarage->m_fDir2Len = pGarage->m_vDir2.Magnitude();
+ pGarage->m_vDir1 /= pGarage->m_fDir1Len;
+ pGarage->m_vDir2 /= pGarage->m_fDir2Len;
pGarage->m_pDoor1 = nil;
pGarage->m_pDoor2 = nil;
- pGarage->m_fDoor1Z = p1.z;
- pGarage->m_fDoor2Z = p1.z;
+ pGarage->m_fDoor1Z = Z1;
+ pGarage->m_fDoor2Z = Z1;
pGarage->m_eGarageType = type;
pGarage->m_bRecreateDoorOnNextRefresh = false;
pGarage->m_bRotatedDoor = false;
@@ -234,7 +246,6 @@ int16 CGarages::AddOne(CVector p1, CVector p2, uint8 type, int32 targetId)
pGarage->m_nTimeToStartAction = 0;
pGarage->field_2 = false;
pGarage->m_nTargetModelIndex = targetId;
- pGarage->field_96 = nil;
pGarage->m_bCollectedCarsState = 0;
pGarage->m_bDeactivated = false;
pGarage->m_bResprayHappened = false;
@@ -255,6 +266,17 @@ int16 CGarages::AddOne(CVector p1, CVector p2, uint8 type, int32 targetId)
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
pGarage->m_eGarageState = GS_FULLYCLOSED;
pGarage->m_fDoorPos = 0.0f;
break;
@@ -308,10 +330,10 @@ void CGarage::Update()
TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this;
if (pVehicle->GetModelIndex() == MI_MRWHOOP) {
if (pVehicle->IsWithinArea(
- m_fX1 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY1 + DISTANCE_FOR_MRWHOOP_HACK,
- m_fX2 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY2 + DISTANCE_FOR_MRWHOOP_HACK)) {
+ m_fInfX - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fInfY - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupX + DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupY + DISTANCE_FOR_MRWHOOP_HACK)) {
TheCamera.pToGarageWeAreIn = this;
CGarages::bCamShouldBeOutisde = true;
}
@@ -325,11 +347,48 @@ void CGarage::Update()
}
if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)
return;
+ if (m_bRotatedDoor) {
+#ifdef GTA_PS2
+ if (m_eGarageState == GS_OPENING) {
+ if (m_pDoor1) {
+ if (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor1)
+ m_pDoor1->bUsesCollision = false;
+ }
+ if (m_pDoor2) {
+ if (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor2)
+ m_pDoor2->bUsesCollision = false;
+ }
+ }
+ else if (m_eGarageState == GS_OPENED) {
+ if (m_pDoor1)
+ m_pDoor1->bUsesCollision = true;
+ if (m_pDoor2)
+ m_pDoor2->bUsesCollision = true;
+ }
+#else
+ if (m_eGarageState == GS_OPENING || m_eGarageState == GS_OPENED) {
+ if (m_pDoor1) {
+ if (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor1 || FindPlayerPed()->GetPedState() == PED_JUMP || FindPlayerPed()->GetPedState() == PED_FALL || !FindPlayerPed()->bIsStanding)
+ m_pDoor1->bUsesCollision = false;
+ }
+ if (m_pDoor2) {
+ if (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor2 || FindPlayerPed()->GetPedState() == PED_JUMP || FindPlayerPed()->GetPedState() == PED_FALL || !FindPlayerPed()->bIsStanding)
+ m_pDoor2->bUsesCollision = false;
+ }
+ }
+ else {
+ if (m_pDoor1)
+ m_pDoor1->bUsesCollision = true;
+ if (m_pDoor2)
+ m_pDoor2->bUsesCollision = true;
+ }
+#endif
+ }
switch (m_eGarageType) {
case GARAGE_RESPRAY:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
+ if (IsStaticPlayerCarEntirelyInside()) {
if (CGarages::IsCarSprayable(FindPlayerVehicle())) {
if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= RESPRAY_PRICE || CGarages::RespraysAreFree) {
m_eGarageState = GS_CLOSING;
@@ -337,7 +396,7 @@ void CGarage::Update()
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
}
else {
- CGarages::TriggerMessage("GA_3", -1, 4000, -1); // No more freebies. $1000 to respray!
+ CGarages::TriggerMessage("GA_3", -1, 4000, -1); // No more freebies. $100 to respray!
m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);
}
@@ -351,13 +410,15 @@ void CGarage::Update()
if (FindPlayerVehicle()) {
if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -373,19 +434,20 @@ void CGarage::Update()
#endif
((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
m_eGarageState = GS_OPENING;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_OPENING, 1);
bool bTakeMoney = false;
- if (FindPlayerPed()->m_pWanted->GetWantedLevel() != 0)
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() != 0) {
bTakeMoney = true;
- FindPlayerPed()->m_pWanted->Reset();
+ FindPlayerPed()->m_pWanted->Suspend();
+ }
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
#ifdef FIX_BUGS
@@ -393,18 +455,30 @@ void CGarage::Update()
#else
bool bChangedColour;
#endif
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
if (FindPlayerVehicle()->m_fHealth < FREE_RESPRAY_HEALTH_THRESHOLD)
bTakeMoney = true;
FindPlayerVehicle()->m_fHealth = 1000.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ if (FindPlayerVehicle()->IsCar()) {
+ ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
+ ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ }
+ else {
+ ((CBike*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
+ ((CBike*)(FindPlayerVehicle()))->Fix();
+ }
+ FindPlayerVehicle()->m_nDoorLock = CARLOCK_UNLOCKED;
+ ++CStats::Sprayings;
if (FindPlayerVehicle()->GetUp().z < 0.0f) {
FindPlayerVehicle()->GetUp() = -FindPlayerVehicle()->GetUp();
FindPlayerVehicle()->GetRight() = -FindPlayerVehicle()->GetRight();
}
bChangedColour = false;
+#ifdef FIX_BUGS
+ if (!FindPlayerVehicle()->IsCar() || !((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#else
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#endif
uint8 colour1, colour2;
uint16 attempt;
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
@@ -419,16 +493,9 @@ void CGarage::Update()
if (bChangedColour) {
for (int i = 0; i < NUM_PARTICLES_IN_RESPRAY; i++) {
CVector pos;
-#ifdef FIX_BUGS
- pos.x = CGeneral::GetRandomNumberInRange(m_fX1 + 0.5f, m_fX2 - 0.5f);
- pos.y = CGeneral::GetRandomNumberInRange(m_fY1 + 0.5f, m_fY2 - 0.5f);
+ pos.x = CGeneral::GetRandomNumberInRange(m_fInfX + 0.5f, m_fSupX - 0.5f);
+ pos.y = CGeneral::GetRandomNumberInRange(m_fInfY + 0.5f, m_fSupY - 0.5f);
pos.z = CGeneral::GetRandomNumberInRange(m_fDoor1Z - 3.0f, m_fDoor1Z + 1.0f);
-#else
- // wtf is this
- pos.x = m_fX1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fX2 - m_fX1 - 1.0f);
- pos.y = m_fY1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fY2 - m_fY1 - 1.0f);
- pos.z = m_fDoor1Z - 3.0f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * 4.0f;
-#endif
CParticle::AddParticle(PARTICLE_GARAGEPAINT_SPRAY, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, CVehicleModelInfo::ms_vehicleColourTable[colour1]);
}
}
@@ -436,8 +503,10 @@ void CGarage::Update()
CenterCarInGarage(FindPlayerVehicle());
}
if (bTakeMoney) {
- if (!CGarages::RespraysAreFree)
+ if (!CGarages::RespraysAreFree) {
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE);
+ CStats::AutoPaintingBudget += RESPRAY_PRICE;
+ }
CGarages::TriggerMessage("GA_2", -1, 4000, -1); // New engine and paint job. The cops won't recognize you!
}
else if (bChangedColour) {
@@ -449,10 +518,10 @@ void CGarage::Update()
m_bResprayHappened = true;
}
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_OPENING:
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
@@ -477,12 +546,8 @@ void CGarage::Update()
case GARAGE_BOMBSHOP3:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
-#ifdef FIX_BUGS // FindPlayerVehicle() can never be NULL here because IsStaticPlayerCarEntirelyInside() is true, and there is no IsCar() check
- if (FindPlayerVehicle()->IsCar() && ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#else
- if (!FindPlayerVehicle() || ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#endif
+ if (IsStaticPlayerCarEntirelyInside()) {
+ if (!FindPlayerVehicle() || FindPlayerVehicle()->m_bombType) {
CGarages::TriggerMessage("GA_5", -1, 4000, -1); //"Your car is already fitted with a bomb"
m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB_ALREADY_SET, 1);
@@ -500,6 +565,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -507,62 +574,72 @@ void CGarage::Update()
DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
- case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
- case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
- default: break;
- }
- m_eGarageState = GS_OPENING;
- if (!CGarages::BombsAreFree)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
- ((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
- ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
- if (m_eGarageType == GARAGE_BOMBSHOP3)
- CGarages::GivePlayerDetonator();
- CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
- }
+ if (m_eGarageType != GARAGE_BOMBSHOP3 || CStreaming::HasModelLoaded(MI_BOMB)) {
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
+ case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
+ case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
+ }
+ m_eGarageState = GS_OPENING;
+ if (!CGarages::BombsAreFree)
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
+#if (!defined GTA_PS2 || defined FIX_BUGS)
+ FindPlayerVehicle()->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
+ FindPlayerVehicle()->m_pBombRigger = FindPlayerPed();
+#else // PS2 version contained a bug: CBike was casted to CAutomobile, but due to coincidence it didn't corrupt memory
+ ((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
+ ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
+#endif
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CGarages::GivePlayerDetonator();
+ CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
+ }
#ifdef DETECT_PAD_INPUT_SWITCH
- int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
+ int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
#else
- int16 Mode = CPad::GetPad(0)->Mode;
+ int16 Mode = CPad::GetPad(0)->Mode;
#endif
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
- break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ }
break;
- }
- break;
- case GARAGE_BOMBSHOP2:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP2:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ }
break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP3:
+ CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
break;
}
- break;
- case GARAGE_BOMBSHOP3:
- CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
- break;
- default: break;
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
+ }
+ else {
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
}
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
}
break;
case GS_OPENING:
@@ -587,14 +664,17 @@ void CGarage::Update()
switch (m_eGarageState) {
case GS_OPENED:
if (((CVector2D)FindPlayerCoors() - CVector2D(GetGarageCenterX(), GetGarageCenterY())).MagnitudeSqr() > SQR(DISTANCE_TO_CLOSE_MISSION_GARAGE)) {
- if ((CTimer::GetFrameCounter() & 0x1F) == 0 && !IsAnyOtherCarTouchingGarage(nil)) {
+ if ((CTimer::GetFrameCounter() & 0x1F) == 0
+#ifndef GTA_PS2
+ && (!m_pTarget || IsEntityTouching3D(m_pTarget))
+#endif
+ ) {
m_eGarageState = GS_CLOSING;
m_bClosingWithoutTargetCar = true;
}
}
else if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) &&
- !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f) &&
- !IsAnyOtherCarTouchingGarage(m_pTarget)) {
+ IsEntityEntirelyOutside(FindPlayerVehicle() ? (CEntity*)FindPlayerVehicle() : (CEntity*)FindPlayerPed(), 2.0f)) {
CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
m_eGarageState = GS_CLOSING;
@@ -602,6 +682,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -646,92 +728,10 @@ void CGarage::Update()
}
break;
case GARAGE_COLLECTSPECIFICCARS:
- switch (m_eGarageState) {
- case GS_OPENED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- if (!FindPlayerVehicle()) {
- if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyOtherCarTouchingGarage(m_pTarget)) {
- if (IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) {
- CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
- m_eGarageState = GS_CLOSING;
- }
- }
- else if (Abs(FindPlayerCoors().x - GetGarageCenterX()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE ||
- Abs(FindPlayerCoors().y - GetGarageCenterY()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = nil;
- }
- }
- break;
- case GS_CLOSING:
- m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == 0.0f) {
- m_eGarageState = GS_FULLYCLOSED;
- DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- if (m_pTarget) {
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- m_pTarget = nil;
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
- int16 reward;
- switch (m_nTargetModelIndex) {
- case MI_POLICE:
- reward = REWARD_FOR_FIRST_POLICE_CAR * (MAX_POLICE_CARS_TO_COLLECT - CGarages::PoliceCarsCollected++) / MAX_POLICE_CARS_TO_COLLECT;
- break;
- case MI_SECURICA:
- reward = REWARD_FOR_FIRST_BANK_VAN * (MAX_BANK_VANS_TO_COLLECT - CGarages::BankVansCollected++) / MAX_BANK_VANS_TO_COLLECT;
- break;
-#ifdef FIX_BUGS // not possible though
- default:
- reward = 0;
- break;
-#endif
- }
- if (reward > 0) {
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- CGarages::TriggerMessage("GA_10", reward, 4000, -1); // Nice one. Here's your $~1~
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_ACCEPTED, 1);
- }
- else {
- CGarages::TriggerMessage("GA_11", -1, 4000, -1); // We got these wheels already. It's worthless to us!
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_DECLINED, 1);
- }
- }
- }
- UpdateDoorsHeight();
- break;
- case GS_FULLYCLOSED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == m_fDoorHeight) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateDoorsHeight();
- break;
- //case GS_OPENEDCONTAINSCAR:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_AFTERDROPOFF:
- default:
- break;
- }
- break;
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
+ case GARAGE_COLLECTCARS_4:
switch (m_eGarageState) {
case GS_OPENED:
if (FindPlayerVehicle() && DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {
@@ -764,6 +764,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -851,75 +853,6 @@ void CGarage::Update()
}
break;
case GARAGE_CRUSHER:
- switch (m_eGarageState) {
- case GS_OPENED:
- {
- int i = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN) / CRUSHER_VEHICLE_TEST_SPAN;
- int end = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN + 1) / CRUSHER_VEHICLE_TEST_SPAN;
- for (; i < end; i++) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- if (pVehicle->IsCar() && IsEntityEntirelyInside3D(pVehicle, 0.0f)) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = pVehicle;
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- }
- break;
- }
- case GS_CLOSING:
- if (m_pTarget) {
- m_fDoorPos = Max(0.0f, m_fDoorPos - CRUSHER_CRANE_SPEED * CTimer::GetTimeStep());
- if (m_fDoorPos < TWOPI / 5) {
- m_pTarget->bUsesCollision = false;
- m_pTarget->bAffectedByGravity = false;
- m_pTarget->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- }
- else {
- m_pTarget->SetMoveSpeed(m_pTarget->GetMoveSpeed() * Pow(0.8f, CTimer::GetTimeStep()));
- }
- if (m_fDoorPos == 0.0f) {
- CGarages::CrushedCarId = CPools::GetVehiclePool()->GetIndex(m_pTarget);
- float reward = Min(CRUSHER_MAX_REWARD, CRUSHER_MIN_REWARD + m_pTarget->pHandling->nMonetaryValue * m_pTarget->m_fHealth * CRUSHER_REWARD_COEFFICIENT);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- ++CStats::CarsCrushed;
- m_pTarget = nil;
- m_eGarageState = GS_AFTERDROPOFF;
- m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR;
- DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- }
- }
- else
- m_eGarageState = GS_OPENING;
- UpdateCrusherAngle();
- break;
- case GS_AFTERDROPOFF:
- if (CTimer::GetTimeInMilliseconds() <= m_nTimeToStartAction) {
- UpdateCrusherShake((myrand() & 0xFF - 128) * 0.0002f, (myrand() & 0xFF - 128) * 0.0002f);
- }
- else {
- UpdateCrusherShake(0.0f, 0.0f);
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED);
- if (m_fDoorPos == HALFPI) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateCrusherAngle();
- break;
- //case GS_FULLYCLOSED:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_OPENEDCONTAINSCAR:
- default:
- break;
- }
- if (!FindPlayerVehicle() && (CTimer::GetFrameCounter() & 0x1F) == 0x17 && IsEntityEntirelyInside(FindPlayerPed()))
- FindPlayerPed()->InflictDamage(nil, WEAPONTYPE_RAMMEDBYCAR, 300.0f, PEDPIECE_TORSO, 0);
break;
case GARAGE_MISSION_KEEPCAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
@@ -938,6 +871,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -1033,6 +968,15 @@ void CGarage::Update()
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
{
@@ -1045,7 +989,7 @@ void CGarage::Update()
m_eGarageState = GS_CLOSING;
else if (FindPlayerVehicle() &&
CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=
- CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ FindMaxNumStoredCarsForGarage()) {
m_eGarageState = GS_CLOSING;
}
else if (distance > SQR(DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE)) {
@@ -1061,12 +1005,7 @@ void CGarage::Update()
else if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
m_eGarageState = GS_FULLYCLOSED;
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break;
- case GARAGE_HIDEOUT_TWO: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse2, MAX_STORED_CARS_IN_COMMERCIAL); break;
- case GARAGE_HIDEOUT_THREE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse3, MAX_STORED_CARS_IN_SUBURBAN); break;
- default: break;
- }
+ StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)], NUM_GARAGE_STORED_CARS);
}
UpdateDoorsHeight();
break;
@@ -1075,30 +1014,19 @@ void CGarage::Update()
float distance = CalcDistToGarageRectangleSquared(FindPlayerCoors().x, FindPlayerCoors().y);
if (distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT) ||
distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR) && FindPlayerVehicle()) {
- if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= FindMaxNumStoredCarsForGarage()) {
if (m_pDoor1) {
if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) &&
CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) {
- CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
- CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE) {
+ CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
+ CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ }
}
}
}
- else {
-#ifdef FIX_BUGS
- bool bCreatedAllCars = false;
-#else
- bool bCreatedAllCars;
-#endif
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse1); break;
- case GARAGE_HIDEOUT_TWO: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse2); break;
- case GARAGE_HIDEOUT_THREE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse3); break;
- default: break;
- }
- if (bCreatedAllCars)
- m_eGarageState = GS_OPENING;
- }
+ else if (RestoreCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)]))
+ m_eGarageState = GS_OPENING;
}
break;
}
@@ -1128,6 +1056,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -1158,8 +1088,42 @@ void CGarage::Update()
break;
}
break;
- //case GARAGE_COLLECTORSITEMS:
- //case GARAGE_60SECONDS:
+ //case GARAGE_COLLECTORSITEMS:
+ //case GARAGE_60SECONDS:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ switch (m_eGarageState) {
+ case GS_OPENED:
+ if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyCarBlockingDoor() && IsPlayerOutsideGarage()) {
+ CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
+ m_eGarageState = GS_CLOSING;
+ m_bClosingWithoutTargetCar = false;
+ }
+ break;
+ case GS_CLOSING:
+ m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == 0.0f) {
+ m_eGarageState = GS_FULLYCLOSED;
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ }
+ UpdateDoorsHeight();
+ break;
+ case GS_FULLYCLOSED:
+ break;
+ case GS_OPENING:
+ m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == m_fDoorHeight) {
+ m_eGarageState = GS_OPENED;
+ DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
+ }
+ UpdateDoorsHeight();
+ break;
+ //case GS_OPENEDCONTAINSCAR:
+ //case GS_CLOSEDCONTAINSCAR:
+ //case GS_AFTERDROPOFF:
+ default:
+ break;
+ }
default:
break;
}
@@ -1169,15 +1133,15 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
{
if (!FindPlayerVehicle())
return false;
- if (!FindPlayerVehicle()->IsCar())
+ if (!FindPlayerVehicle()->IsCar() && !FindPlayerVehicle()->IsBike())
return false;
if (FindPlayerPed()->GetPedState() != PED_DRIVING)
return false;
if (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_CAR)
return false;
CVehicle* pVehicle = FindPlayerVehicle();
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2)
+ if (pVehicle->GetPosition().x < m_fInfX || pVehicle->GetPosition().x > m_fSupX ||
+ pVehicle->GetPosition().y < m_fInfY || pVehicle->GetPosition().y > m_fSupY)
return false;
if (Abs(pVehicle->GetSpeed().x) > 0.01f ||
Abs(pVehicle->GetSpeed().y) > 0.01f ||
@@ -1188,35 +1152,58 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
return IsEntityEntirelyInside3D(pVehicle, 0.0f);
}
-bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
+bool CGarage::IsPointInsideGarage(CVector pos)
{
- if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
- pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
+ // is it IsPointInsideGarage(pos, 0.0f)?
+ if (pos.z < m_fInfZ)
+ return false;
+ if (pos.z > m_fSupZ)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir1Len < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir2Len < dp)
return false;
- CColModel* pColModel = pEntity->GetColModel();
- for (int i = 0; i < pColModel->numSpheres; i++) {
- CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
- float radius = pColModel->spheres[i].radius;
- if (pos.x - radius < m_fX1 || pos.x + radius > m_fX2 ||
- pos.y - radius < m_fY1 || pos.y + radius > m_fY2)
- return false;
- }
return true;
}
-bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
+bool CGarage::IsPointInsideGarage(CVector pos, float m_fMargin)
{
- if (pEntity->GetPosition().x < m_fX1 - fMargin || pEntity->GetPosition().x > m_fX2 + fMargin ||
- pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
- pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
+ if (pos.z < m_fInfZ - m_fMargin)
+ return false;
+ if (pos.z > m_fSupZ + m_fMargin)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir1Len + m_fMargin < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir2Len + m_fMargin < dp)
+ return false;
+ return true;
+}
+
+bool CGarage::IsEntityEntirelyInside3D(CEntity* pEntity, float fMargin)
+{
+ if (pEntity->GetPosition().x < m_fInfX - fMargin || pEntity->GetPosition().x > m_fSupX + fMargin ||
+ pEntity->GetPosition().y < m_fInfY - fMargin || pEntity->GetPosition().y > m_fSupY + fMargin ||
+ pEntity->GetPosition().z < m_fInfZ - fMargin || pEntity->GetPosition().z > m_fSupZ + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 - fMargin || pos.x - radius > m_fX2 + fMargin ||
- pos.y + radius < m_fY1 - fMargin || pos.y - radius > m_fY2 + fMargin ||
- pos.z + radius < m_fZ1 - fMargin || pos.z - radius > m_fZ2 + fMargin)
+ if (!IsPointInsideGarage(pos, fMargin - radius))
return false;
}
return true;
@@ -1224,15 +1211,14 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
{
- if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
- pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
+ if (pEntity->GetPosition().x > m_fInfX - fMargin && pEntity->GetPosition().x < m_fSupX + fMargin &&
+ pEntity->GetPosition().y > m_fInfY - fMargin && pEntity->GetPosition().y < m_fSupY + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 - fMargin && pos.x - radius < m_fX2 + fMargin &&
- pos.y + radius > m_fY1 - fMargin && pos.y - radius < m_fY2 + fMargin)
+ if (IsPointInsideGarage(pos, fMargin + radius))
return false;
}
return true;
@@ -1241,8 +1227,15 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
bool CGarage::IsGarageEmpty()
{
int16 num;
- CWorld::FindObjectsIntersectingCube(CVector(m_fX1, m_fY1, m_fZ1), CVector(m_fX2, m_fY2, m_fZ2), &num, 2, nil, false, true, true, false, false);
- return num == 0;
+ CEntity* pEntities[16];
+ CWorld::FindObjectsIntersectingCube(CVector(m_fInfX, m_fInfY, m_fInfZ), CVector(m_fSupX, m_fSupY, m_fSupZ), &num, 16, pEntities, false, true, true, false, false);
+ if (num <= 0)
+ return true;
+ for (int i = 0; i < 16; i++) {
+ if (IsEntityTouching3D(pEntities[i]))
+ return false;
+ }
+ return true;
}
bool CGarage::IsPlayerOutsideGarage()
@@ -1252,20 +1245,18 @@ bool CGarage::IsPlayerOutsideGarage()
return IsEntityEntirelyOutside(FindPlayerPed(), 0.0f);
}
-bool CGarage::IsEntityTouching3D(CEntity * pEntity)
+bool CGarage::IsEntityTouching3D(CEntity* pEntity)
{
float radius = pEntity->GetBoundRadius();
- if (m_fX1 - radius > pEntity->GetPosition().x || m_fX2 + radius < pEntity->GetPosition().x ||
- m_fY1 - radius > pEntity->GetPosition().y || m_fY2 + radius < pEntity->GetPosition().y ||
- m_fZ1 - radius > pEntity->GetPosition().z || m_fZ2 + radius < pEntity->GetPosition().z)
+ if (m_fInfX - radius > pEntity->GetPosition().x || m_fSupX + radius < pEntity->GetPosition().x ||
+ m_fInfY - radius > pEntity->GetPosition().y || m_fSupY + radius < pEntity->GetPosition().y ||
+ m_fInfZ - radius > pEntity->GetPosition().z || m_fSupZ + radius < pEntity->GetPosition().z)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
return false;
@@ -1277,9 +1268,7 @@ bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius + fMargin < m_fX1 || pos.x - radius - fMargin > m_fX2 ||
- pos.y + radius + fMargin < m_fY1 || pos.y - radius - fMargin > m_fY2 ||
- pos.z + radius + fMargin < m_fZ1 || pos.z - radius - fMargin > m_fZ2)
+ if (!IsPointInsideGarage(pos, fMargin + radius))
return true;
}
return false;
@@ -1290,7 +1279,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
uint32 i = CPools::GetVehiclePool()->GetSize();
while (i--) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle || pVehicle == pException)
+ if (!pVehicle || pVehicle == pException || pVehicle->GetStatus() == STATUS_WRECKED)
continue;
if (!IsEntityTouching3D(pVehicle))
continue;
@@ -1298,15 +1287,35 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
return false;
}
+void CGarage::ThrowCarsNearDoorOutOfGarage(CVehicle* pException)
+{
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle || pVehicle == pException)
+ continue;
+ if (!IsEntityTouching3D(pVehicle))
+ continue;
+ CColModel* pColModel = pVehicle->GetColModel();
+ for (int i = 0; i < pColModel->numSpheres; i++) {
+ CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
+ float radius = pColModel->spheres[i].radius;
+ if (!IsPointInsideGarage(pos, 0.0f)) {
+ CVector vecDirectionAway(pVehicle->GetPosition().x - GetGarageCenterX(), pVehicle->GetPosition().y - GetGarageCenterY(), 0.0f);
+ vecDirectionAway.Normalise();
+ pVehicle->AddToMoveSpeed(vecDirectionAway * CTimer::GetTimeStepInSeconds());
+ }
+ }
+ }
+}
+
bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
{
uint32 i = CPools::GetPedPool()->GetSize();
@@ -1320,9 +1329,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1342,9 +1349,7 @@ bool CGarage::IsAnyCarBlockingDoor()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2)
+ if (!IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1359,9 +1364,7 @@ int32 CGarage::CountCarsWithCenterPointWithinGarage(CEntity * pException)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || pVehicle == pException)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2)
+ if (IsPointInsideGarage(pVehicle->GetPosition()))
total++;
}
return total;
@@ -1376,14 +1379,12 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
continue;
if (!IsEntityTouching3D(pVehicle))
continue;
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2 ||
- pVehicle->GetPosition().z < m_fZ1 || pVehicle->GetPosition().z > m_fZ2) {
+ if (!IsPointInsideGarage(pVehicle->GetPosition())) {
if (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
CWorld::Remove(pVehicle);
delete pVehicle;
#ifndef FIX_BUGS
- return; // makes no sense
+ return;
#endif
}
}
@@ -1393,11 +1394,8 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
void CGarages::PrintMessages()
{
if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) {
-#ifdef FIX_BUGS
+ CFont::DrawFonts();
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f));
-#else
- CFont::SetScale(1.2f, 1.5f);
-#endif
CFont::SetPropOn();
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
@@ -1407,52 +1405,22 @@ void CGarages::PrintMessages()
CFont::SetCentreSize(SCREEN_WIDTH - 50);
#endif
CFont::SetCentreOn();
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
- CFont::SetColor(CRGBA(0, 0, 0, 255));
+ CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
+ CFont::SetDropShadowPosition(2);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
-#if defined(PS2_HUD) || defined (FIX_BUGS)
- float y_offset = SCREEN_HEIGHT / 3; // THIS is PS2 calculation
-#else
- float y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements
-#endif
+ float y_offset = SCREEN_SCALE_Y(140.0f);
if (MessageNumberInString2 >= 0) {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
-#else
- CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
-#endif
- CFont::SetColor(CRGBA(89, 115, 150, 255));
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
-#else
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
-#endif
+ CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(30.0f), gUString);
}
else if (MessageNumberInString >= 0) {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
-#else
- CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
-#endif
-
- CFont::SetColor(CRGBA(89, 115, 150, 255));
-
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
-#else
- CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
-#endif
+ CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(30.0f), gUString);
}
else {
-#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
-#else
- CFont::PrintString(SCREEN_WIDTH / 2 - 2.0f, y_offset - 2.0f, TheText.Get(MessageIDString));
-#endif
- CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
}
}
@@ -1470,6 +1438,9 @@ bool CGarages::IsCarSprayable(CVehicle * pVehicle)
case MI_BARRACKS:
case MI_DODO:
case MI_COACH:
+#ifndef GTA_PS2
+ case MI_FBIRANCH:
+#endif
return false;
default:
break;
@@ -1482,15 +1453,27 @@ void CGarage::UpdateDoorsHeight()
RefreshDoorPointers(false);
if (m_pDoor1) {
m_pDoor1->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor1Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor1X + m_fDoorPos * m_pDoor1->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor1Y - m_fDoorPos * m_pDoor1->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor1->GetPosition().z;
+ m_pDoor1->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor1, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor1->GetMatrix().UpdateRW();
m_pDoor1->UpdateRwFrame();
}
if (m_pDoor2) {
m_pDoor2->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor2Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor2X + m_fDoorPos * m_pDoor2->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor2Y - m_fDoorPos * m_pDoor2->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor2->GetPosition().z;
+ m_pDoor2->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor2, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor2->GetMatrix().UpdateRW();
m_pDoor2->UpdateRwFrame();
}
@@ -1600,11 +1583,12 @@ void CGarages::TriggerMessage(const char* text, int16 num1, uint16 time, int16 n
MessageNumberInString2 = num2;
}
-void CGarages::SetTargetCarForMissonGarage(int16 garage, CVehicle * pVehicle)
+void CGarages::SetTargetCarForMissonGarage(int16 garage, CVehicle* pVehicle)
{
assert(garage >= 0 && garage < NUM_GARAGES);
if (pVehicle) {
aGarages[garage].m_pTarget = pVehicle;
+ aGarages[garage].m_pTarget->RegisterReference((CEntity**)&aGarages[garage].m_pTarget);
if (aGarages[garage].m_eGarageState == GS_CLOSEDCONTAINSCAR)
aGarages[garage].m_eGarageState = GS_FULLYCLOSED;
}
@@ -1656,11 +1640,9 @@ bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id)
bool CGarage::DoesCraigNeedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return (CGarages::CarTypesCollected[ct] & BIT(i)) == 0;
}
return false;
@@ -1668,11 +1650,9 @@ bool CGarage::DoesCraigNeedThisCar(int32 mi)
bool CGarage::HasCraigCollectedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return CGarages::CarTypesCollected[ct] & BIT(i);
}
return false;
@@ -1680,12 +1660,10 @@ bool CGarage::HasCraigCollectedThisCar(int32 mi)
bool CGarage::MarkThisCarAsCollectedForCraig(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
int index;
for (index = 0; index < TOTAL_COLLECTCARS_CARS; index++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][index])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][index] || (gaCarsToCollectInCraigsGarages[ct][index] == MI_CHEETAH && mi == MI_VICECHEE))
break;
}
if (index >= TOTAL_COLLECTCARS_CARS)
@@ -1718,16 +1696,16 @@ void CGarage::CloseThisGarage()
float CGarage::CalcDistToGarageRectangleSquared(float X, float Y)
{
float distX, distY;
- if (X < m_fX1)
- distX = m_fX1 - X;
- else if (X > m_fX2)
- distX = X - m_fX2;
+ if (X < m_fInfX)
+ distX = m_fInfX - X;
+ else if (X > m_fSupX)
+ distX = X - m_fSupX;
else
distX = 0.0f;
- if (Y < m_fY1)
- distY = m_fY1 - Y;
- else if (Y > m_fY2)
- distY = Y - m_fY2;
+ if (Y < m_fInfY)
+ distY = m_fInfY - Y;
+ else if (Y > m_fSupY)
+ distY = Y - m_fSupY;
else
distY = 0.0f;
return SQR(distX) + SQR(distY);
@@ -1748,10 +1726,10 @@ void CGarage::FindDoorsEntities()
{
m_pDoor1 = nil;
m_pDoor2 = nil;
- int xstart = Max(0, CWorld::GetSectorIndexX(m_fX1));
- int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
- int ystart = Max(0, CWorld::GetSectorIndexY(m_fY1));
- int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fY2));
+ int xstart = Max(0, CWorld::GetSectorIndexX(GetGarageCenterX() - 100.0f));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(GetGarageCenterX() + 100.0f));
+ int ystart = Max(0, CWorld::GetSectorIndexY(GetGarageCenterY() - 100.0f));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(GetGarageCenterY() + 100.0f));
assert(xstart <= xend);
assert(ystart <= yend);
@@ -1766,20 +1744,22 @@ void CGarage::FindDoorsEntities()
FindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_DUMMIES_OVERLAP], true);
}
}
- if (!m_pDoor1 || !m_pDoor2)
- return;
- if (m_pDoor1->GetModelIndex() == MI_CRUSHERBODY || m_pDoor1->GetModelIndex() == MI_CRUSHERLID)
- return;
- CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
- CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
- if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
- if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
- m_pDoor1 = m_pDoor2;
- m_bDoor1IsDummy = m_bDoor2IsDummy;
+ if (m_pDoor1 && m_pDoor2) {
+ CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
+ CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
+ if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
+ if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
+ m_pDoor1 = m_pDoor2;
+ m_bDoor1IsDummy = m_bDoor2IsDummy;
+ }
+ m_pDoor2 = nil;
+ m_bDoor2IsDummy = false;
}
- m_pDoor2 = nil;
- m_bDoor2IsDummy = false;
}
+ if (m_pDoor1)
+ m_pDoor1->bUsesCollision = true;
+ if (m_pDoor2)
+ m_pDoor2->bUsesCollision = true;
}
void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
@@ -1792,29 +1772,8 @@ void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
pEntity->m_scanCode = CWorld::GetCurrentScanCode();
if (!pEntity || !CGarages::IsModelIndexADoor(pEntity->GetModelIndex()))
continue;
- if (Abs(pEntity->GetPosition().x - GetGarageCenterX()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (Abs(pEntity->GetPosition().y - GetGarageCenterY()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (pEntity->GetModelIndex() == MI_CRUSHERBODY) {
- m_pDoor1 = pEntity;
- m_bDoor1IsDummy = dummy;
- // very odd pool operations, they could have used GetJustIndex
- if (dummy)
- m_bDoor1PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor1PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
- continue;
- }
- if (pEntity->GetModelIndex() == MI_CRUSHERLID) {
- m_pDoor2 = pEntity;
- m_bDoor2IsDummy = dummy;
- if (dummy)
- m_bDoor2PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor2PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
+ if (!IsPointInsideGarage(pEntity->GetPosition(), 2.0f))
continue;
- }
if (!m_pDoor1) {
m_pDoor1 = pEntity;
m_bDoor1IsDummy = dummy;
@@ -1849,6 +1808,8 @@ void CGarages::SetGarageDoorToRotate(int16 garage)
aGarages[garage].m_bRotatedDoor = true;
aGarages[garage].m_fDoorHeight /= 2.0f;
aGarages[garage].m_fDoorHeight -= 0.1f;
+ aGarages[garage].m_fDoorPos = Min(aGarages[garage].m_fDoorHeight, aGarages[garage].m_fDoorPos);
+ aGarages[garage].UpdateDoorsHeight();
}
void CGarages::SetLeaveCameraForThisGarage(int16 garage)
@@ -1882,8 +1843,8 @@ void CStoredCar::StoreCar(CVehicle* pVehicle)
if (pVehicle->bExplosionProof) m_nFlags |= FLAG_EXPLOSIONPROOF;
if (pVehicle->bCollisionProof) m_nFlags |= FLAG_COLLISIONPROOF;
if (pVehicle->bMeleeProof) m_nFlags |= FLAG_MELEEPROOF;
- if (pVehicle->IsCar())
- m_nCarBombType = ((CAutomobile*)pVehicle)->m_bombType;
+ if (pVehicle->IsCar() || pVehicle->IsBike())
+ m_nCarBombType = ((CAutomobile*)pVehicle)->m_bombType; // NB: cast to CAutomobile is original behaviour
}
CVehicle* CStoredCar::RestoreCar()
@@ -1899,15 +1860,17 @@ CVehicle* CStoredCar::RestoreCar()
{
CVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB);
}
-#ifdef FIX_BUGS
CVehicle* pVehicle;
if (CModelInfo::IsBoatModel(m_nModelIndex))
pVehicle = new CBoat(m_nModelIndex, RANDOM_VEHICLE);
+ else if (CModelInfo::IsBikeModel(m_nModelIndex))
+ {
+ CBike* pBike = new CBike(m_nModelIndex, RANDOM_VEHICLE);
+ pBike->bIsStanding = true;
+ pVehicle = pBike;
+ }
else
pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#else
- CVehicle* pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#endif
pVehicle->SetPosition(m_vecPos);
pVehicle->SetStatus(STATUS_ABANDONED);
pVehicle->GetForward() = m_vecAngle;
@@ -1918,9 +1881,7 @@ CVehicle* CStoredCar::RestoreCar()
pVehicle->m_currentColour2 = m_nSecondaryColor;
pVehicle->m_nRadioStation = m_nRadioStation;
pVehicle->bFreebies = false;
-#ifdef FIX_BUGS
if (pVehicle->IsCar())
-#endif
{
((CAutomobile*)pVehicle)->m_bombType = m_nCarBombType;
#ifdef FIX_BUGS
@@ -1948,9 +1909,7 @@ void CGarage::StoreAndRemoveCarsForThisHideout(CStoredCar* aCars, int32 nMax)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) {
if (index < Max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f))
aCars[index++].StoreCar(pVehicle);
@@ -1985,24 +1944,23 @@ bool CGarage::RestoreCarsForThisHideout(CStoredCar* aCars)
bool CGarages::IsPointInAGarageCameraZone(CVector point)
{
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
switch (aGarages[i].m_eGarageType) {
case GARAGE_NONE:
break;
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.y)
+ case GARAGE_COLLECTCARS_4:
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_COLLECTCARS))
return true;
break;
default:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_DEFAULT <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_DEFAULT >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_DEFAULT <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_DEFAULT >= point.y)
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_DEFAULT))
return true;
break;
}
@@ -2017,8 +1975,13 @@ bool CGarages::CameraShouldBeOutside()
void CGarages::GivePlayerDetonator()
{
- FindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR, 1);
- FindPlayerPed()->GetWeapon(FindPlayerPed()->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY;
+ CPlayerPed* pPed = FindPlayerPed();
+ int slot = CWeaponInfo::GetWeaponInfo(WEAPONTYPE_DETONATOR)->m_nWeaponSlot;
+ pPed->GiveWeapon(WEAPONTYPE_DETONATOR, 1);
+ pPed->GetWeapon(pPed->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY;
+ pPed->m_nSelectedWepSlot = slot;
+ if (pPed->m_storedWeapon != WEAPONTYPE_UNIDENTIFIED)
+ pPed->m_storedWeapon = WEAPONTYPE_DETONATOR;
}
float CGarages::FindDoorHeightForMI(int32 mi)
@@ -2035,14 +1998,12 @@ void CGarage::TidyUpGarage()
while (--i) {
#endif
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle || !pVehicle->IsCar())
- continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
- if (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) {
- CWorld::Remove(pVehicle);
- delete pVehicle;
+ if (pVehicle && (pVehicle->IsCar() || pVehicle->IsBike())) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
+ if (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) {
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+ }
}
}
}
@@ -2057,9 +2018,9 @@ void CGarage::TidyUpGarageClose()
while (--i) {
#endif
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle || !pVehicle->IsCar())
+ if (!pVehicle)
continue;
- if (!pVehicle->IsCar() || pVehicle->GetStatus() != STATUS_WRECKED || !IsEntityTouching3D(pVehicle))
+ if ((!pVehicle->IsCar() && !pVehicle->IsBike()) || pVehicle->GetStatus() != STATUS_WRECKED || !IsEntityTouching3D(pVehicle))
continue;
bool bRemove = false;
if (m_eGarageState != GS_FULLYCLOSED) {
@@ -2067,11 +2028,8 @@ void CGarage::TidyUpGarageClose()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2) {
+ if (!IsPointInsideGarage(pos, radius))
bRemove = true;
- }
}
}
else
@@ -2087,7 +2045,11 @@ void CGarage::TidyUpGarageClose()
void CGarages::PlayerArrestedOrDied()
{
static int GarageToBeTidied = 0; // lol
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
if (aGarages[i].m_eGarageType != GARAGE_NONE)
aGarages[i].PlayerArrestedOrDied();
}
@@ -2114,6 +2076,17 @@ void CGarage::PlayerArrestedOrDied()
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
case GS_CLOSING:
@@ -2165,39 +2138,26 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle)
pVehicle->GetMatrix().GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance;
pVehicle->GetMatrix().GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance;
}
- if (!IsEntityEntirelyInside3D(pVehicle, 0.1f))
+ if (!IsEntityEntirelyInside3D(pVehicle, 0.3f))
pVehicle->SetPosition(pos);
}
void CGarages::CloseHideOutGaragesBeforeSave()
{
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
- if (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_TWO &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
+#endif
+ if (!IsThisGarageTypeSafehouse(aGarages[i].m_eGarageType))
continue;
- if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
- (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
+ if (aGarages[i].m_eGarageState != GS_FULLYCLOSED) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
- switch (aGarages[i].m_eGarageType) {
- case GARAGE_HIDEOUT_ONE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse1, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_TWO:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse2, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_THREE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse3, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- default:
- break;
- }
+ aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouses[FindSafeHouseIndexForGarageType(aGarages[i].m_eGarageType)], NUM_GARAGE_STORED_CARS);
+ aGarages[i].RemoveCarsBlockingDoorNotInside();
+ aGarages[i].m_fDoorPos = 0.0f;
+ aGarages[i].UpdateDoorsHeight();
}
- aGarages[i].m_fDoorPos = 0.0f;
- aGarages[i].UpdateDoorsHeight();
}
}
@@ -2205,46 +2165,32 @@ int32 CGarages::CountCarsInHideoutGarage(uint8 type)
{
int32 total = 0;
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- total += (aCarsInSafeHouse1[i].HasCar());
- break;
- case GARAGE_HIDEOUT_TWO:
- total += (aCarsInSafeHouse2[i].HasCar());
- break;
- case GARAGE_HIDEOUT_THREE:
- total += (aCarsInSafeHouse3[i].HasCar());
- break;
- default: break;
- }
+ total += aCarsInSafeHouses[FindSafeHouseIndexForGarageType(type)][i].HasCar();
}
return total;
}
-int32 CGarages::FindMaxNumStoredCarsForGarage(uint8 type)
-{
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- return LIMIT_CARS_IN_INDUSTRIAL;
- case GARAGE_HIDEOUT_TWO:
- return LIMIT_CARS_IN_COMMERCIAL;
- case GARAGE_HIDEOUT_THREE:
- return LIMIT_CARS_IN_SUBURBAN;
- default: break;
- }
- return 0;
-}
-
bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
{
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
switch (aGarages[i].m_eGarageType) {
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
default: break;
}
@@ -2254,14 +2200,16 @@ bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
bool CGarages::IsPointWithinAnyGarage(Const CVector& point)
{
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
switch (aGarages[i].m_eGarageType) {
case GARAGE_NONE:
continue;
default:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
}
}
@@ -2270,13 +2218,19 @@ bool CGarages::IsPointWithinAnyGarage(Const CVector& point)
void CGarages::SetAllDoorsBackToOriginalHeight()
{
+#ifdef FIX_BUGS
+ for (uint32 i = 0; i < NumGarages; i++) {
+#else
for (int i = 0; i < NUM_GARAGES; i++) {
+#endif
switch (aGarages[i].m_eGarageType) {
case GARAGE_NONE:
continue;
default:
aGarages[i].RefreshDoorPointers(true);
if (aGarages[i].m_pDoor1) {
+ aGarages[i].m_pDoor1->GetMatrix().GetPosition().x = aGarages[i].m_fDoor1X;
+ aGarages[i].m_pDoor1->GetMatrix().GetPosition().y = aGarages[i].m_fDoor1Y;
aGarages[i].m_pDoor1->GetMatrix().GetPosition().z = aGarages[i].m_fDoor1Z;
if (aGarages[i].m_pDoor1->IsObject())
((CObject*)aGarages[i].m_pDoor1)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor1Z;
@@ -2286,6 +2240,8 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
aGarages[i].m_pDoor1->UpdateRwFrame();
}
if (aGarages[i].m_pDoor2) {
+ aGarages[i].m_pDoor2->GetMatrix().GetPosition().x = aGarages[i].m_fDoor2X;
+ aGarages[i].m_pDoor2->GetMatrix().GetPosition().y = aGarages[i].m_fDoor2Y;
aGarages[i].m_pDoor2->GetMatrix().GetPosition().z = aGarages[i].m_fDoor2Z;
if (aGarages[i].m_pDoor2->IsObject())
((CObject*)aGarages[i].m_pDoor2)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor2Z;
@@ -2300,14 +2256,11 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
void CGarages::Save(uint8 * buf, uint32 * size)
{
-#ifdef FIX_GARAGE_SIZE
- INITSAVEBUF
- *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
-#else
- * size = 5484;
-#endif
-#if !defined THIS_IS_STUPID && !defined FIX_GARAGE_SIZE && defined COMPATIBLE_SAVES
- memset(buf + 5240, 0, *size - 5240); // garbage data is written otherwise
+//INITSAVEBUF
+ *size = 7876; // for some reason it's not actual size again
+ //*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
+#if !defined THIS_IS_STUPID && defined COMPATIBLE_SAVES
+ memset(buf + 7340, 0, *size - 7340); // garbage data is written otherwise
#endif
CloseHideOutGaragesBeforeSave();
WriteSaveBuf(buf, NumGarages);
@@ -2320,19 +2273,20 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, CarTypesCollected[i]);
WriteSaveBuf(buf, LastTimeHelpMessage);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- WriteSaveBuf(buf, aCarsInSafeHouse1[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse2[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse3[i]);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ WriteSaveBuf(buf, aCarsInSafeHouses[j][i]);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, aGarages[i].m_eGarageType);
WriteSaveBuf(buf, aGarages[i].m_eGarageState);
+ WriteSaveBuf(buf, aGarages[i].m_nMaxStoredCars);
WriteSaveBuf(buf, aGarages[i].field_2);
WriteSaveBuf(buf, aGarages[i].m_bClosingWithoutTargetCar);
WriteSaveBuf(buf, aGarages[i].m_bDeactivated);
WriteSaveBuf(buf, aGarages[i].m_bResprayHappened);
- ZeroSaveBuf(buf, 2);
+ ZeroSaveBuf(buf, 1);
WriteSaveBuf(buf, aGarages[i].m_nTargetModelIndex);
ZeroSaveBuf(buf, 4 + 4);
WriteSaveBuf(buf, aGarages[i].m_bDoor1PoolIndex);
@@ -2343,12 +2297,17 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, aGarages[i].m_bRotatedDoor);
WriteSaveBuf(buf, aGarages[i].m_bCameraFollowsPlayer);
ZeroSaveBuf(buf, 1);
- WriteSaveBuf(buf, aGarages[i].m_fX1);
- WriteSaveBuf(buf, aGarages[i].m_fX2);
- WriteSaveBuf(buf, aGarages[i].m_fY1);
- WriteSaveBuf(buf, aGarages[i].m_fY2);
- WriteSaveBuf(buf, aGarages[i].m_fZ1);
- WriteSaveBuf(buf, aGarages[i].m_fZ2);
+ WriteSaveBuf(buf, aGarages[i].m_vecCorner1);
+ WriteSaveBuf(buf, aGarages[i].m_fInfZ);
+ WriteSaveBuf(buf, aGarages[i].m_vDir1);
+ WriteSaveBuf(buf, aGarages[i].m_vDir2);
+ WriteSaveBuf(buf, aGarages[i].m_fSupZ);
+ WriteSaveBuf(buf, aGarages[i].m_fDir1Len);
+ WriteSaveBuf(buf, aGarages[i].m_fDir2Len);
+ WriteSaveBuf(buf, aGarages[i].m_fInfX);
+ WriteSaveBuf(buf, aGarages[i].m_fSupX);
+ WriteSaveBuf(buf, aGarages[i].m_fInfY);
+ WriteSaveBuf(buf, aGarages[i].m_fSupY);
WriteSaveBuf(buf, aGarages[i].m_fDoorPos);
WriteSaveBuf(buf, aGarages[i].m_fDoorHeight);
WriteSaveBuf(buf, aGarages[i].m_fDoor1X);
@@ -2359,15 +2318,13 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, aGarages[i].m_fDoor2Z);
WriteSaveBuf(buf, aGarages[i].m_nTimeToStartAction);
WriteSaveBuf(buf, aGarages[i].m_bCollectedCarsState);
- ZeroSaveBuf(buf, 3 + 4 + 4);
+ ZeroSaveBuf(buf, 3 + 4);
ZeroSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar));
#else
WriteSaveBuf(buf, aGarages[i]);
#endif
}
-#ifdef FIX_GARAGE_SIZE
- VALIDATESAVEBUF(*size);
-#endif
+//VALIDATESAVEBUF(*size);
}
const CStoredCar &CStoredCar::operator=(const CStoredCar & other)
@@ -2387,12 +2344,9 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other)
void CGarages::Load(uint8* buf, uint32 size)
{
-#ifdef FIX_GARAGE_SIZE
- INITSAVEBUF
- assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)));
-#else
- assert(size == 5484);
-#endif
+//INITSAVEBUF
+ assert(size == 7876);
+ //assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)));
CloseHideOutGaragesBeforeSave();
ReadSaveBuf(&NumGarages, buf);
int32 tempInt;
@@ -2407,46 +2361,52 @@ void CGarages::Load(uint8* buf, uint32 size)
ReadSaveBuf(&CarTypesCollected[i], buf);
ReadSaveBuf(&LastTimeHelpMessage, buf);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- ReadSaveBuf(&aCarsInSafeHouse1[i], buf);
- ReadSaveBuf(&aCarsInSafeHouse2[i], buf);
- ReadSaveBuf(&aCarsInSafeHouse3[i], buf);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ ReadSaveBuf(&aCarsInSafeHouses[j][i], buf);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++) {
#ifdef COMPATIBLE_SAVES
ReadSaveBuf(&aGarages[i].m_eGarageType, buf);
ReadSaveBuf(&aGarages[i].m_eGarageState, buf);
+ ReadSaveBuf(&aGarages[i].m_nMaxStoredCars, buf);
ReadSaveBuf(&aGarages[i].field_2, buf);
ReadSaveBuf(&aGarages[i].m_bClosingWithoutTargetCar, buf);
ReadSaveBuf(&aGarages[i].m_bDeactivated, buf);
ReadSaveBuf(&aGarages[i].m_bResprayHappened, buf);
- SkipSaveBuf(buf, 2);
+ SkipSaveBuf(buf, 1);
ReadSaveBuf(&aGarages[i].m_nTargetModelIndex, buf);
SkipSaveBuf(buf, 4 + 4);
- ReadSaveBuf(&aGarages[i].m_bDoor1PoolIndex, buf);
- ReadSaveBuf(&aGarages[i].m_bDoor2PoolIndex, buf);
- ReadSaveBuf(&aGarages[i].m_bDoor1IsDummy, buf);
- ReadSaveBuf(&aGarages[i].m_bDoor2IsDummy, buf);
- ReadSaveBuf(&aGarages[i].m_bRecreateDoorOnNextRefresh, buf);
- ReadSaveBuf(&aGarages[i].m_bRotatedDoor, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor1PoolIndex, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor2PoolIndex, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor1IsDummy, buf);
+ ReadSaveBuf(&aGarages[i].m_bDoor2IsDummy, buf);
+ ReadSaveBuf(&aGarages[i].m_bRecreateDoorOnNextRefresh, buf);
+ ReadSaveBuf(&aGarages[i].m_bRotatedDoor, buf);
ReadSaveBuf(&aGarages[i].m_bCameraFollowsPlayer, buf);
SkipSaveBuf(buf, 1);
- ReadSaveBuf(&aGarages[i].m_fX1, buf);
- ReadSaveBuf(&aGarages[i].m_fX2, buf);
- ReadSaveBuf(&aGarages[i].m_fY1, buf);
- ReadSaveBuf(&aGarages[i].m_fY2, buf);
- ReadSaveBuf(&aGarages[i].m_fZ1, buf);
- ReadSaveBuf(&aGarages[i].m_fZ2, buf);
- ReadSaveBuf(&aGarages[i].m_fDoorPos, buf);
- ReadSaveBuf(&aGarages[i].m_fDoorHeight, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor1X, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor1Y, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor2X, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor2Y, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor1Z, buf);
- ReadSaveBuf(&aGarages[i].m_fDoor2Z, buf);
- ReadSaveBuf(&aGarages[i].m_nTimeToStartAction, buf);
+ ReadSaveBuf(&aGarages[i].m_vecCorner1, buf);
+ ReadSaveBuf(&aGarages[i].m_fInfZ, buf);
+ ReadSaveBuf(&aGarages[i].m_vDir1, buf);
+ ReadSaveBuf(&aGarages[i].m_vDir2, buf);
+ ReadSaveBuf(&aGarages[i].m_fSupZ, buf);
+ ReadSaveBuf(&aGarages[i].m_fDir1Len, buf);
+ ReadSaveBuf(&aGarages[i].m_fDir2Len, buf);
+ ReadSaveBuf(&aGarages[i].m_fInfX, buf);
+ ReadSaveBuf(&aGarages[i].m_fSupX, buf);
+ ReadSaveBuf(&aGarages[i].m_fInfY, buf);
+ ReadSaveBuf(&aGarages[i].m_fSupY, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoorPos, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoorHeight, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1X, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1Y, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2X, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2Y, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor1Z, buf);
+ ReadSaveBuf(&aGarages[i].m_fDoor2Z, buf);
+ ReadSaveBuf(&aGarages[i].m_nTimeToStartAction, buf);
ReadSaveBuf(&aGarages[i].m_bCollectedCarsState, buf);
- SkipSaveBuf(buf, 3 + 4 + 4);
+ SkipSaveBuf(buf, 3 + 4);
SkipSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar));
#else
ReadSaveBuf(&aGarages[i], buf);
@@ -2454,7 +2414,6 @@ void CGarages::Load(uint8* buf, uint32 size)
aGarages[i].m_pDoor1 = nil;
aGarages[i].m_pDoor2 = nil;
aGarages[i].m_pTarget = nil;
- aGarages[i].field_96 = nil;
aGarages[i].m_bRecreateDoorOnNextRefresh = true;
aGarages[i].RefreshDoorPointers(true);
if (aGarages[i].m_eGarageType == GARAGE_CRUSHER)
@@ -2462,9 +2421,7 @@ void CGarages::Load(uint8* buf, uint32 size)
else
aGarages[i].UpdateDoorsHeight();
}
-#ifdef FIX_GARAGE_SIZE
- VALIDATESAVEBUF(size);
-#endif
+//VALIDATESAVEBUF(size);
MessageEndTime = 0;
bCamShouldBeOutisde = false;
@@ -2474,8 +2431,7 @@ void CGarages::Load(uint8* buf, uint32 size)
bool
CGarages::IsModelIndexADoor(uint32 id)
{
- return id == MI_GARAGEDOOR1 ||
- id == MI_GARAGEDOOR2 ||
+ return id == MI_GARAGEDOOR2 ||
id == MI_GARAGEDOOR3 ||
id == MI_GARAGEDOOR4 ||
id == MI_GARAGEDOOR5 ||
@@ -2489,7 +2445,6 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR14 ||
id == MI_GARAGEDOOR15 ||
id == MI_GARAGEDOOR16 ||
- id == MI_GARAGEDOOR17 ||
id == MI_GARAGEDOOR18 ||
id == MI_GARAGEDOOR19 ||
id == MI_GARAGEDOOR20 ||
@@ -2498,15 +2453,7 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR23 ||
id == MI_GARAGEDOOR24 ||
id == MI_GARAGEDOOR25 ||
- id == MI_GARAGEDOOR26 ||
- id == MI_GARAGEDOOR27 ||
- id == MI_GARAGEDOOR28 ||
- id == MI_GARAGEDOOR29 ||
- id == MI_GARAGEDOOR30 ||
- id == MI_GARAGEDOOR31 ||
- id == MI_GARAGEDOOR32 ||
- id == MI_CRUSHERBODY ||
- id == MI_CRUSHERLID;
+ id == MI_GARAGEDOOR26;
}
void CGarages::StopCarFromBlowingUp(CAutomobile* pCar)
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 8a9fd1b6..358d404d 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -41,12 +41,24 @@ enum eGarageType
GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,
GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,
GARAGE_MISSION_KEEPCAR_REMAINCLOSED,
+ GARAGE_COLLECTCARS_4,
+ GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR,
+ GARAGE_HIDEOUT_FOUR,
+ GARAGE_HIDEOUT_FIVE,
+ GARAGE_HIDEOUT_SIX,
+ GARAGE_HIDEOUT_SEVEN,
+ GARAGE_HIDEOUT_EIGHT,
+ GARAGE_HIDEOUT_NINE,
+ GARAGE_HIDEOUT_TEN,
+ GARAGE_HIDEOUT_ELEVEN,
+ GARAGE_HIDEOUT_TWELVE
};
enum
{
- TOTAL_COLLECTCARS_GARAGES = GARAGE_COLLECTCARS_3 - GARAGE_COLLECTCARS_1 + 1,
- TOTAL_COLLECTCARS_CARS = 16
+ TOTAL_COLLECTCARS_GARAGES = 4,
+ TOTAL_HIDEOUT_GARAGES = 12,
+ TOTAL_COLLECTCARS_CARS = 6
};
class CStoredCar
@@ -81,18 +93,12 @@ VALIDATE_SIZE(CStoredCar, 0x28);
#define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f
-#define CRUSHER_GARAGE_X1 (1135.5f)
-#define CRUSHER_GARAGE_Y1 (57.0f)
-#define CRUSHER_GARAGE_Z1 (-1.0f)
-#define CRUSHER_GARAGE_X2 (1149.5f)
-#define CRUSHER_GARAGE_Y2 (63.7f)
-#define CRUSHER_GARAGE_Z2 (3.5f)
-
class CGarage
{
public:
uint8 m_eGarageType;
uint8 m_eGarageState;
+ uint8 m_nMaxStoredCars;
bool field_2; // unused
bool m_bClosingWithoutTargetCar;
bool m_bDeactivated;
@@ -107,12 +113,17 @@ public:
bool m_bRecreateDoorOnNextRefresh;
bool m_bRotatedDoor;
bool m_bCameraFollowsPlayer;
- float m_fX1;
- float m_fX2;
- float m_fY1;
- float m_fY2;
- float m_fZ1;
- float m_fZ2;
+ CVector2D m_vecCorner1;
+ float m_fInfZ;
+ CVector2D m_vDir1;
+ CVector2D m_vDir2;
+ float m_fSupZ;
+ float m_fDir1Len;
+ float m_fDir2Len;
+ float m_fInfX;
+ float m_fSupX;
+ float m_fInfY;
+ float m_fSupY;
float m_fDoorPos;
float m_fDoorHeight;
float m_fDoor1X;
@@ -124,7 +135,6 @@ public:
uint32 m_nTimeToStartAction;
uint8 m_bCollectedCarsState;
CVehicle *m_pTarget;
- void* field_96; // unused
CStoredCar m_sStoredCar; // not needed
void OpenThisGarage();
@@ -133,16 +143,16 @@ public:
bool IsClosed() { return m_eGarageState == GS_FULLYCLOSED; }
bool IsUsed() { return m_eGarageType != GARAGE_NONE; }
void Update();
- float GetGarageCenterX() { return (m_fX1 + m_fX2) / 2; }
- float GetGarageCenterY() { return (m_fY1 + m_fY2) / 2; }
+ float GetGarageCenterX() { return (m_fInfX + m_fSupX) / 2; }
+ float GetGarageCenterY() { return (m_fInfY + m_fSupY) / 2; }
bool IsFar()
{
#ifdef FIX_BUGS
return Abs(TheCamera.GetPosition().x - GetGarageCenterX()) > SWITCH_GARAGE_DISTANCE_CLOSE ||
Abs(TheCamera.GetPosition().y - GetGarageCenterY()) > SWITCH_GARAGE_DISTANCE_CLOSE;
#else
- return Abs(TheCamera.GetPosition().x - m_fX1) > SWITCH_GARAGE_DISTANCE_CLOSE ||
- Abs(TheCamera.GetPosition().y - m_fY1) > SWITCH_GARAGE_DISTANCE_CLOSE;
+ return Abs(TheCamera.GetPosition().x - m_fInfX) > SWITCH_GARAGE_DISTANCE_CLOSE ||
+ Abs(TheCamera.GetPosition().y - m_fInfY) > SWITCH_GARAGE_DISTANCE_CLOSE;
#endif
}
void TidyUpGarageClose();
@@ -152,7 +162,6 @@ public:
void UpdateDoorsHeight();
bool IsEntityEntirelyInside3D(CEntity*, float);
bool IsEntityEntirelyOutside(CEntity*, float);
- bool IsEntityEntirelyInside(CEntity*);
float CalcDistToGarageRectangleSquared(float, float);
float CalcSmallestDistToGarageDoorSquared(float, float);
bool IsAnyOtherCarTouchingGarage(CVehicle* pException);
@@ -181,14 +190,18 @@ public:
void MarkThisCarAsCollectedFor60Seconds(int mi);
bool IsPlayerEntirelyInsideGarage();
-};
+ bool IsPointInsideGarage(CVector);
+ bool IsPointInsideGarage(CVector, float);
+ void ThrowCarsNearDoorOutOfGarage(CVehicle*);
+
+ int32 FindMaxNumStoredCarsForGarage() { return Min(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
-VALIDATE_SIZE(CGarage, 140);
+};
class CGarages
{
enum {
- MESSAGE_LENGTH = 8
+ MESSAGE_LENGTH = 8,
};
public:
static int32 BankVansCollected;
@@ -207,9 +220,7 @@ public:
static bool PlayerInGarage;
static int32 PoliceCarsCollected;
static CGarage aGarages[NUM_GARAGES];
- static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+ static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];
static bool bCamShouldBeOutisde;
static void Init(void);
@@ -218,7 +229,7 @@ public:
#endif
static void Update(void);
- static int16 AddOne(CVector pos1, CVector pos2, uint8 type, int32 targetId);
+ static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, uint8 type, int32 targetId);
static void ChangeGarageType(int16, uint8, int32);
static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16);
@@ -251,13 +262,42 @@ public:
static void SetFreeBombs(bool bValue) { BombsAreFree = bValue; }
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
static void StopCarFromBlowingUp(CAutomobile*);
+ static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
static int32 CountCarsInHideoutGarage(uint8);
- static int32 FindMaxNumStoredCarsForGarage(uint8);
static int32 GetBombTypeForGarageType(uint8 type) { return type - GARAGE_BOMBSHOP1 + 1; }
- static int32 GetCarsCollectedIndexForGarageType(uint8 type) { return type - GARAGE_COLLECTCARS_1; }
+ static int32 GetCarsCollectedIndexForGarageType(uint8 type)
+ {
+ switch (type) {
+ case GARAGE_COLLECTCARS_1: return 0;
+ case GARAGE_COLLECTCARS_2: return 1;
+ case GARAGE_COLLECTCARS_3: return 2;
+ case GARAGE_COLLECTCARS_4: return 3;
+ default: assert(0);
+ }
+ return 0;
+ }
+ static int32 FindSafeHouseIndexForGarageType(uint8 type)
+ {
+ switch (type) {
+ case GARAGE_HIDEOUT_ONE: return 0;
+ case GARAGE_HIDEOUT_TWO: return 1;
+ case GARAGE_HIDEOUT_THREE: return 2;
+ case GARAGE_HIDEOUT_FOUR: return 3;
+ case GARAGE_HIDEOUT_FIVE: return 4;
+ case GARAGE_HIDEOUT_SIX: return 5;
+ case GARAGE_HIDEOUT_SEVEN: return 6;
+ case GARAGE_HIDEOUT_EIGHT: return 7;
+ case GARAGE_HIDEOUT_NINE: return 8;
+ case GARAGE_HIDEOUT_TEN: return 9;
+ case GARAGE_HIDEOUT_ELEVEN: return 10;
+ case GARAGE_HIDEOUT_TWELVE: return 11;
+ }
+ return -1;
+ }
+ static bool IsThisGarageTypeSafehouse(uint8 type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
};
diff --git a/src/control/OnscreenTimer.cpp b/src/control/OnscreenTimer.cpp
index 08c68cb5..5045c1e0 100644
--- a/src/control/OnscreenTimer.cpp
+++ b/src/control/OnscreenTimer.cpp
@@ -7,23 +7,29 @@
#include "Timer.h"
#include "Script.h"
#include "OnscreenTimer.h"
+#include "Camera.h"
void
COnscreenTimer::Init()
{
m_bDisabled = false;
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
- m_sEntries[i].m_nTimerOffset = 0;
- m_sEntries[i].m_nCounterOffset = 0;
+ for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
+ m_sCounters[i].m_nCounterOffset = 0;
- for(uint32 j = 0; j < 10; j++) {
- m_sEntries[i].m_aTimerText[j] = '\0';
- m_sEntries[i].m_aCounterText[j] = '\0';
- }
+ for(uint32 j = 0; j < ARRAY_SIZE(m_sCounters[0].m_aCounterText); j++)
+ m_sCounters[i].m_aCounterText[j] = '\0';
+
+ m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;
+ m_sCounters[i].m_bCounterProcessed = false;
+ }
+ for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
+ m_sClocks[i].m_nClockOffset = 0;
- m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER;
- m_sEntries[i].m_bTimerProcessed = false;
- m_sEntries[i].m_bCounterProcessed = false;
+ for(uint32 j = 0; j < ARRAY_SIZE(m_sClocks[0].m_aClockText); j++)
+ m_sClocks[i].m_aClockText[j] = '\0';
+
+ m_sClocks[i].m_bClockProcessed = false;
+ m_sClocks[i].m_bClockGoingDown = true;
}
}
@@ -31,8 +37,8 @@ void
COnscreenTimer::Process()
{
if(!CReplay::IsPlayingBack() && !m_bDisabled)
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++)
- m_sEntries[i].Process();
+ for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++)
+ m_sClocks[i].Process();
}
void
@@ -40,21 +46,34 @@ COnscreenTimer::ProcessForDisplay()
{
if(CHud::m_Wants_To_Draw_Hud) {
m_bProcessed = false;
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++)
- if(m_sEntries[i].ProcessForDisplay())
+ for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
+ m_sClocks[i].m_bClockProcessed = false;
+ if (m_sClocks[i].m_nClockOffset != 0) {
+ m_sClocks[i].ProcessForDisplayClock();
+ m_sClocks[i].m_bClockProcessed = true;
+ m_bProcessed = true;
+ }
+ }
+ for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
+ m_sCounters[i].m_bCounterProcessed = false;
+ if (m_sCounters[i].m_nCounterOffset != 0) {
+ m_sCounters[i].ProcessForDisplayCounter();
+ m_sCounters[i].m_bCounterProcessed = true;
m_bProcessed = true;
+ }
+ }
}
}
void
COnscreenTimer::ClearCounter(uint32 offset)
{
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
- if(offset == m_sEntries[i].m_nCounterOffset) {
- m_sEntries[i].m_nCounterOffset = 0;
- m_sEntries[i].m_aCounterText[0] = '\0';
- m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER;
- m_sEntries[i].m_bCounterProcessed = false;
+ for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
+ if(offset == m_sCounters[i].m_nCounterOffset) {
+ m_sCounters[i].m_nCounterOffset = 0;
+ m_sCounters[i].m_aCounterText[0] = '\0';
+ m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;
+ m_sCounters[i].m_bCounterProcessed = false;
}
}
}
@@ -62,98 +81,85 @@ COnscreenTimer::ClearCounter(uint32 offset)
void
COnscreenTimer::ClearClock(uint32 offset)
{
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++)
- if(offset == m_sEntries[i].m_nTimerOffset) {
- m_sEntries[i].m_nTimerOffset = 0;
- m_sEntries[i].m_aTimerText[0] = '\0';
- m_sEntries[i].m_bTimerProcessed = false;
+ for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++)
+ if(offset == m_sClocks[i].m_nClockOffset) {
+ m_sClocks[i].m_nClockOffset = 0;
+ m_sClocks[i].m_aClockText[0] = '\0';
+ m_sClocks[i].m_bClockProcessed = false;
+ m_sClocks[i].m_bClockGoingDown = true;
}
}
void
-COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text)
+COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos)
{
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++)
- if(m_sEntries[i].m_nCounterOffset == 0) {
- m_sEntries[i].m_nCounterOffset = offset;
- if (text)
- strncpy(m_sEntries[i].m_aCounterText, text, 10);
- else
- m_sEntries[i].m_aCounterText[0] = '\0';
- m_sEntries[i].m_nType = type;
- break;
- }
+ if (m_sCounters[pos].m_aCounterText[0] != '\0')
+ return;
+
+ m_sCounters[pos].m_nCounterOffset = offset;
+ if(text)
+ strncpy(m_sCounters[pos].m_aCounterText, text, ARRAY_SIZE(m_sCounters[0].m_aCounterText));
+ else
+ m_sCounters[pos].m_aCounterText[0] = '\0';
+
+ m_sCounters[pos].m_nType = type;
}
void
-COnscreenTimer::AddClock(uint32 offset, char* text)
+COnscreenTimer::AddClock(uint32 offset, char* text, bool bGoingDown)
{
- for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++)
- if(m_sEntries[i].m_nTimerOffset == 0) {
- m_sEntries[i].m_nTimerOffset = offset;
- if (text)
- strncpy(m_sEntries[i].m_aTimerText, text, 10);
+ for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
+ if(m_sClocks[i].m_nClockOffset == 0) {
+ m_sClocks[i].m_nClockOffset = offset;
+ m_sClocks[i].m_bClockGoingDown = bGoingDown;
+ if(text)
+ strncpy(m_sClocks[i].m_aClockText, text, ARRAY_SIZE(m_sClocks[0].m_aClockText));
else
- m_sEntries[i].m_aTimerText[0] = '\0';
+ m_sClocks[i].m_aClockText[0] = '\0';
break;
}
+ }
}
void
COnscreenTimerEntry::Process()
{
- if(m_nTimerOffset == 0)
+ if(m_nClockOffset == 0)
return;
- int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nTimerOffset);
+ int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nClockOffset);
int32 oldTime = *timerPtr;
- int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds());
- if(newTime < 0) {
- *timerPtr = 0;
- m_bTimerProcessed = false;
- m_nTimerOffset = 0;
- m_aTimerText[0] = '\0';
- } else {
+ if (m_bClockGoingDown) {
+ int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds());
*timerPtr = newTime;
- int32 oldTimeSeconds = oldTime / 1000;
- if(oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds) {
- DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000);
+ if (newTime < 0) {
+ *timerPtr = 0;
+ m_bClockProcessed = 0;
+ m_nClockOffset = 0;
+ m_aClockText[0] = 0;
+ }
+ else {
+ int32 oldTimeSeconds = oldTime / 1000;
+ if (oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds && !TheCamera.m_WideScreenOn) {
+ DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000);
+ }
}
}
-}
-
-bool
-COnscreenTimerEntry::ProcessForDisplay()
-{
- m_bTimerProcessed = false;
- m_bCounterProcessed = false;
-
- if(m_nTimerOffset == 0 && m_nCounterOffset == 0)
- return false;
-
- if(m_nTimerOffset != 0) {
- m_bTimerProcessed = true;
- ProcessForDisplayClock();
- }
-
- if(m_nCounterOffset != 0) {
- m_bCounterProcessed = true;
- ProcessForDisplayCounter();
- }
- return true;
+ else
+ *timerPtr = oldTime + int32(CTimer::GetTimeStepInMilliseconds());
}
void
COnscreenTimerEntry::ProcessForDisplayClock()
{
- uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nTimerOffset);
- sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60,
+ uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nClockOffset);
+ sprintf(m_aClockBuffer, "%02d:%02d", time / 1000 / 60 % 100,
time / 1000 % 60);
}
void
-COnscreenTimerEntry::ProcessForDisplayCounter()
+COnscreenCounterEntry::ProcessForDisplayCounter()
{
uint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset);
- sprintf(m_bCounterBuffer, "%d", counter);
+ sprintf(m_aCounterBuffer, "%d", counter);
}
diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h
index 3ef7764a..8c049d7d 100644
--- a/src/control/OnscreenTimer.h
+++ b/src/control/OnscreenTimer.h
@@ -9,29 +9,37 @@ enum
class COnscreenTimerEntry
{
public:
- uint32 m_nTimerOffset;
+ uint32 m_nClockOffset;
+ char m_aClockText[10];
+ char m_aClockBuffer[40];
+ bool m_bClockProcessed;
+ bool m_bClockGoingDown;
+
+ void Process();
+ void ProcessForDisplayClock();
+};
+
+VALIDATE_SIZE(COnscreenTimerEntry, 0x3C);
+
+class COnscreenCounterEntry
+{
+public:
uint32 m_nCounterOffset;
- char m_aTimerText[10];
char m_aCounterText[10];
uint16 m_nType;
- char m_bCounterBuffer[42];
- char m_bTimerBuffer[42];
- bool m_bTimerProcessed;
+ char m_aCounterBuffer[40];
bool m_bCounterProcessed;
- void Process();
- bool ProcessForDisplay();
-
- void ProcessForDisplayClock();
void ProcessForDisplayCounter();
};
-VALIDATE_SIZE(COnscreenTimerEntry, 0x74);
+VALIDATE_SIZE(COnscreenCounterEntry, 0x3C);
class COnscreenTimer
{
public:
- COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
+ COnscreenTimerEntry m_sClocks[NUMONSCREENCLOCKS];
+ COnscreenCounterEntry m_sCounters[NUMONSCREENCOUNTERS];
bool m_bProcessed;
bool m_bDisabled;
@@ -42,8 +50,8 @@ public:
void ClearCounter(uint32 offset);
void ClearClock(uint32 offset);
- void AddCounter(uint32 offset, uint16 type, char* text);
- void AddClock(uint32 offset, char* text);
+ void AddCounter(uint32 offset, uint16 type, char* text, uint16 pos);
+ void AddClock(uint32 offset, char* text, bool bGoingDown);
};
-VALIDATE_SIZE(COnscreenTimer, 0x78);
+VALIDATE_SIZE(COnscreenTimer, 0xF4);
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index c6407820..80d40b45 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -18,21 +18,20 @@ CPathFind ThePaths;
#define MIN_PED_ROUTE_DISTANCE 23.8f
-#define NUMTEMPNODES 4000
-#define NUMDETACHED_CARS 100
-#define NUMDETACHED_PEDS 50
-
-
-// object flags:
-// 1 UseInRoadBlock
-// 2 east/west road(?)
+#define NUMTEMPNODES 5000
+#define NUMDETACHED_CARS 1024
+#define NUMDETACHED_PEDS 1214
+#define NUMTEMPEXTERNALNODES 4600
CPathInfoForObject *InfoForTileCars;
CPathInfoForObject *InfoForTilePeds;
-// unused
-CTempDetachedNode *DetachedNodesCars;
-CTempDetachedNode *DetachedNodesPeds;
+CPathInfoForObject *DetachedInfoForTileCars;
+CPathInfoForObject *DetachedInfoForTilePeds;
+CTempNodeExternal *TempExternalNodes;
+int32 NumTempExternalNodes;
+int32 NumDetachedPedNodeGroups;
+int32 NumDetachedCarNodeGroups;
bool
CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints)
@@ -197,7 +196,7 @@ CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CV
void
CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition)
{
- const CColBox& boundingBox = pEntity->GetColModel()->boundingBox;
+ const CBox& boundingBox = pEntity->GetColModel()->boundingBox;
const float fBoundMaxY = boundingBox.max.y + 0.3f;
const float fBoundMinY = boundingBox.min.y - 0.3f;
const float fBoundMaxX = boundingBox.max.x + 0.3f;
@@ -227,6 +226,25 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p
}
}
+// Make sure all externals link TO an internal
+void
+CPathInfoForObject::SwapConnectionsToBeRightWayRound(void)
+{
+ int e, i;
+ CPathInfoForObject *tile = this;
+
+ for(e = 0; e < 12; e++)
+ if(tile[e].type == NodeTypeExtern && tile[e].next < 0)
+ for(i = 0; i < 12; i++)
+ if(tile[i].type == NodeTypeIntern && tile[i].next == e){
+ tile[e].next = i;
+ tile[i].next = -1;
+ bool tmp = !!tile[e].crossing;
+ tile[e].crossing = tile[i].crossing;
+ tile[i].crossing = tmp;
+ }
+}
+
void
CPathFind::Init(void)
{
@@ -237,6 +255,7 @@ CPathFind::Init(void)
m_numConnections = 0;
m_numCarPathLinks = 0;
unk = 0;
+ NumTempExternalNodes = 0;
for(i = 0; i < NUM_PATHNODES; i++)
m_pathNodes[i].distance = MAX_DIST;
@@ -250,21 +269,28 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- // NB: MIAMI doesn't use numPathGroups here but hardcodes 4500
- InfoForTileCars = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTileCars, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
- InfoForTilePeds = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTilePeds, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
-
- // unused
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
- DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS];
- memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode));
- DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS];
- memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode));
+ // NB: MIAMI doesn't use numPathGroups here but hardcodes PATHNODESIZE
+ InfoForTileCars = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTileCars, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+ InfoForTilePeds = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTilePeds, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ DetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS];
+ memset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject));
+ DetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS];
+ memset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject));
+
+ delete[] TempExternalNodes;
+ TempExternalNodes = nil;
+ TempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES];
+ memset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal));
+ NumTempExternalNodes = 0;
+ NumDetachedPedNodeGroups = 0;
+ NumDetachedCarNodeGroups = 0;
}
void
@@ -274,66 +300,133 @@ CPathFind::RegisterMapObject(CTreadable *mapObject)
}
void
-CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing)
+CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTilePeds[i].type = type;
InfoForTilePeds[i].next = next;
- InfoForTilePeds[i].x = x;
- InfoForTilePeds[i].y = y;
- InfoForTilePeds[i].z = z;
+ InfoForTilePeds[i].x = x/16.0f;
+ InfoForTilePeds[i].y = y/16.0f;
+ InfoForTilePeds[i].z = z/16.0f;
+ InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);
InfoForTilePeds[i].numLeftLanes = 0;
InfoForTilePeds[i].numRightLanes = 0;
InfoForTilePeds[i].crossing = crossing;
-
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTilePeds[j].x && y == InfoForTilePeds[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several ped nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTilePeds[j].x, y, InfoForTilePeds[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ InfoForTilePeds[i].speedLimit = 0;
+ InfoForTilePeds[i].roadBlock = false;
+ InfoForTilePeds[i].disabled = false;
+ InfoForTilePeds[i].waterPath = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
+ InfoForTilePeds[i].betweenLevels = false;
+ InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTilePeds[id*12].SwapConnectionsToBeRightWayRound();
}
void
-CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight)
+CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTileCars[i].type = type;
InfoForTileCars[i].next = next;
- InfoForTileCars[i].x = x;
- InfoForTileCars[i].y = y;
- InfoForTileCars[i].z = z;
+ InfoForTileCars[i].x = x/16.0f;
+ InfoForTileCars[i].y = y/16.0f;
+ InfoForTileCars[i].z = z/16.0f;
+ InfoForTileCars[i].width = 8.0f*Min(width, 15.0f);
InfoForTileCars[i].numLeftLanes = numLeft;
InfoForTileCars[i].numRightLanes = numRight;
+ InfoForTileCars[i].crossing = false;
+ InfoForTileCars[i].speedLimit = 0;
+ InfoForTileCars[i].roadBlock = false;
+ InfoForTileCars[i].disabled = false;
+ InfoForTileCars[i].waterPath = false;
+ InfoForTileCars[i].onlySmallBoats = false;
+ InfoForTileCars[i].betweenLevels = false;
+ InfoForTileCars[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTileCars[id*12].SwapConnectionsToBeRightWayRound();
+}
+void
+CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate)
+{
+ int i;
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTileCars[j].x && y == InfoForTileCars[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several car nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTileCars[j].x, y, InfoForTileCars[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ if(NumDetachedPedNodeGroups >= NUMDETACHED_PEDS)
+ return;
+
+ i = NumDetachedPedNodeGroups*12 + node;
+ DetachedInfoForTilePeds[i].type = type;
+ DetachedInfoForTilePeds[i].next = next;
+ DetachedInfoForTilePeds[i].x = x/16.0f;
+ DetachedInfoForTilePeds[i].y = y/16.0f;
+ DetachedInfoForTilePeds[i].z = z/16.0f;
+ DetachedInfoForTilePeds[i].width = 8.0f*Min(width, 31.0f);
+ DetachedInfoForTilePeds[i].numLeftLanes = 0;
+ DetachedInfoForTilePeds[i].numRightLanes = 0;
+ DetachedInfoForTilePeds[i].crossing = crossing;
+ DetachedInfoForTilePeds[i].speedLimit = 0;
+ DetachedInfoForTilePeds[i].roadBlock = false;
+ DetachedInfoForTilePeds[i].disabled = disabled;
+ DetachedInfoForTilePeds[i].waterPath = false;
+ DetachedInfoForTilePeds[i].onlySmallBoats = false;
+ DetachedInfoForTilePeds[i].betweenLevels = betweenLevels;
+ DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTilePeds[NumDetachedPedNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedPedNodeGroups++;
+ }
}
void
-CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out)
+CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool onlySmallBoats)
+{
+ int i;
+
+ if(NumDetachedCarNodeGroups >= NUMDETACHED_CARS)
+ return;
+
+ i = NumDetachedCarNodeGroups*12 + node;
+ DetachedInfoForTileCars[i].type = type;
+ DetachedInfoForTileCars[i].next = next;
+ DetachedInfoForTileCars[i].x = x/16.0f;
+ DetachedInfoForTileCars[i].y = y/16.0f;
+ DetachedInfoForTileCars[i].z = z/16.0f;
+ DetachedInfoForTileCars[i].width = 8.0f*Min(width, 15.0f);
+ DetachedInfoForTileCars[i].numLeftLanes = numLeft;
+ DetachedInfoForTileCars[i].numRightLanes = numRight;
+ DetachedInfoForTileCars[i].crossing = false;
+ DetachedInfoForTileCars[i].speedLimit = speedLimit;
+ DetachedInfoForTileCars[i].roadBlock = roadBlock;
+ DetachedInfoForTileCars[i].disabled = disabled;
+ DetachedInfoForTileCars[i].waterPath = waterPath;
+ DetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;
+ DetachedInfoForTileCars[i].betweenLevels = betweenLevels;
+ DetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTileCars[NumDetachedCarNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedCarNodeGroups++;
+ }
+}
+
+void
+CPathFind::CalcNodeCoors(float x, float y, float z, int id, CVector *out)
{
CVector pos;
- pos.x = x / 16.0f;
- pos.y = y / 16.0f;
- pos.z = z / 16.0f;
+ pos.x = x;
+ pos.y = y;
+ pos.z = z;
*out = m_mapObjects[id]->GetMatrix() * pos;
}
@@ -347,23 +440,18 @@ CPathFind::LoadPathFindData(void)
void
CPathFind::PreparePathData(void)
{
- int i, j, k;
- int numExtern, numIntern, numLanes;
- float maxX, maxY;
+ int i, j;
+ int numExtern, numIntern;
CTempNode *tempNodes;
printf("PreparePathData\n");
if(!CPathFind::LoadPathFindData() && // empty
InfoForTileCars && InfoForTilePeds &&
- DetachedNodesCars && DetachedNodesPeds
- ){
+ DetachedInfoForTileCars && DetachedInfoForTilePeds && TempExternalNodes){
tempNodes = new CTempNode[NUMTEMPNODES];
m_numConnections = 0;
- for(i = 0; i < PATHNODESIZE; i++)
- m_pathNodes[i].unkBits = 0;
-
for(i = 0; i < PATHNODESIZE; i++){
numExtern = 0;
numIntern = 0;
@@ -377,6 +465,19 @@ CPathFind::PreparePathData(void)
printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i);
}
+ int numExternDetached, numInternDetached;
+ for(i = 0; i < NUMDETACHED_CARS; i++){
+ numExternDetached = 0;
+ numInternDetached = 0;
+ for(j = 0; j < 12; j++){
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern)
+ numExternDetached++;
+ if(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeIntern)
+ numInternDetached++;
+ }
+ // no diagnostic here
+ }
+
for(i = 0; i < PATHNODESIZE; i++)
for(j = 0; j < 12; j++)
if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){
@@ -388,51 +489,24 @@ CPathFind::PreparePathData(void)
if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0)
printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
}
+ for(i = 0; i < NUMDETACHED_CARS; i++)
+ for(j = 0; j < 12; j++)
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern){
+ // MI:%d here but no argument for it
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numRightLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes + DetachedInfoForTileCars[i*12 + j].numRightLanes <= 0)
+ printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
+ }
m_numPathNodes = 0;
- PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, NUMDETACHED_CARS);
+ PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedInfoForTileCars, NumDetachedCarNodeGroups);
m_numCarPathNodes = m_numPathNodes;
- PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, NUMDETACHED_PEDS);
+ PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedInfoForTilePeds, NumDetachedPedNodeGroups);
m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes;
- // TODO: figure out what exactly is going on here
- // Some roads seem to get a west/east flag
- for(i = 0; i < m_numMapObjects; i++){
- numExtern = 0;
- numIntern = 0;
- numLanes = 0;
- maxX = 0.0f;
- maxY = 0.0f;
- for(j = 0; j < 12; j++){
- k = m_mapObjects[i]->GetModelIndex()*12 + j;
- if(InfoForTileCars[k].type == NodeTypeExtern){
- numExtern++;
- numLanes = Max(numLanes, InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes);
- maxX = Max(maxX, Abs(InfoForTileCars[k].x));
- maxY = Max(maxY, Abs(InfoForTileCars[k].y));
- }else if(InfoForTileCars[k].type == NodeTypeIntern)
- numIntern++;
- }
-
- if(numIntern == 1 && numExtern == 2){
- if(numLanes < 4){
- if((i & 7) == 4){ // 1/8 probability
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }else{
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }
- }
-
delete[] tempNodes;
CountFloodFillGroups(PATH_CAR);
@@ -443,10 +517,12 @@ CPathFind::PreparePathData(void)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ delete[] TempExternalNodes;
+ TempExternalNodes = nil;
}
printf("Done with PreparePathData\n");
}
@@ -493,8 +569,8 @@ CPathFind::CountFloodFillGroups(uint8 type)
if(node->numLinks == 0){
if(type == PATH_CAR)
- printf("Single car node: %f %f %f (%d)\n",
- node->GetX(), node->GetY(), node->GetZ(), m_mapObjects[node->objectIndex]->GetModelIndex());
+ printf("Single car node: %f %f %f\n",
+ node->GetX(), node->GetY(), node->GetZ());
else
printf("Single ped node: %f %f %f\n",
node->GetX(), node->GetY(), node->GetZ());
@@ -524,48 +600,28 @@ int32 TempListLength;
void
CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int numDetached)
+ float maxdist, CPathInfoForObject *detachednodes, int numDetached)
{
static CVector CoorsXFormed;
- int i, j, k, l;
+ int i, j, k;
int l1, l2;
int start;
float posx, posy;
float dx, dy, mag;
float nearestDist;
int nearestId;
- int next;
int oldNumPathNodes, oldNumLinks;
float dist;
int iseg, jseg;
- int istart, jstart;
int done, cont;
int tileStart;
-#ifndef MASTER
- for (i = 0; i < m_numMapObjects-1; i++)
- for (j = i+1; j < m_numMapObjects; j++) {
- CTreadable *obj1 = m_mapObjects[i];
- CTreadable *obj2 = m_mapObjects[j];
- if (obj1->GetModelIndex() == obj2->GetModelIndex() &&
- obj1->GetPosition().x == obj2->GetPosition().x && obj1->GetPosition().y == obj2->GetPosition().y && obj1->GetPosition().z == obj2->GetPosition().z &&
- obj1->GetRight().x == obj2->GetRight().x && obj1->GetForward().x == obj2->GetForward().x && obj1->GetUp().x == obj2->GetUp().x &&
- obj1->GetRight().y == obj2->GetRight().y && obj1->GetForward().y == obj2->GetForward().y && obj1->GetUp().y == obj2->GetUp().y &&
- obj1->GetRight().z == obj2->GetRight().z && obj1->GetForward().z == obj2->GetForward().z && obj1->GetUp().z == obj2->GetUp().z) {
- printf("THIS IS VERY BAD INDEED. FIX IMMEDIATELY!!!\n");
- printf("Double road objects at the following coors: %f %f %f\n", obj1->GetPosition().x, obj1->GetPosition().y, obj1->GetPosition().z);
- }
- }
-#endif // !MASTER
-
oldNumPathNodes = m_numPathNodes;
oldNumLinks = m_numConnections;
-#define OBJECTINDEX(n) (m_pathNodes[(n)].objectIndex)
- // Initialize map objects
- for(i = 0; i < m_numMapObjects; i++)
- for(j = 0; j < 12; j++)
- m_mapObjects[i]->m_nodeIndices[type][j] = -1;
+#define OBJECTINDEX(n) (mapObjIndices[(n)])
+ int16 *mapObjIndices = new int16[NUM_PATHNODES];
+ NumTempExternalNodes = 0;
// Calculate internal nodes, store them and connect them to defining object
for(i = 0; i < m_numMapObjects; i++){
@@ -581,89 +637,125 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
&CoorsXFormed);
m_pathNodes[m_numPathNodes].SetPosition(CoorsXFormed);
OBJECTINDEX(m_numPathNodes) = i;
- m_pathNodes[m_numPathNodes].unkBits = 1;
- m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes;
+ m_pathNodes[m_numPathNodes].width = objectpathinfo[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = objectpathinfo[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = objectpathinfo[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = objectpathinfo[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;
m_numPathNodes++;
}
+ else if(objectpathinfo[start + j].type == NodeTypeExtern){
+ CalcNodeCoors(
+ objectpathinfo[start + j].x,
+ objectpathinfo[start + j].y,
+ objectpathinfo[start + j].z,
+ i,
+ &CoorsXFormed);
+ TempExternalNodes[NumTempExternalNodes].pos = CoorsXFormed;
+ assert(objectpathinfo[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + objectpathinfo[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = objectpathinfo[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = objectpathinfo[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!objectpathinfo[start + j].crossing;
+ NumTempExternalNodes++;
+ }
}
}
+ // Same thing for detached nodes
+ for(i = 0; i < numDetached; i++){
+ tileStart = m_numPathNodes;
+ start = 12*i;
+ for(j = 0; j < 12; j++){
+ if(detachednodes[start + j].type == NodeTypeIntern){
+ CVector pos;
+ pos.x = detachednodes[start + j].x;
+ pos.y = detachednodes[start + j].y;
+ pos.z = detachednodes[start + j].z;
+ m_pathNodes[m_numPathNodes].SetPosition(pos);
+ mapObjIndices[m_numPathNodes] = -(i+1);
+ m_pathNodes[m_numPathNodes].width = detachednodes[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = detachednodes[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = detachednodes[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = detachednodes[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;
+ m_numPathNodes++;
+ }else if(detachednodes[start + j].type == NodeTypeExtern){
+ TempExternalNodes[NumTempExternalNodes].pos.x = detachednodes[start + j].x;
+ TempExternalNodes[NumTempExternalNodes].pos.y = detachednodes[start + j].y;
+ TempExternalNodes[NumTempExternalNodes].pos.z = detachednodes[start + j].z;
+ assert(detachednodes[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + detachednodes[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = detachednodes[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = detachednodes[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = detachednodes[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!detachednodes[start + j].crossing;
+ NumTempExternalNodes++;
+ }
+ }
+ }
// Insert external nodes into TempList
TempListLength = 0;
- for(i = 0; i < m_numMapObjects; i++){
- start = 12 * m_mapObjects[i]->GetModelIndex();
- for(j = 0; j < 12; j++){
- if(objectpathinfo[start + j].type != NodeTypeExtern)
+ for(i = 0; i < NumTempExternalNodes; i++){
+ // find closest unconnected node
+ nearestId = -1;
+ nearestDist = maxdist;
+ for(k = 0; k < TempListLength; k++){
+ if(tempnodes[k].linkState != 1)
continue;
- CalcNodeCoors(
- objectpathinfo[start + j].x,
- objectpathinfo[start + j].y,
- objectpathinfo[start + j].z,
- i,
- &CoorsXFormed);
-
- // find closest unconnected node
- nearestId = -1;
- nearestDist = maxdist;
- for(k = 0; k < TempListLength; k++){
- if(tempnodes[k].linkState != 1)
- continue;
- dx = tempnodes[k].pos.x - CoorsXFormed.x;
- if(Abs(dx) < nearestDist){
- dy = tempnodes[k].pos.y - CoorsXFormed.y;
- if(Abs(dy) < nearestDist){
- nearestDist = Max(Abs(dx), Abs(dy));
- nearestId = k;
- }
+ dx = tempnodes[k].pos.x - TempExternalNodes[i].pos.x;
+ if(Abs(dx) < nearestDist){
+ dy = tempnodes[k].pos.y - TempExternalNodes[i].pos.y;
+ if(Abs(dy) < nearestDist){
+ nearestDist = Max(Abs(dx), Abs(dy));
+ nearestId = k;
}
}
+ }
- if(nearestId < 0){
- // None found, add this one to temp list
- tempnodes[TempListLength].pos = CoorsXFormed;
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- // link to connecting internal node
- tempnodes[TempListLength].link1 = m_mapObjects[i]->m_nodeIndices[type][next];
- if(type == PATH_CAR){
- tempnodes[TempListLength].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
- tempnodes[TempListLength].numRightLanes = objectpathinfo[start + j].numRightLanes;
- }
- tempnodes[TempListLength++].linkState = 1;
- }else{
- // Found nearest, connect it to our neighbour
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- tempnodes[nearestId].link2 = m_mapObjects[i]->m_nodeIndices[type][next];
- tempnodes[nearestId].linkState = 2;
-
- // collapse this node with nearest we found
- dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
- dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
- tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f;
- mag = Sqrt(dx*dx + dy*dy);
- tempnodes[nearestId].dirX = dx/mag;
- tempnodes[nearestId].dirY = dy/mag;
- // do something when number of lanes doesn't agree
- if(type == PATH_CAR)
- if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
- (objectpathinfo[start + j].numLeftLanes == 0 || objectpathinfo[start + j].numRightLanes == 0)){
- // why switch left and right here?
- tempnodes[nearestId].numLeftLanes = objectpathinfo[start + j].numRightLanes;
- tempnodes[nearestId].numRightLanes = objectpathinfo[start + j].numLeftLanes;
- }
+ if(nearestId < 0){
+ // None found, add this one to temp list
+ tempnodes[TempListLength].pos = TempExternalNodes[i].pos;
+ // link to connecting internal node
+ tempnodes[TempListLength].link1 = TempExternalNodes[i].next;
+ if(type == PATH_CAR){
+ tempnodes[TempListLength].numLeftLanes = TempExternalNodes[i].numLeftLanes;
+ tempnodes[TempListLength].numRightLanes = TempExternalNodes[i].numRightLanes;
}
+ tempnodes[TempListLength].width = TempExternalNodes[i].width;
+ tempnodes[TempListLength].isCross = TempExternalNodes[i].isCross;
+ tempnodes[TempListLength++].linkState = 1;
+ }else{
+ // Found nearest, connect it to our neighbour
+ tempnodes[nearestId].link2 = TempExternalNodes[i].next;
+ tempnodes[nearestId].linkState = 2;
+
+ // collapse this node with nearest we found
+ dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
+ dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
+ tempnodes[nearestId].pos = (tempnodes[nearestId].pos + TempExternalNodes[i].pos)*0.5f;
+ mag = Sqrt(dx*dx + dy*dy);
+ tempnodes[nearestId].dirX = dx/mag * 100;
+ tempnodes[nearestId].dirY = dy/mag * 100;
+ tempnodes[nearestId].width = Max(tempnodes[nearestId].width, TempExternalNodes[i].width);
+ if(TempExternalNodes[i].isCross)
+ tempnodes[nearestId].isCross = true; // TODO: is this guaranteed to be false otherwise?
+ // do something when number of lanes doesn't agree
+ if(type == PATH_CAR)
+ if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
+ (TempExternalNodes[i].numLeftLanes == 0 || TempExternalNodes[i].numRightLanes == 0)){
+ // why switch left and right here?
+ tempnodes[nearestId].numLeftLanes = TempExternalNodes[i].numRightLanes;
+ tempnodes[nearestId].numRightLanes = TempExternalNodes[i].numLeftLanes;
+ }
}
}
@@ -688,27 +780,30 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
continue;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
- m_connectionFlags[m_numConnections].flags = 0;
+ m_distances[m_numConnections] = Min(dist, 255);
+ if(tempnodes[j].isCross)
+ m_connections[j] |= 0x8000; // crosses road flag
if(type == PATH_CAR){
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
- m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
- m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
- m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
+ if(m_carPathLinks[k].dirX == tempnodes[j].dirX &&
+ m_carPathLinks[k].dirY == tempnodes[j].dirY &&
+ m_carPathLinks[k].x == (int)(tempnodes[j].pos.x*8.0f) &&
+ m_carPathLinks[k].y == (int)(tempnodes[j].pos.y*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
- m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
- m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
- m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
+ m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX;
+ m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY;
+ m_carPathLinks[m_numCarPathLinks].x = tempnodes[j].pos.x*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = tempnodes[j].pos.y*8.0f;
+ m_carPathLinks[m_numCarPathLinks].trafficLightDirection = false;
+ m_carPathLinks[m_numCarPathLinks].width = tempnodes[j].width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
@@ -722,6 +817,18 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_numConnections++;
}
+ CPathInfoForObject *tile;
+ if(mapObjIndices[i] < 0){
+ if(type == PATH_CAR)
+ tile = &DetachedInfoForTileCars[12 * (-1 - mapObjIndices[i])];
+ else
+ tile = &DetachedInfoForTilePeds[12 * (-1 - mapObjIndices[i])];
+ }else{
+ if(type == PATH_CAR)
+ tile = &InfoForTileCars[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ else
+ tile = &InfoForTilePeds[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ }
// Find i inside path segment
iseg = 0;
@@ -729,7 +836,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
if(OBJECTINDEX(j) == OBJECTINDEX(i))
iseg++;
- istart = 12 * m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex();
// Add links to other internal nodes
for(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){
if(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j)
@@ -737,14 +843,13 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// N.B.: in every path segment, the externals have to be at the end
jseg = j-i + iseg;
- jstart = 12 * m_mapObjects[m_pathNodes[j].objectIndex]->GetModelIndex();
- if(objectpathinfo[istart + iseg].next == jseg ||
- objectpathinfo[jstart + jseg].next == iseg){
+ if(tile[iseg].next == jseg ||
+ tile[jseg].next == iseg){
// Found a link between i and jConnectionSetCrossesRoad
// NB this clears the flags in MIAMI
m_connections[m_numConnections] = j;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
+ m_distances[m_numConnections] = Min(dist, 255);
if(type == PATH_CAR){
posx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f;
@@ -754,6 +859,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
mag = Sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;
+ uint8 width = Max(m_pathNodes[i].width, m_pathNodes[j].width);
if(i < j){
dx = -dx;
dy = -dy;
@@ -761,20 +867,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == dx &&
- m_carPathLinks[k].dir.y == dy &&
- m_carPathLinks[k].pos.x == posx &&
- m_carPathLinks[k].pos.y == posy){
+ if(m_carPathLinks[k].dirX == (int)(dx*100.0f) &&
+ m_carPathLinks[k].dirY == (int)(dy*100.0f) &&
+ m_carPathLinks[k].x == (int)(posx*8.0f) &&
+ m_carPathLinks[k].y == (int)(posy*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = dx;
- m_carPathLinks[m_numCarPathLinks].dir.y = dy;
- m_carPathLinks[m_numCarPathLinks].pos.x = posx;
- m_carPathLinks[m_numCarPathLinks].pos.y = posy;
+ m_carPathLinks[m_numCarPathLinks].dirX = dx*100.0f;
+ m_carPathLinks[m_numCarPathLinks].dirY = dy*100.0f;
+ m_carPathLinks[m_numCarPathLinks].x = posx*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = posy*8.0f;
+ m_carPathLinks[m_numCarPathLinks].trafficLightDirection = false;
+ m_carPathLinks[m_numCarPathLinks].width = width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
@@ -784,11 +892,9 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
}
}else{
// Crosses road
- if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].crossing ||
- objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].crossing)
- m_connectionFlags[m_numConnections].bCrossesRoad = true;
- else
- m_connectionFlags[m_numConnections].bCrossesRoad = false;
+ if(tile[iseg].next == jseg && tile[iseg].crossing ||
+ tile[jseg].next == iseg && tile[jseg].crossing)
+ m_connections[m_numConnections] |= 0x8000; // crosses road flag
}
m_pathNodes[i].numLinks++;
@@ -801,7 +907,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
done = 0;
// Set number of lanes for all nodes somehow
// very strange code
- for(k = 0; !done && k < 10; k++){
+ for(k = 0; !done && k < 12; k++){
done = 1;
for(i = 0; i < m_numPathNodes; i++){
if(m_pathNodes[i].numLinks != 2)
@@ -809,33 +915,50 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
l1 = m_carPathConnections[m_pathNodes[i].firstLink];
l2 = m_carPathConnections[m_pathNodes[i].firstLink+1];
- if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes != -1){
+ int8 l1Left = m_carPathLinks[l1].numLeftLanes;
+ int8 l1Right = m_carPathLinks[l1].numRightLanes;
+ int8 l2Left = m_carPathLinks[l2].numLeftLanes;
+ int8 l2Right = m_carPathLinks[l2].numRightLanes;
+ int8 *l1Leftp, *l1Rightp;
+ int8 *l2Leftp, *l2Rightp;
+ if(m_carPathLinks[l1].pathNodeIndex == i){
+ l1Leftp = &l1Left;
+ l1Rightp = &l1Right;
+ }else{
+ l1Leftp = &l1Right;
+ l1Rightp = &l1Left;
+ }
+ if(m_carPathLinks[l2].pathNodeIndex == i){
+ l2Leftp = &l2Left;
+ l2Rightp = &l2Right;
+ }else{
+ l2Leftp = &l2Right;
+ l2Rightp = &l2Left;
+ }
+ if(*l1Leftp == -1 && *l2Rightp != -1){
+ *l1Leftp = *l2Rightp;
done = 0;
- if(m_carPathLinks[l2].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numRightLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numLeftLanes;
- }else{
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numLeftLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numRightLanes;
- }
- m_carPathLinks[l1].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes != -1 &&
- m_carPathLinks[l2].numLeftLanes == -1){
+ }
+ if(*l1Rightp == -1 && *l2Leftp != -1){
+ *l1Rightp = *l2Leftp;
done = 0;
- if(m_carPathLinks[l1].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numRightLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numLeftLanes;
- }else{
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numLeftLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numRightLanes;
- }
- m_carPathLinks[l2].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes == -1)
+ }
+ if(*l2Leftp == -1 && *l1Rightp != -1){
+ *l2Leftp = *l1Rightp;
+ done = 0;
+ }
+ if(*l2Rightp == -1 && *l1Leftp != -1){
+ *l2Rightp = *l1Leftp;
+ done = 0;
+ }
+ if(*l1Leftp == -1 && *l2Rightp == -1)
+ done = 0;
+ if(*l2Leftp == -1 && *l1Rightp == -1)
done = 0;
+ m_carPathLinks[l1].numLeftLanes = l1Left;
+ m_carPathLinks[l1].numRightLanes = l1Right;
+ m_carPathLinks[l2].numLeftLanes = l2Left;
+ m_carPathLinks[l2].numRightLanes = l2Right;
}
}
@@ -843,10 +966,10 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
for(i = 0; i < m_numPathNodes; i++)
for(j = 0; j < m_pathNodes[i].numLinks; j++){
k = m_carPathConnections[m_pathNodes[i].firstLink + j];
- if(m_carPathLinks[k].numLeftLanes < 0)
- m_carPathLinks[k].numLeftLanes = 1;
- if(m_carPathLinks[k].numRightLanes < 0)
- m_carPathLinks[k].numRightLanes = 1;
+ if(m_carPathLinks[k].numLeftLanes == -1)
+ m_carPathLinks[k].numLeftLanes = 0;
+ if(m_carPathLinks[k].numRightLanes == -1)
+ m_carPathLinks[k].numRightLanes = 0;
}
}
@@ -855,8 +978,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
do{
cont = 0;
for(i = 0; i < m_numPathNodes; i++){
- m_pathNodes[i].bDisabled = false;
- m_pathNodes[i].bBetweenLevels = false;
// See if node is a dead end, if so, we're not done yet
if(!m_pathNodes[i].bDeadEnd){
k = 0;
@@ -889,21 +1010,11 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_connections[j] = node-1;
}
- // Also in treadables
- for(j = 0; j < m_numMapObjects; j++)
- for(k = 0; k < 12; k++){
- if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] == i){
- // remove this one
- for(l = k; l < 12-1; l++)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][l] = m_mapObjects[j]->m_nodeIndices[PATH_PED][l+1];
- m_mapObjects[j]->m_nodeIndices[PATH_PED][11] = -1;
- }else if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] > i)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][k]--;
- }
-
i--;
m_numPathNodes--;
}
+
+ delete[] mapObjIndices;
}
float
@@ -922,15 +1033,6 @@ CPathFind::CalcRoadDensity(float x, float y)
next = m_carPathConnections[m_pathNodes[i].firstLink + j];
density += m_carPathLinks[next].numLeftLanes * dist;
density += m_carPathLinks[next].numRightLanes * dist;
-
- if(m_carPathLinks[next].numLeftLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
- if(m_carPathLinks[next].numRightLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
}
}
}
@@ -990,6 +1092,7 @@ CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)
}
}
+#ifdef GTA_BRIDGE
void
CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable)
{
@@ -1001,6 +1104,7 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
m_carPathLinks[i].bBridgeLights = enable;
}
}
+#endif
void
CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)
@@ -1142,7 +1246,7 @@ CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y
}
int32
-CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels)
+CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, bool ignoreSelected, bool bWaterPath)
{
int i;
int firstNode, lastNode;
@@ -1164,17 +1268,14 @@ CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bo
for(i = firstNode; i < lastNode; i++){
if(ignoreDisabled && m_pathNodes[i].bDisabled) continue;
if(ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dist = Abs(m_pathNodes[i].GetX() - coors.x) +
- Abs(m_pathNodes[i].GetY() - coors.y) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
- if(dist < closestDist){
- closestDist = dist;
- closestNode = i;
- }
- break;
+ if(ignoreSelected && m_pathNodes[i].bSelected) continue;
+ if(bWaterPath != m_pathNodes[i].bWaterPath) continue;
+ dist = Abs(m_pathNodes[i].GetX() - coors.x) +
+ Abs(m_pathNodes[i].GetY() - coors.y) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ closestDist = dist;
+ closestNode = i;
}
}
return closestDist < distLimit ? closestNode : -1;
@@ -1202,25 +1303,116 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa
}
for(i = firstNode; i < lastNode; i++){
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dX = m_pathNodes[i].GetX() - coors.x;
- dY = m_pathNodes[i].GetY() - coors.y;
- dist = Abs(dX) + Abs(dY) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ dX = m_pathNodes[i].GetX() - coors.x;
+ dY = m_pathNodes[i].GetY() - coors.y;
+ dist = Abs(dX) + Abs(dY) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ NormalizeXY(dX, dY);
+ dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
if(dist < closestDist){
- NormalizeXY(dX, dY);
- dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
- if(dist < closestDist){
+ closestDist = dist;
+ closestNode = i;
+ }
+ }
+ }
+ return closestNode;
+}
+
+void
+CPathFind::FindNodePairClosestToCoors(CVector coors, uint8 type, int* node1, int* node2, float* angle, float minDist, float maxDist, bool ignoreDisabled, bool ignoreBetweenLevels, bool bWaterPath)
+{
+ int i, j;
+ int firstNode, lastNode, connectedNode;
+ float dist;
+ float closestDist = 10000.0f;
+ int closestNode = 0, closestConnectedNode = 0;
+
+ switch (type) {
+ case PATH_CAR:
+ firstNode = 0;
+ lastNode = m_numCarPathNodes;
+ break;
+ case PATH_PED:
+ firstNode = m_numCarPathNodes;
+ lastNode = m_numPathNodes;
+ break;
+ }
+
+ for (i = firstNode; i < lastNode; i++) {
+ if (ignoreDisabled && m_pathNodes[i].bDisabled) continue;
+ if (ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;
+ if (bWaterPath != m_pathNodes[i].bWaterPath) continue;
+ dist = Abs(m_pathNodes[i].GetX() - coors.x) +
+ Abs(m_pathNodes[i].GetY() - coors.y) +
+ 3.0f * Abs(m_pathNodes[i].GetZ() - coors.z);
+ if (dist < closestDist) {
+ for (j = 0; j < m_pathNodes[i].numLinks; j++) {
+ connectedNode = ConnectedNode(m_pathNodes[i].firstLink + j);
+ if (ignoreDisabled && m_pathNodes[connectedNode].bDisabled) continue;
+ if (ignoreBetweenLevels && m_pathNodes[connectedNode].bBetweenLevels) continue;
+ if (bWaterPath != m_pathNodes[connectedNode].bWaterPath) continue;
+ if ((m_pathNodes[connectedNode].GetPosition() - m_pathNodes[i].GetPosition()).Magnitude() > minDist) {
closestDist = dist;
closestNode = i;
+ closestConnectedNode = connectedNode;
}
}
- break;
}
}
- return closestNode;
+ if (closestDist < maxDist) {
+ *node1 = closestNode;
+ *node2 = closestConnectedNode;
+ CVector dir(m_pathNodes[*node2].GetX() - m_pathNodes[*node1].GetX(), m_pathNodes[*node2].GetY() - m_pathNodes[*node1].GetY(), 0.0f);
+ dir.Normalise();
+ *angle = RADTODEG(Atan2(-dir.x, dir.y));
+ }
+ else {
+ *node1 = -1;
+ *node2 = -1;
+ *angle = 0.0f;
+ }
+}
+
+int32
+CPathFind::FindNthNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, int N, bool bWaterPath)
+{
+ int i;
+ int firstNode, lastNode;
+ switch (type) {
+ case PATH_CAR:
+ firstNode = 0;
+ lastNode = m_numCarPathNodes;
+ break;
+ case PATH_PED:
+ firstNode = m_numCarPathNodes;
+ lastNode = m_numPathNodes;
+ break;
+ }
+ for (i = firstNode; i < lastNode; i++)
+ m_pathNodes[i].bSelected = false;
+
+ for (; N > 0; N--) {
+ i = FindNodeClosestToCoors(coors, type, distLimit, ignoreDisabled, ignoreBetweenLevels, true, bWaterPath);
+ if (i < 0)
+ return -1;
+ m_pathNodes[i].bSelected = true;
+ }
+ return FindNodeClosestToCoors(coors, type, distLimit, ignoreDisabled, ignoreBetweenLevels, true, bWaterPath);
+}
+
+CVector
+CPathFind::FindNodeCoorsForScript(int32 id)
+{
+ // the point is to return valid position in case there is a divider in the middle of the road
+ if (!m_pathNodes[id].HasDivider() || m_pathNodes[id].numLinks == 0)
+ return m_pathNodes[id].GetPosition();
+ CVector2D dir(m_pathNodes[ConnectedNode(m_pathNodes[id].firstLink)].GetX() - m_pathNodes[id].GetX(),
+ m_pathNodes[ConnectedNode(m_pathNodes[id].firstLink)].GetY() - m_pathNodes[id].GetY());
+ dir.Normalise();
+ if (dir.x < 0)
+ dir = -dir;
+ return m_pathNodes[id].GetPosition() + CVector(-dir.y, dir.x, 0.0f) * (LANE_WIDTH / 2 + m_pathNodes[id].GetDividerWidth());
}
float
@@ -1278,7 +1470,7 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo
}
bool
-CPathFind::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)
+CPathFind::GenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled)
{
int i, j;
int node1, node2;
@@ -1292,14 +1484,14 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY,
if(m_pathNodes[node1].bDisabled && !ignoreDisabled)
continue;
dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y);
- if(dist1 < spawnDist + 60.0f){
- d1 = dist1 - spawnDist;
+ if(dist1 < Max(spawnDist + 70.0f, spawnDist * 1.7f)){
+ d1 = m_pathNodes[node1].bWaterPath ? (dist1 - spawnDist * 1.5f) : (dist1 - spawnDist);
for(j = 0; j < m_pathNodes[node1].numLinks; j++){
node2 = ConnectedNode(m_pathNodes[node1].firstLink + j);
if(m_pathNodes[node2].bDisabled && !ignoreDisabled)
continue;
dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y);
- d2 = dist2 - spawnDist;
+ d2 = m_pathNodes[node2].bWaterPath ? (dist2 - spawnDist * 1.5f) : (dist2 - spawnDist);
if(d1*d2 < 0.0f){
// nodes are on different sides of spawn distance
float f2 = Abs(d1)/(Abs(d1) + Abs(d2));
@@ -1336,94 +1528,76 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi
{
int i;
int node1, node2;
+ float node1_dist, node2_dist;
+ static int32 node_cnt;
if(m_numPedPathNodes == 0)
return false;
- for(i = 0; i < 400; i++){
- node1 = m_numCarPathNodes + CGeneral::GetRandomNumber() % m_numPedPathNodes;
- if(DistanceSqr2D(m_pathNodes[node1].GetPosition(), x, y) < sq(maxDist+30.0f)){
- if(m_pathNodes[node1].numLinks == 0)
- continue;
- int link = m_pathNodes[node1].firstLink + CGeneral::GetRandomNumber() % m_pathNodes[node1].numLinks;
- if(ConnectionCrossesRoad(link))
- continue;
- node2 = ConnectedNode(link);
- if(m_pathNodes[node1].bDisabled || m_pathNodes[node2].bDisabled)
- continue;
-
- float f2 = (CGeneral::GetRandomNumber()&0xFF)/256.0f;
- float f1 = 1.0f - f2;
- *pPositionBetweenNodes = f2;
- CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2;
- if(Distance2D(pos, x, y) < maxDist+20.0f){
- pos.x += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;
- pos.y += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;
- float dist = Distance2D(pos, x, y);
-
- bool visible;
- if(camMatrix)
- visible = TheCamera.IsSphereVisible(pos, 2.0f, camMatrix);
- else
- visible = TheCamera.IsSphereVisible(pos, 2.0f);
- if(!visible){
- minDist = minDistOffScreen;
- maxDist = maxDistOffScreen;
- }
- if(minDist < dist && dist < maxDist){
- *pNode1 = node1;
- *pNode2 = node2;
- *pPosition = pos;
-
- bool found;
- float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z+2.0f, &found);
- if(!found)
- return false;
- if(Abs(groundZ - pos.z) > 3.0f)
- return false;
- pPosition->z = groundZ;
- return true;
- }
- }
+ for(i = 0; i < 230; i++){
+ if (node_cnt++ >= m_numPedPathNodes)
+ node_cnt = 0;
+ node1 = node_cnt + m_numCarPathNodes;
+ node1_dist = Distance2D(m_pathNodes[node1].GetPosition(), x, y);
+ if(node1_dist < maxDist+30.0f){
+ if(m_pathNodes[node1].numLinks != 0)
+ break;
}
}
- return false;
-}
-
-CTreadable*
-CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type)
-{
- int i, j, k;
- int node1, node2;
- CTreadable *closestMapObj = nil;
- float closestDist = 10000.0f;
+ if (i >= 230)
+ return false;
- for(i = 0; i < m_numMapObjects; i++){
- CTreadable *mapObj = m_mapObjects[i];
- if(mapObj->m_nodeIndices[type][0] < 0)
+ for(i = 0; i < m_pathNodes[node1].numLinks; i++){
+ int link = m_pathNodes[node1].firstLink + i;
+ if(ConnectionCrossesRoad(link))
continue;
- CVector vDist = mapObj->GetPosition() - coors;
- float fDist = Abs(vDist.x) + Abs(vDist.y) + Abs(vDist.z);
- if(fDist < 200.0f || fDist < closestDist)
- for(j = 0; j < 12; j++){
- node1 = mapObj->m_nodeIndices[type][j];
- if(node1 < 0)
- break;
- // FIX: game uses ThePaths here explicitly
- for(k = 0; k < m_pathNodes[node1].numLinks; k++){
- node2 = ConnectedNode(m_pathNodes[node1].firstLink + k);
- float lineDist = CCollision::DistToLine(&m_pathNodes[node1].GetPosition(), &m_pathNodes[node2].GetPosition(), &coors);
- if(lineDist < closestDist){
- closestDist = lineDist;
- if((coors - m_pathNodes[node1].GetPosition()).MagnitudeSqr() < (coors - m_pathNodes[node2].GetPosition()).MagnitudeSqr())
- closestMapObj = m_mapObjects[m_pathNodes[node1].objectIndex];
- else
- closestMapObj = m_mapObjects[m_pathNodes[node2].objectIndex];
- }
- }
+ node2 = ConnectedNode(link);
+ if(m_pathNodes[node1].bDisabled || m_pathNodes[node2].bDisabled)
+ continue;
+ node2_dist = Distance2D(m_pathNodes[node2].GetPosition(), x, y);
+ if ((node1_dist < maxDist || node2_dist < maxDist) && (node1_dist > minDistOffScreen || node2_dist > minDistOffScreen))
+ break;
+ }
+ if(i >= m_pathNodes[node1].numLinks)
+ return false;
+
+ for(i = 0; i < 5; i++){
+ float f2 = (CGeneral::GetRandomNumber()&0xFF)/256.0f;
+ float f1 = 1.0f - f2;
+ *pPositionBetweenNodes = f2;
+ CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2;
+ if(Distance2D(pos, x, y) < maxDist+20.0f){
+ pos.x += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;
+ pos.y += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;
+ float dist = Distance2D(pos, x, y);
+
+ bool visible;
+ if(camMatrix)
+ visible = TheCamera.IsSphereVisible(pos, 2.0f, camMatrix);
+ else
+ visible = TheCamera.IsSphereVisible(pos, 2.0f);
+ if(!visible){
+ minDist = minDistOffScreen;
+ maxDist = maxDistOffScreen;
+ }
+ if(visible && (minDist < dist && dist < maxDist) ||
+ !visible && (minDistOffScreen < dist && dist < maxDistOffScreen)){
+ *pNode1 = node1;
+ *pNode2 = node2;
+ *pPosition = pos;
+
+ bool found;
+ float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z+2.0f, &found);
+ if(!found)
+ return false;
+ if(Abs(groundZ - pos.z) > 3.0f)
+ return false;
+ pPosition->z = groundZ;
+ return true;
}
+ }
}
- return closestMapObj;
+ return false;
}
void
@@ -1433,19 +1607,8 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
CPathNode *node;
if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->GetPosition()).MagnitudeSqr() > 7.0f){
- // need to find the node we're coming from
- node = nil;
- CTreadable *obj = FindRoadObjectClosestToCoors(coors, type);
- float nodeDist = 1000000000.0f;
- for(i = 0; i < 12; i++){
- if(obj->m_nodeIndices[type][i] < 0)
- break;
- float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].GetPosition()).MagnitudeSqr();
- if(dist < nodeDist){
- nodeDist = dist;
- node = &m_pathNodes[obj->m_nodeIndices[type][i]];
- }
- }
+ int32 nodeIdx = FindNodeClosestToCoors(coors, type, 999999.88f);
+ node = &m_pathNodes[nodeIdx];
}
CVector2D vCurDir(Sin(curDir*PI/4.0f), Cos(curDir * PI / 4.0f));
@@ -1501,7 +1664,7 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
}
}
-static CPathNode *apNodesToBeCleared[4995];
+static CPathNode *apNodesToBeCleared[6525];
void
CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId)
@@ -1518,42 +1681,22 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
}
// Find start
- int numPathsToTry;
- CTreadable *startObj;
- if(startNodeId < 0){
- if(vehicle == nil || (startObj = vehicle->m_treadable[type]) == nil)
- startObj = FindRoadObjectClosestToCoors(start, type);
- numPathsToTry = 0;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNodeId].group)
- numPathsToTry++;
- }
- }else{
- numPathsToTry = 1;
- startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex];
- }
- if(numPathsToTry == 0) {
+ if(startNodeId < 0)
+ startNodeId = FindNodeClosestToCoors(start, type, 999999.88f);
+ if(startNodeId < 0) {
*pNumNodes = 0;
if(pDist) *pDist = 100000.0f;
return;
}
-
- if(startNodeId < 0){
- // why only check node 0?
- if(m_pathNodes[startObj->m_nodeIndices[type][0]].group !=
- m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
- }else{
- if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
+ if(startNodeId == targetNodeId){
+ *pNumNodes = 0;
+ if(pDist) *pDist = 0.0f;
+ return;
+ }
+ if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
+ *pNumNodes = 0;
+ if(pDist) *pDist = 100000.0f;
+ return;
}
for(i = 0; i < ARRAY_SIZE(m_searchNodes); i++)
@@ -1565,14 +1708,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Dijkstra's algorithm
// Find distances
int numPathsFound = 0;
- if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNodeId].objectIndex] == startObj)
- numPathsFound++;
- for(i = 0; numPathsFound < numPathsToTry; i = (i+1) & 0x1FF){
+ for(i = 0; numPathsFound == 0; i = (i+1) & 0x1FF){
CPathNode *node;
for(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){
- if(m_mapObjects[node->objectIndex] == startObj &&
- (startNodeId < 0 || node == &m_pathNodes[startNodeId]))
- numPathsFound++;
+ if(node == &m_pathNodes[startNodeId])
+ numPathsFound = 1;
for(j = 0; j < node->numLinks; j++){
int next = ConnectedNode(node->firstLink + j);
@@ -1592,34 +1732,12 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Find out whence to start tracing back
CPathNode *curNode;
- if(startNodeId < 0){
- int minDist = MAX_DIST;
- *pNumNodes = 1;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].GetPosition() - start).Magnitude();
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist < minDist){
- minDist = m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist;
- curNode = &m_pathNodes[startObj->m_nodeIndices[type][i]];
- }
- }
- if(maxNumNodes == 0){
- *pNumNodes = 0;
- }else{
- nodes[0] = curNode;
- *pNumNodes = 1;
- }
- if(pDist)
- *pDist = minDist;
- }else
- {
- curNode = &m_pathNodes[startNodeId];
- *pNumNodes = 0;
- if(pDist)
- *pDist = m_pathNodes[startNodeId].distance;
- }
+ curNode = &m_pathNodes[startNodeId];
+ *pNumNodes = 0;
+ if(pDist)
+ *pDist = m_pathNodes[startNodeId].distance;
+ nodes[(*pNumNodes)++] = curNode;
// Trace back to target and update list of nodes
while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId])
for(i = 0; i < curNode->numLinks; i++){
@@ -1633,7 +1751,6 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
for(i = 0; i < numNodesToBeCleared; i++)
apNodesToBeCleared[i]->distance = MAX_DIST;
- return;
}
static CPathNode *pNodeList[32];
@@ -1652,12 +1769,12 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
#ifdef FIX_BUGS
// dist has GenerationDistMultiplier as a factor, so our reference dist should have it too
if(type == PATH_CAR)
- return dist < 160.0f*TheCamera.GenerationDistMultiplier;
+ return dist < 150.0f*TheCamera.GenerationDistMultiplier;
else
return dist < 100.0f*TheCamera.GenerationDistMultiplier;
#else
if(type == PATH_CAR)
- return dist < 160.0f;
+ return dist < 150.0f;
else
return dist < 100.0f;
#endif
@@ -1701,6 +1818,12 @@ CPathFind::Load(uint8 *buf, uint32 size)
m_pathNodes[i].bBetweenLevels = true;
else
m_pathNodes[i].bBetweenLevels = false;
+
+#ifdef SECUROM
+ // if pirated game
+ for(i = 0; i < m_numPathNodes; i++)
+ m_pathNodes[i].bDisabled = true;
+#endif
}
void
@@ -1828,3 +1951,39 @@ CPathFind::DisplayPathData(void)
}
}
}
+
+CVector
+CPathFind::TakeWidthIntoAccountForWandering(CPathNode* nextNode, uint16 random)
+{
+ CVector pos = nextNode->GetPosition();
+ float newX = (nextNode->GetPedNodeWidth() * ((random % 16) - 7)) + pos.x;
+ float newY = (nextNode->GetPedNodeWidth() * (((random / 16) % 16) - 7)) + pos.y;
+ return CVector(newX, newY, pos.z);
+}
+
+void
+CPathFind::TakeWidthIntoAccountForCoors(CPathNode* node1, CPathNode* node2, uint16 random, float* x, float* y)
+{
+ *x += (Min(node1->width, node2->width) * WIDTH_TO_PED_NODE_WIDTH * ((random % 16) - 7));
+ *y += (Min(node1->width, node2->width) * WIDTH_TO_PED_NODE_WIDTH * (((random / 16) % 16) - 7));
+}
+
+CPathNode*
+CPathFind::GetNode(int16 index)
+{
+ if(index < 0)
+ return nil;
+ if(index < ARRAY_SIZE(ThePaths.m_searchNodes))
+ return &ThePaths.m_searchNodes[index];
+ return &ThePaths.m_pathNodes[index - ARRAY_SIZE(ThePaths.m_searchNodes)];
+}
+int16
+CPathFind::GetIndex(CPathNode *node)
+{
+ if(node == nil)
+ return -1;
+ if(node >= &ThePaths.m_searchNodes[0] && node < &ThePaths.m_searchNodes[ARRAY_SIZE(ThePaths.m_searchNodes)])
+ return node - ThePaths.m_searchNodes;
+ else
+ return (node - ThePaths.m_pathNodes) + ARRAY_SIZE(ThePaths.m_searchNodes);
+}
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index bbfdf7b7..99759590 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -5,13 +5,13 @@
class CVehicle;
class CPtrList;
+#define LANE_WIDTH 5.0f
+#define WIDTH_TO_PED_NODE_WIDTH (31.f/(500.f * 8.f))
+
enum
{
NodeTypeExtern = 1,
NodeTypeIntern = 2,
-
- UseInRoadBlock = 1,
- ObjectEastWest = 2,
};
enum
@@ -52,35 +52,51 @@ public:
static void AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList);
static void AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition);
static void AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition);
+ static void AddBuildingBlockade(CEntity*, CPedPathNode(*)[40], CVector*);
+ static void AddBuildingBlockadeSectorList(CPtrList&, CPedPathNode(*)[40], CVector*);
};
struct CPathNode
{
- CVector pos;
- CPathNode *prev;
- CPathNode *next;
+ int16 prevIndex;
+ int16 nextIndex;
+ int16 x;
+ int16 y;
+ int16 z;
int16 distance; // in path search
- int16 objectIndex;
int16 firstLink;
- uint8 numLinks;
+ uint8 width;
+ int8 group;
- uint8 unkBits : 2;
+ uint8 numLinks : 4;
uint8 bDeadEnd : 1;
uint8 bDisabled : 1;
uint8 bBetweenLevels : 1;
-
- int8 group;
-
- CVector &GetPosition(void) { return pos; }
- void SetPosition(const CVector &p) { pos = p; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetZ(void) { return pos.z; }
-
- CPathNode *GetPrev(void) { return prev; }
- CPathNode *GetNext(void) { return next; }
- void SetPrev(CPathNode *node) { prev = node; }
- void SetNext(CPathNode *node) { next = node; }
+ uint8 bUseInRoadBlock : 1;
+
+ uint8 bWaterPath : 1;
+ uint8 bOnlySmallBoats : 1;
+ uint8 bSelected : 1;
+ 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; }
+ bool HasDivider(void) { return width != 0; }
+ float GetDividerWidth(void) { return width/(2*8.0f); }
+ float GetPedNodeWidth(void) { return width*WIDTH_TO_PED_NODE_WIDTH; }
+ CPathNode *GetPrev(void);
+ CPathNode *GetNext(void);
+ void SetPrev(CPathNode *node);
+ void SetNext(CPathNode *node);
};
union CConnectionFlags
@@ -94,22 +110,25 @@ union CConnectionFlags
struct CCarPathLink
{
- CVector2D pos;
- CVector2D dir;
+ int16 x;
+ int16 y;
int16 pathNodeIndex;
- int8 numLeftLanes;
- int8 numRightLanes;
- uint8 trafficLightType;
-
- uint8 bBridgeLights : 1;
- // more?
-
- CVector2D &GetPosition(void) { return pos; }
- CVector2D &GetDirection(void) { return dir; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetDirX(void) { return dir.x; }
- float GetDirY(void) { return dir.y; }
+ int8 dirX;
+ int8 dirY;
+ int8 numLeftLanes : 3;
+ int8 numRightLanes : 3;
+ uint8 trafficLightDirection : 1;
+ uint8 trafficLightType : 2;
+ uint8 bBridgeLights : 1; // at least in LCS...
+ uint8 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; }
+ float GetLaneOffset(void) { return width/(2*8.0f*LANE_WIDTH); }
float OneWayLaneOffset()
{
@@ -117,21 +136,34 @@ struct CCarPathLink
return 0.5f - 0.5f * numRightLanes;
if (numRightLanes == 0)
return 0.5f - 0.5f * numLeftLanes;
- return 0.5f;
+ return 0.5f + GetLaneOffset();
}
};
// This is what we're reading from the files, only temporary
struct CPathInfoForObject
{
- int16 x;
- int16 y;
- int16 z;
+ float x;
+ float y;
+ float z;
int8 type;
int8 next;
int8 numLeftLanes;
int8 numRightLanes;
+ int8 speedLimit;
+ uint8 width;
+
uint8 crossing : 1;
+ uint8 onlySmallBoats : 1;
+ uint8 roadBlock : 1;
+ uint8 disabled : 1;
+ uint8 waterPath : 1;
+ uint8 betweenLevels : 1;
+
+ uint8 spawnRate : 4;
+
+ void CheckIntegrity(void);
+ void SwapConnectionsToBeRightWayRound(void);
};
extern CPathInfoForObject *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds;
@@ -139,30 +171,43 @@ extern CPathInfoForObject *InfoForTilePeds;
struct CTempNode
{
CVector pos;
- float dirX;
- float dirY;
+ int8 dirX; // *100
+ int8 dirY;
int16 link1;
int16 link2;
int8 numLeftLanes;
int8 numRightLanes;
+ uint8 width;
+ bool isCross;
int8 linkState;
};
-struct CTempDetachedNode // unused
+struct CTempNodeExternal // made up name
+{
+ CVector pos;
+ int16 next;
+ int8 numLeftLanes;
+ int8 numRightLanes;
+ uint8 width;
+ bool isCross;
+};
+
+// from mobile
+template<typename T>
+class CRoute
{
- uint8 foo[20];
+ T m_node[8];
};
+
class CPathFind
{
public:
CPathNode m_pathNodes[NUM_PATHNODES];
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
CTreadable *m_mapObjects[NUM_MAPOBJECTS];
- uint8 m_objectFlags[NUM_MAPOBJECTS];
- int16 m_connections[NUM_PATHCONNECTIONS];
- int16 m_distances[NUM_PATHCONNECTIONS];
- CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS];
+ uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags
+ uint8 m_distances[NUM_PATHCONNECTIONS];
int16 m_carPathConnections[NUM_PATHCONNECTIONS];
int32 m_numPathNodes;
@@ -178,14 +223,19 @@ public:
void Init(void);
void AllocatePathFindInfoMem(int16 numPathGroups);
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);
- void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out);
+ void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate);
+ void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate);
+ void StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate);
+ void StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk);
+ void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);
bool LoadPathFindData(void);
void PreparePathData(void);
void CountFloodFillGroups(uint8 type);
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int32 numDetached);
+ float maxdist, CPathInfoForObject *detachednodes, int32 numDetached);
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
@@ -203,30 +253,52 @@ 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);
- int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false);
+ int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreSelected = false, bool bWaterPath = false);
int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
+ void FindNodePairClosestToCoors(CVector coors, uint8 type, int* node1, int* node2, float* angle, float minDist, float maxDist, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool bWaterPath = false);
+ int32 FindNthNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, int N, bool bWaterPath = false);
+ CVector FindNodeCoorsForScript(int32 id);
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 GenerateCarCreationCoors(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);
- CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type);
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);
- 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; }
+
+ static CVector TakeWidthIntoAccountForWandering(CPathNode*, uint16);
+ static void TakeWidthIntoAccountForCoors(CPathNode*, CPathNode*, uint16, float*, float*);
+
+ 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; }
void DisplayPathData(void);
-};
-VALIDATE_SIZE(CPathFind, 0x49bf4);
+ // Following methods are present on mobile but are unused. TODO: implement them
+ void SavePathFindData(void);
+ void ComputeRoute(uint8, const CVector&, const CVector&, CRoute<CPathNode*>&);
+ void RecordNodesClosestToCoors(CVector, uint8, int, CPathNode**, float, bool, bool, bool);
+ void RecordNodesInCircle(const CVector&, float, uint8, int, CPathNode**, bool, bool, bool, bool);
+ void ArrangeOneNodeList(CPathInfoForObject*, int16);
+ void ArrangeNodes(int16);
+ void RegisterMarker(CVector*);
+ void Shutdown(void);
+};
extern CPathFind ThePaths;
+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); }
+
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;
diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp
index 7632cfa3..41f9d766 100644
--- a/src/control/Phones.cpp
+++ b/src/control/Phones.cpp
@@ -41,16 +41,6 @@ CPed *CPhoneInfo::pCallBackPed; // ped who picking up the phone (reset after pic
after 60 seconds of last phone pick-up.
*/
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-CPed* crimeReporters[NUMPHONES] = {};
-bool
-isPhoneAvailable(int m_phoneId)
-{
- return crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_WAIT_ON_FOOT ||
- (crimeReporters[m_phoneId]->m_nPedState != PED_MAKE_CALL && crimeReporters[m_phoneId]->m_nPedState != PED_FACE_PHONE && crimeReporters[m_phoneId]->m_nPedState != PED_SEEK_POS);
-}
-#endif
-
void
CPhoneInfo::Update(void)
{
@@ -167,14 +157,9 @@ CPhoneInfo::FindNearestFreePhone(CVector *pos)
int nearestPhoneId = -1;
float nearestPhoneDist = 60.0f;
- for (int phoneId = 0; phoneId < m_nMax; phoneId++) {
+ for (int phoneId = 0; phoneId < m_nMax; phoneId++) {
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (isPhoneAvailable(phoneId))
-#else
- if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE)
-#endif
- {
+ if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE) {
float phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D();
if (phoneDist < nearestPhoneDist) {
@@ -215,81 +200,32 @@ CPhoneInfo::IsMessageBeingDisplayed(int phoneId)
return pPhoneDisplayingMessages == &m_aPhones[phoneId];
}
-#ifdef COMPATIBLE_SAVES
-static inline void
-LoadPhone(CPhone &phone, uint8 *&buf)
-{
- ReadSaveBuf(&phone.m_vecPos, buf);
- SkipSaveBuf(buf, 6 * 4);
- ReadSaveBuf<uint32>(&phone.m_repeatedMessagePickupStart, buf);
- uint32 tmp;
- ReadSaveBuf(&tmp, buf);
- phone.m_pEntity = (CEntity*)(uintptr)tmp;
- ReadSaveBuf<PhoneState>(&phone.m_nState, buf);
- ReadSaveBuf<bool>(&phone.m_visibleToCam, buf);
- SkipSaveBuf(buf, 3);
-}
-#endif
-
void
CPhoneInfo::Load(uint8 *buf, uint32 size)
{
INITSAVEBUF
- int32 max, scriptPhonesMax;
- ReadSaveBuf(&max, buf);
- ReadSaveBuf(&scriptPhonesMax, buf);
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- m_nMax = Min(NUMPHONES, max);
- m_nScriptPhonesMax = 0;
-
- bool ignoreOtherPhones = false;
-
- // We can do it without touching saves. We'll only load script phones, others are already loaded in Initialise
- for (int i = 0; i < 50; i++) {
- CPhone phoneToLoad;
-#ifdef COMPATIBLE_SAVES
- phoneToLoad.m_apMessages[0]=phoneToLoad.m_apMessages[1]=phoneToLoad.m_apMessages[2]=phoneToLoad.m_apMessages[3]=phoneToLoad.m_apMessages[4]=phoneToLoad.m_apMessages[5] = nil;
- LoadPhone(phoneToLoad, buf);
-#else
- ReadSaveBuf(&phoneToLoad, buf);
-#endif
-
- if (ignoreOtherPhones)
- continue;
-
- if (i < scriptPhonesMax) {
- if (i >= m_nMax) {
- assert(0 && "Number of phones used by script exceeds the NUMPHONES or the stored phones in save file. Ignoring some phones");
- ignoreOtherPhones = true;
- continue;
- }
- SwapPhone(phoneToLoad.m_vecPos.x, phoneToLoad.m_vecPos.y, i);
-
- m_aPhones[i] = phoneToLoad;
- // It's saved as building pool index in save file, convert it to true entity
- if (m_aPhones[i].m_pEntity) {
- m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1);
- }
- } else
- ignoreOtherPhones = true;
- }
-#else
- m_nMax = max;
- m_nScriptPhonesMax = scriptPhonesMax;
-
+ ReadSaveBuf(&m_nMax, buf);
+ ReadSaveBuf(&m_nScriptPhonesMax, buf);
for (int i = 0; i < NUMPHONES; i++) {
#ifdef COMPATIBLE_SAVES
- LoadPhone(m_aPhones[i], buf);
+ ReadSaveBuf(&m_aPhones[i].m_vecPos, buf);
+ SkipSaveBuf(buf, 6 * 4);
+ ReadSaveBuf(&m_aPhones[i].m_repeatedMessagePickupStart, buf);
+ int32 tmp;
+ ReadSaveBuf(&tmp, buf);
+ // It's saved as building pool index in save file, convert it to true entity
+ m_aPhones[i].m_pEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil;
+ ReadSaveBuf(&m_aPhones[i].m_nState, buf);
+ ReadSaveBuf(&m_aPhones[i].m_visibleToCam, buf);
+ SkipSaveBuf(buf, 3);
#else
ReadSaveBuf(&m_aPhones[i], buf);
-#endif
// It's saved as building pool index in save file, convert it to true entity
if (m_aPhones[i].m_pEntity) {
m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1);
}
- }
#endif
+ }
VALIDATESAVEBUF(size)
}
@@ -327,31 +263,6 @@ CPhoneInfo::SetPhoneMessage_Repeatedly(int phoneId, wchar *msg1, wchar *msg2, wc
}
}
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-void
-CPhoneInfo::SwapPhone(float xPos, float yPos, int into)
-{
- // "into" should be in 0 - m_nScriptPhonesMax range
- int nearestPhoneId = -1;
- CVector pos(xPos, yPos, 0.0f);
- float nearestPhoneDist = 1.0f;
-
- for (int phoneId = m_nScriptPhonesMax; phoneId < m_nMax; phoneId++) {
- float phoneDistance = (m_aPhones[phoneId].m_vecPos - pos).Magnitude2D();
- if (phoneDistance < nearestPhoneDist) {
- nearestPhoneDist = phoneDistance;
- nearestPhoneId = phoneId;
- }
- }
- m_aPhones[nearestPhoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED;
-
- CPhone oldPhone = m_aPhones[into];
- m_aPhones[into] = m_aPhones[nearestPhoneId];
- m_aPhones[nearestPhoneId] = oldPhone;
- m_nScriptPhonesMax++;
-}
-#endif
-
int
CPhoneInfo::GrabPhone(float xPos, float yPos)
{
@@ -411,11 +322,7 @@ CPhoneInfo::Save(uint8 *buf, uint32 *size)
INITSAVEBUF
WriteSaveBuf(buf, m_nMax);
WriteSaveBuf(buf, m_nScriptPhonesMax);
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- for (int phoneId = 0; phoneId < 50; phoneId++) { // We can do it without touching saves
-#else
- for (int phoneId = 0; phoneId < NUMPHONES; phoneId++) {
-#endif
+ for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) {
#ifdef COMPATIBLE_SAVES
WriteSaveBuf(buf, m_aPhones[phoneId].m_vecPos);
ZeroSaveBuf(buf, 6 * 4);
diff --git a/src/control/Phones.h b/src/control/Phones.h
index 02c9a928..81b40dc2 100644
--- a/src/control/Phones.h
+++ b/src/control/Phones.h
@@ -61,17 +61,9 @@ public:
void Initialise(void);
void Shutdown(void);
void Update(void);
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- void SwapPhone(float xPos, float yPos, int into);
-#endif
};
extern CPhoneInfo gPhoneInfo;
void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg);
-void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg);
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-extern CPed *crimeReporters[NUMPHONES];
-bool isPhoneAvailable(int);
-#endif
+void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); \ No newline at end of file
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 8d3472ea..f6b1a9b9 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -31,9 +31,13 @@
#include "Timer.h"
#include "WaterLevel.h"
#include "World.h"
+#include "Hud.h"
+#include "Messages.h"
+#include "Streaming.h"
+#include "SaveBuf.h"
#ifdef COMPATIBLE_SAVES
-#define PICKUPS_SAVE_SIZE 0x24C0
+#define PICKUPS_SAVE_SIZE 0x4440
#else
#define PICKUPS_SAVE_SIZE sizeof(aPickUps)
#endif
@@ -43,6 +47,9 @@ int16 CPickups::NumMessages;
int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];
int16 CPickups::CollectedPickUpIndex;
+int32 CPickups::PlayerOnWeaponPickup;
+int32 CollectPickupBuffer;
+
// unused
bool CPickups::bPickUpcamActivated;
CVehicle *CPickups::pPlayerVehicle;
@@ -51,38 +58,154 @@ uint32 CPickups::StaticCamStartTime;
tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
-// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
-uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
-uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
-uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
+uint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 8, 68, 24,
+ 32, 28, 20, 200, 120, 120, 120, 120, 120, 40, 28, 8, 300, 200, 1000, 1, 400, 36, 0 };
-uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
-uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
-uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
-float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
+uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 34, 12,
+ 16, 14, 10, 100, 60, 60, 60, 60, 60, 20, 14, 4, 150, 100, 500, 1, 400, 36, 0 };
+uint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3] = { 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1000, 1000,
+ 1000, 500, 8000, 250, 400, 1200, 1250, 1250, 800, 800, 650, 1200, 5000, 400,
+ 10000, 10000, 8000, 8000, 8000, 10000, 1000, 11000, 500, 20, 10, 0 };
-inline void
-CPickup::Remove()
+struct
+{
+ uint8 r,g,b;
+ float unk;
+} aPickupColors[] = {
+ { 128, 128, 128, 1.0f },
+ { 128, 128, 128, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 97, 194, 247, 1.0f },
+ { 27, 89, 130, 1.0f },
+ { 27, 89, 130, 1.0f },
+ { 27, 89, 130, 1.0f },
+ { 27, 89, 130, 1.0f },
+ { 27, 89, 130, 1.0f },
+ { 149, 194, 24, 1.0f },
+ { 149, 194, 24, 1.0f },
+ { 45, 155, 90, 1.0f },
+ { 45, 155, 90, 1.0f },
+ { 45, 155, 90, 1.0f },
+ { 255, 227, 79, 1.0f },
+ { 255, 227, 79, 1.0f },
+ { 255, 227, 79, 1.0f },
+ { 255, 227, 79, 1.0f },
+ { 254, 137, 0, 1.0f },
+ { 254, 137, 0, 1.0f },
+ { 249, 131, 215, 1.0f },
+ { 249, 131, 215, 1.0f },
+ { 164, 40, 178, 1.0f },
+ { 164, 40, 178, 1.0f },
+ { 164, 40, 178, 1.0f },
+ { 164, 40, 178, 1.0f },
+ { 69, 69, 69, 1.0f },
+ { 69, 69, 69, 1.0f },
+ { 69, 69, 69, 1.0f },
+ { 255, 100, 100, 1.0f },
+ { 128, 255, 128, 1.0f },
+ { 100, 100, 255, 1.0f },
+ { 255, 255, 100, 1.0f },
+ { 255, 100, 100, 1.0f },
+ { 100, 255, 100, 1.0f },
+ { 255, 255, 255, 1.0f }
+};
+
+
+void
+ModifyStringLabelForControlSetting(char *str)
+{
+ int len = (int)strlen(str);
+ if (len <= 2)
+ return;
+
+ if (str[len - 2] != '_')
+ return;
+
+ switch (CPad::GetPad(0)->Mode) {
+ case 0:
+ case 1:
+ str[len - 1] = 'L';
+ break;
+ case 2:
+ str[len - 1] = 'T';
+ break;
+ case 3:
+ str[len - 1] = 'C';
+ break;
+ default:
+ return;
+ }
+}
+
+void
+CPickup::ExtractAmmoFromPickup(CPlayerPed *player)
{
- CWorld::Remove(m_pObject);
- delete m_pObject;
+ eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());
+
+ if (m_eType == PICKUP_IN_SHOP || !CWeaponInfo::IsWeaponSlotAmmoMergeable(CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot))
+ return;
+ uint32 ammo = m_nQuantity;
+ if (ammo == 0) {
+ if (!m_bWasAmmoCollected)
+ ammo = AmmoForWeapon_OnStreet[weaponType];
+ else
+ goto removeAmmo;
+ }
+ player->GrantAmmo(weaponType, ammo);
+ DMAudio.PlayOneShot(player->m_audioEntityId, SOUND_WEAPON_RELOAD, weaponType); // BUG? weapon type as volume, wtf?
+removeAmmo:
+ m_nQuantity = 0;
+ m_bWasAmmoCollected = true;
+}
+
+void
+CPickup::Remove()
+{
+ GetRidOfObjects();
m_bRemoved = true;
- m_pObject = nil;
m_eType = PICKUP_NONE;
}
CObject *
-CPickup::GiveUsAPickUpObject(int32 handle)
+CPickup::GiveUsAPickUpObject(CObject **ppObject, CObject **ppExtraObject, int32 handle, int32 extraHandle)
{
- CObject *object;
+ CObject *&object = *ppObject;
+ CObject *&extraObject = *ppExtraObject;
+
+ object = extraObject = nil;
+
+ int32 modelId = -1;
+ if (CModelInfo::GetModelInfo(m_eModelIndex)->GetModelType() == MITYPE_WEAPON) {
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(((CWeaponModelInfo*)CModelInfo::GetModelInfo(m_eModelIndex))->GetWeaponInfo());
+ modelId = weaponInfo->m_nModelId;
+ if (modelId == m_eModelIndex)
+ modelId = weaponInfo->m_nModel2Id;
+ }
if (handle >= 0) {
CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
- object = new (handle) CObject(m_eModelIndex, false);
- } else
+ if (extraHandle >= 0)
+ CPools::MakeSureSlotInObjectPoolIsEmpty(extraHandle);
+ if (object == nil)
+ object = new(handle) CObject(m_eModelIndex, false);
+
+ if (extraHandle >= 0 && modelId != -1 && extraObject == nil)
+ extraObject = new(extraHandle) CObject(modelId, false);
+ } else {
object = new CObject(m_eModelIndex, false);
+ if (modelId != -1)
+ extraObject = new CObject(modelId, false);
+ }
if (object == nil) return nil;
object->ObjectCreatedBy = MISSION_OBJECT;
@@ -95,14 +218,38 @@ CPickup::GiveUsAPickUpObject(int32 handle)
object->bExplosionProof = true;
object->bUsesCollision = false;
object->bIsPickup = true;
+ object->bAmmoCollected = m_bWasAmmoCollected;
+ object->bHasPreRenderEffects = true;
+
+ if (extraObject) {
+ extraObject->ObjectCreatedBy = MISSION_OBJECT;
+ extraObject->SetPosition(m_vecPos);
+ extraObject->SetOrientation(0.0f, 0.0f, -HALFPI);
+ extraObject->GetMatrix().UpdateRW();
+ extraObject->UpdateRwFrame();
+
+ extraObject->bAffectedByGravity = false;
+ extraObject->bExplosionProof = true;
+ extraObject->bUsesCollision = false;
+ extraObject->bIsPickup = true;
+ extraObject->bAmmoCollected = true;
+ extraObject->bHasPreRenderEffects = true;
+ extraObject->m_nBonusValue = 0;
+ extraObject->bPickupObjWithMessage = false;
+ extraObject->bOutOfStock = false;
+ }
- object->m_nBonusValue = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
+ object->m_nBonusValue = (m_eModelIndex == MI_PICKUP_BONUS || m_eModelIndex == MI_PICKUP_CLOTHES) ? m_nQuantity : 0;
switch (m_eType)
{
case PICKUP_IN_SHOP:
object->bPickupObjWithMessage = true;
object->bOutOfStock = false;
+ if (m_eModelIndex == MI_PICKUP_HEALTH || m_eModelIndex == MI_PICKUP_ADRENALINE)
+ object->m_nCostValue = 0;
+ else
+ object->m_nCostValue = CostOfWeapon[CPickups::WeaponForModel(m_eModelIndex)];
break;
case PICKUP_ON_STREET:
case PICKUP_ONCE:
@@ -131,28 +278,47 @@ CPickup::GiveUsAPickUpObject(int32 handle)
}
bool
-CPickup::CanBePickedUp(CPlayerPed *player)
+CPickup::CanBePickedUp(CPlayerPed *player, int playerId)
{
+ assert(m_pObject != nil);
bool cannotBePickedUp =
- (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
+ (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.2f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.2f)
|| (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->GetWantedLevel() == 0)
- || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
+ || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame))
+ || (m_eType == PICKUP_ASSET_REVENUE && m_fRevenue < 10.0f);
return !cannotBePickedUp;
}
bool
CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
{
- float waterLevel;
bool result = false;
+ float waterLevel;
+
+ if (m_pObject) {
+ m_pObject->GetMatrix().GetPosition() = m_vecPos;
+ if (m_pExtraObject)
+ m_pExtraObject->GetMatrix().GetPosition() = m_vecPos;
+ }
+ if (m_eType == PICKUP_ASSET_REVENUE) {
+ uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nTimer;
+ m_nTimer = CTimer::GetTimeInMilliseconds();
+
+ if (Distance(FindPlayerCoors(), m_vecPos) > 10.0f)
+ m_fRevenue += float(timePassed * m_nMoneySpeed) / SQR(1200.0f);
+
+ m_fRevenue = Min(m_fRevenue, m_nQuantity);
+
+ m_pObject->m_nCostValue = m_fRevenue < 10 ? 0 : m_fRevenue;
+ }
if (m_bRemoved) {
if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
// respawn pickup if we're far enough
float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
- m_pObject = GiveUsAPickUpObject(-1);
+ m_pObject = GiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1);
if (m_pObject) {
CWorld::Add(m_pObject);
m_bRemoved = false;
@@ -162,6 +328,14 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
return false;
}
+ if (!m_pObject) {
+ GiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1);
+ if (m_pObject)
+ CWorld::Add(m_pObject);
+ if (m_pExtraObject)
+ CWorld::Add(m_pExtraObject);
+ }
+
if (!m_pObject) return false;
if (!IsMine()) {
@@ -191,37 +365,94 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
}
}
+ if (isPickupTouched) {
+ eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());
+ if (weaponType < WEAPONTYPE_TOTALWEAPONS && CDarkel::FrenzyOnGoing()) {
+ isPickupTouched = false;
+ m_bWasControlMessageShown = false;
+ } else if (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType != WEAPONTYPE_UNARMED) {
+ uint32 slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;
+ eWeaponType plrWeaponSlot = FindPlayerPed()->GetWeapon(slot).m_eWeaponType;
+ if (plrWeaponSlot != weaponType) {
+ if (CStreaming::ms_aInfoForModel[m_pObject->GetModelIndex()].m_loadState == STREAMSTATE_LOADED) {
+ if (plrWeaponSlot == WEAPONTYPE_UNARMED || (FindPlayerPed()->GetWeapon(slot).m_nAmmoTotal == 0 && !CWeaponInfo::IsWeaponSlotAmmoMergeable(slot))) {
+ if (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500) {
+ CPickups::PlayerOnWeaponPickup = 6;
+ isPickupTouched = false;
+ }
+ } else {
+ CPickups::PlayerOnWeaponPickup = 6;
+ if (CWeaponInfo::IsWeaponSlotAmmoMergeable(slot)) {
+ if (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE || m_eType == PICKUP_ON_STREET) {
+ ExtractAmmoFromPickup(player);
+ FindPlayerPed()->GetWeapon(slot).Reload();
+ }
+ }
+ if (!m_bWasControlMessageShown) {
+ switch (CPad::GetPad(0)->Mode)
+ {
+ case 0:
+ case 1:
+ CHud::SetHelpMessage(TheText.Get("PU_CF1"), false);
+ break;
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("PU_CF3"), false);
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("PU_CF4"), false);
+ break;
+ default:
+ break;
+ }
+ m_bWasControlMessageShown = true;
+ }
+ if (CollectPickupBuffer == 0)
+ isPickupTouched = false;
+ if (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500)
+ isPickupTouched = false;
+ }
+ } else
+ isPickupTouched = false;
+ }
+ }
+ } else
+ m_bWasControlMessageShown = false;
+
// if we didn't then we've got nothing to do
- if (isPickupTouched && CanBePickedUp(player)) {
- CPad::GetPad(0)->StartShake(120, 100);
+ if (isPickupTouched && CanBePickedUp(player, playerId)) {
+ if (m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY && m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY_FORSALE)
+ CPad::GetPad(0)->StartShake(120, 100);
+
+ eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());
switch (m_eType)
{
case PICKUP_IN_SHOP:
- if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
+ if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[weaponType])
CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
- } else {
- CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
+ else {
+ CWorld::Players[playerId].m_nMoney -= CostOfWeapon[weaponType];
if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ if (!player->DoesPlayerWantNewWeapon(weaponType, false))
+ break;
+ player->GiveWeapon(weaponType, AmmoForWeapon[weaponType]);
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);
DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
}
result = true;
- CWorld::Remove(m_pObject);
- delete m_pObject;
- m_pObject = nil;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
- m_bRemoved = true;
+ Remove();
}
break;
case PICKUP_ON_STREET:
case PICKUP_ON_STREET_SLOW:
if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- }
+ if (!player->DoesPlayerWantNewWeapon(weaponType, false))
+ break;
+ if (weaponType != WEAPONTYPE_UNARMED) {
+ player->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon_OnStreet[weaponType]), true);
+
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);
+
DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
} else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
@@ -231,9 +462,9 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
}
}
- if (m_eType == PICKUP_ON_STREET) {
+ if (m_eType == PICKUP_ON_STREET)
m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
- } else if (m_eType == PICKUP_ON_STREET_SLOW) {
+ else if (m_eType == PICKUP_ON_STREET_SLOW) {
if (MI_PICKUP_BRIBE == m_pObject->GetModelIndex())
m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
else
@@ -241,32 +472,37 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
}
result = true;
- CWorld::Remove(m_pObject);
- delete m_pObject;
- m_pObject = nil;
+ GetRidOfObjects();
m_bRemoved = true;
break;
case PICKUP_ONCE:
case PICKUP_ONCE_TIMEOUT:
+ case PICKUP_ONCE_TIMEOUT_SLOW:
if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (!player->DoesPlayerWantNewWeapon(weaponType, false)) {
+ ExtractAmmoFromPickup(player);
+ break;
+ }
+
+ if (weaponType != WEAPONTYPE_UNARMED) {
+ player->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon[weaponType]), true);
if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);
}
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ if (MI_PICKUP_SAVEGAME != m_pObject->GetModelIndex())
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
}
result = true;
Remove();
break;
case PICKUP_COLLECTABLE1:
CWorld::Players[playerId].m_nCollectedPackages++;
- CWorld::Players[playerId].m_nMoney += 1000;
+ CWorld::Players[playerId].m_nMoney += 100;
if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
printf("All collectables have been picked up\n");
CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 100000;
} else
CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
@@ -283,6 +519,39 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
result = true;
Remove();
DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
+ player->Say(SOUND_PED_MUGGING);
+ break;
+ case PICKUP_ASSET_REVENUE:
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += m_fRevenue;
+ m_fRevenue = 0.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
+ break;
+ case PICKUP_PROPERTY_LOCKED:
+ if (!m_bWasControlMessageShown) {
+ m_bWasControlMessageShown = true;
+ CHud::SetHelpMessage(TheText.Get(m_sTextKey), false);
+ }
+ break;
+ case PICKUP_PROPERTY_FORSALE:
+ ModifyStringLabelForControlSetting(m_sTextKey);
+ CMessages::InsertNumberInString(TheText.Get(m_sTextKey), m_nQuantity,
+ 0, 0, 0, 0, 0, gUString);
+ if (!CHud::IsHelpMessageBeingDisplayed())
+ CHud::SetHelpMessage(gUString, false);
+ if (CollectPickupBuffer == 0)
+ break;
+ if (CTheScripts::IsPlayerOnAMission())
+ CHud::SetHelpMessage(TheText.Get("PROP_2"), true);
+ else {
+ if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= m_nQuantity) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= m_nQuantity;
+ CHud::SetHelpMessage(nil, true);
+ result = true;
+ Remove();
+ break;
+ }
+ CHud::SetHelpMessage(TheText.Get("PROP_1"), true);
+ }
break;
default:
break;
@@ -311,7 +580,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
touched = true;
#ifdef FIX_BUGS
- break;
+ break; // added break here
#endif
}
}
@@ -343,7 +612,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
explode = true;
#ifdef FIX_BUGS
- break;
+ break; // added break here
#endif
}
}
@@ -378,12 +647,48 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
default: break;
}
}
- if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
+
+ if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE_TIMEOUT_SLOW || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
Remove();
+
return result;
}
void
+CPickup::ProcessGunShot(CVector *vec1, CVector *vec2)
+{
+ CColLine line(*vec1, *vec2);
+ if (m_pObject) {
+ CColSphere sphere;
+ sphere.radius = 4.0f;
+ sphere.center = m_pObject->GetPosition();
+ if (CCollision::TestLineSphere(line, sphere)) {
+ CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
+ CWorld::Remove(m_pObject);
+ delete m_pObject;
+ m_pObject = nil;
+ m_bRemoved = true;
+ m_eType = PICKUP_NONE;
+ }
+ }
+}
+
+void
+CPickup::GetRidOfObjects()
+{
+ if (m_pObject) {
+ CWorld::Remove(m_pObject);
+ delete m_pObject;
+ m_pObject = nil;
+ }
+ if (m_pExtraObject) {
+ CWorld::Remove(m_pExtraObject);
+ delete m_pExtraObject;
+ m_pExtraObject = nil;
+ }
+}
+
+void
CPickups::Init(void)
{
NumMessages = 0;
@@ -391,6 +696,7 @@ CPickups::Init(void)
aPickUps[i].m_eType = PICKUP_NONE;
aPickUps[i].m_nIndex = 1;
aPickUps[i].m_pObject = nil;
+ aPickUps[i].m_pExtraObject = nil;
}
for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
@@ -400,6 +706,28 @@ CPickups::Init(void)
}
bool
+CPickups::TestForPickupsInBubble(CVector pos, float range)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if ((aPickUps[i].m_vecPos - pos).Magnitude() < range)
+ return true;
+ }
+ return false;
+}
+
+bool
+CPickups::TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused) {
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == type && aPickUps[i].m_eModelIndex == ModelForWeapon(weapon))
+ if ((aPickUps[i].m_vecPos - pos).Magnitude() < 7.5f) {
+ aPickUps[i].m_nQuantity += quantity;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
CPickups::IsPickUpPickedUp(int32 pickupId)
{
for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
@@ -415,7 +743,7 @@ void
CPickups::PassTime(uint32 time)
{
for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_eType != PICKUP_ASSET_REVENUE) {
if (aPickUps[i].m_nTimer <= time)
aPickUps[i].m_nTimer = 0;
else
@@ -449,22 +777,21 @@ CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
return true;
} else if (modelIndex == MI_PICKUP_BODYARMOUR) {
- player->m_fArmour = 100.0f;
+ player->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
return true;
} else if (modelIndex == MI_PICKUP_INFO) {
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
return true;
} else if (modelIndex == MI_PICKUP_HEALTH) {
- player->m_fHealth = 100.0f;
+ player->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
return true;
} else if (modelIndex == MI_PICKUP_BONUS) {
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
return true;
} else if (modelIndex == MI_PICKUP_BRIBE) {
- int32 level = FindPlayerPed()->m_pWanted->GetWantedLevel() - 1;
- if (level < 0) level = 0;
+ int32 level = Max(FindPlayerPed()->m_pWanted->GetWantedLevel() - 1, 0);
player->SetWantedLevel(level);
DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
return true;
@@ -476,23 +803,9 @@ CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
}
void
-CPickups::RemoveAllFloatingPickups()
-{
- for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
- if (aPickUps[i].m_pObject) {
- CWorld::Remove(aPickUps[i].m_pObject);
- delete aPickUps[i].m_pObject;
- aPickUps[i].m_pObject = nil;
- }
- }
- }
-}
-
-void
CPickups::RemovePickUp(int32 pickupIndex)
{
- int32 index = CPickups::GetActualPickupIndex(pickupIndex);
+ int32 index = GetActualPickupIndex(pickupIndex);
if (index == -1) return;
if (aPickUps[index].m_pObject) {
@@ -500,24 +813,30 @@ CPickups::RemovePickUp(int32 pickupIndex)
delete aPickUps[index].m_pObject;
aPickUps[index].m_pObject = nil;
}
+ if (aPickUps[index].m_pExtraObject) {
+ CWorld::Remove(aPickUps[index].m_pExtraObject);
+ delete aPickUps[index].m_pExtraObject;
+ aPickUps[index].m_pExtraObject = nil;
+ }
aPickUps[index].m_eType = PICKUP_NONE;
aPickUps[index].m_bRemoved = true;
}
int32
-CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate, bool highPriority, char* pText)
{
bool bFreeFound = false;
int32 slot = 0;
- if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
+ if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE || highPriority) {
for (slot = NUMPICKUPS-1; slot >= 0; slot--) {
if (aPickUps[slot].m_eType == PICKUP_NONE) {
bFreeFound = true;
break;
}
}
- } else {
+ }
+ if (!bFreeFound) {
for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
if (aPickUps[slot].m_eType == PICKUP_NONE) {
bFreeFound = true;
@@ -533,10 +852,11 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan
if (slot >= NUMGENERALPICKUPS) {
for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
+ if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) break;
}
if (slot >= NUMGENERALPICKUPS) return -1;
+ aPickUps[slot].GetRidOfObjects();
}
}
@@ -545,8 +865,15 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan
aPickUps[slot].m_eType = type;
aPickUps[slot].m_bRemoved = false;
aPickUps[slot].m_nQuantity = quantity;
+ aPickUps[slot].m_nMoneySpeed = rate;
+ aPickUps[slot].m_fRevenue = 0.0f;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds();
+ aPickUps[slot].m_bWasAmmoCollected = highPriority;
+ aPickUps[slot].m_bWasControlMessageShown = false;
if (type == PICKUP_ONCE_TIMEOUT)
aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
+ else if (type == PICKUP_ONCE_TIMEOUT_SLOW)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 120000;
else if (type == PICKUP_MONEY)
aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
@@ -557,10 +884,17 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan
aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
}
aPickUps[slot].m_eModelIndex = modelIndex;
+ if (pText)
+ strncpy(aPickUps[slot].m_sTextKey, pText, 8);
+ else
+ aPickUps[slot].m_sTextKey[0] = '\0';
+
aPickUps[slot].m_vecPos = pos;
- aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
+ aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(&aPickUps[slot].m_pObject, &aPickUps[slot].m_pExtraObject, -1, -1);
if (aPickUps[slot].m_pObject)
CWorld::Add(aPickUps[slot].m_pObject);
+ if (aPickUps[slot].m_pExtraObject)
+ CWorld::Add(aPickUps[slot].m_pExtraObject);
return GetNewUniquePickupIndex(slot);
}
@@ -583,50 +917,17 @@ CPickups::GetNewUniquePickupIndex(int32 slot)
int32
CPickups::ModelForWeapon(eWeaponType weaponType)
{
- switch (weaponType)
- {
- case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
- case WEAPONTYPE_COLT45: return MI_COLT;
- case WEAPONTYPE_UZI: return MI_UZI;
- case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
- case WEAPONTYPE_AK47: return MI_AK47;
- case WEAPONTYPE_M16: return MI_M16;
- case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
- case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
- case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
- case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
- case WEAPONTYPE_GRENADE: return MI_GRENADE;
- default: break;
- }
- return 0;
+ return CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId;
}
eWeaponType
CPickups::WeaponForModel(int32 model)
{
if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
- switch (model)
- {
- case MI_GRENADE: return WEAPONTYPE_GRENADE;
- case MI_AK47: return WEAPONTYPE_AK47;
- case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
- case MI_COLT: return WEAPONTYPE_COLT45;
- case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
- case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
- case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
- case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
- case MI_UZI: return WEAPONTYPE_UZI;
- case MI_MISSILE: return WEAPONTYPE_UNARMED;
- case MI_M16: return WEAPONTYPE_M16;
- case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
- }
- return WEAPONTYPE_UNARMED;
-}
-
-int32
-CPickups::FindColourIndexForWeaponMI(int32 model)
-{
- return WeaponForModel(model) - 1;
+ if (model == MI_PICKUP_HEALTH) return WEAPONTYPE_HEALTH;
+ if (model == MI_PICKUP_ADRENALINE) return WEAPONTYPE_ARMOUR;
+ if (model == -1) return WEAPONTYPE_UNARMED;
+ return ((CWeaponModelInfo*)CModelInfo::GetModelInfo(model))->GetWeaponInfo();
}
void
@@ -671,69 +972,159 @@ CPickups::Update()
}
}
#endif
+ if (CPad::GetPad(0)->CollectPickupJustDown())
+ CollectPickupBuffer = 6;
+ else
+ CollectPickupBuffer = Max(0, CollectPickupBuffer - 1);
+
+ if (PlayerOnWeaponPickup)
+ PlayerOnWeaponPickup = Max(0, PlayerOnWeaponPickup - 1);
+
#define PICKUPS_FRAME_SPAN (6)
#ifdef FIX_BUGS
for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) {
#else // BUG: this code can only reach 318 out of 320 pickups
for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
#endif
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus))
AddToCollectedPickupsArray(i);
- }
}
#undef PICKUPS_FRAME_SPAN
for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus))
AddToCollectedPickupsArray(i);
+ }
+}
+
+CPickup*
+CPickups::FindPickUpForThisObject(CEntity *object)
+{
+ for (uint32 i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && (aPickUps[i].m_pObject == object || aPickUps[i].m_pExtraObject == object)) {
+ return &aPickUps[i];
}
}
+ return &aPickUps[0];
}
void
CPickups::DoPickUpEffects(CEntity *entity)
{
+ CPickup *pickup = FindPickUpForThisObject(entity);
+
if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
entity->bDoNotRender = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
if (!entity->bDoNotRender) {
float modifiedSin = 0.3f * (Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)) + 1.0f);
-
+#ifdef FIX_BUGS
+ int16 colorId = 0;
+#else
int16 colorId;
+#endif
+ bool doInnerGlow = false;
+ bool doOuterGlow = true;
+
+ if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) {
+ colorId = WEAPONTYPE_TOTALWEAPONS;
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR) {
+ colorId = WEAPONTYPE_ARMOUR;
+ } else if (entity->GetModelIndex() == MI_PICKUP_BRIBE) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) {
+ colorId = WEAPONTYPE_HEALTH;
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY_FORSALE) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_REVENUE) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_SAVEGAME) {
+ doInnerGlow = true;
+ doOuterGlow = false;
+ } else if (entity->GetModelIndex() == MI_PICKUP_CLOTHES) {
+ colorId = WEAPONTYPE_TOTALWEAPONS;
+ doOuterGlow = false;
+ doInnerGlow = true;
+ } else
+ colorId = WeaponForModel(entity->GetModelIndex());
+
+ const CVector& pos = pickup->m_vecPos;
+ if (doOuterGlow) {
+ bool corona1 = false;
+ bool corona2 = false;
+ int timerVal = (CTimer::GetTimeInMilliseconds() >> 9) & 7;
+
+ if (timerVal < 3)
+ corona1 = false;
+ else if (timerVal == 3)
+ corona1 = (CGeneral::GetRandomNumber() & 3) != 0;
+ else
+ corona1 = true;
- if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
- colorId = 11;
- else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
- colorId = 12;
- else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- colorId = 13;
- else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
- colorId = 14;
- else
- colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
-
- assert(colorId >= 0);
-
- const CVector &pos = entity->GetPosition();
+ timerVal = (timerVal - 1) & 7;
+ if (timerVal < 3)
+ corona2 = false;
+ else if (timerVal == 3)
+ corona2 = (CGeneral::GetRandomNumber() & 3) != 0;
+ else
+ corona2 = true;
- float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0,
- aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier, 4.0f,
- 1.0f, 40.0f, false, 0.0f);
+ if (((CObject*)entity)->bAmmoCollected) {
+ corona2 = false;
+ corona1 = false;
+ }
- float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
- CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
- float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f;
- CCoronas::RegisterCorona( (uintptr)entity,
- aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
- 255,
- pos,
- size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ if (corona1) {
+ CCoronas::RegisterCorona((uintptr)entity,
+ aPickupColors[colorId].r * 0.45f, aPickupColors[colorId].g * 0.45f, aPickupColors[colorId].b * 0.45f,
+ 255, pos, 0.76f, 65.0f,
+ CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF,
+ 0.0f, false, -0.4f);
+ CShadows::StoreStaticShadow((uintptr)entity,
+ SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0,
+ aPickupColors[colorId].r * 0.3f, aPickupColors[colorId].g * 0.3f, aPickupColors[colorId].b * 0.3f,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aPickupColors[colorId].r / 256.0f, aPickupColors[colorId].g / 256.0f, aPickupColors[colorId].b / 256.0f, CPointLights::FOG_NONE, true);
+ } else
+ CCoronas::RegisterCorona((uintptr)entity, 0, 0, 0, 255, pos, 0.57f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+
+ if (corona2) {
+ CCoronas::RegisterCorona(
+ (uintptr)entity + 1,
+ aPickupColors[colorId].r * 0.55f, aPickupColors[colorId].g * 0.55f, aPickupColors[colorId].b * 0.55f,
+ 255,
+ pos,
+ 0.6f,
+ 65.0f,
+ CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF,
+ 0.0f, false, -0.4f);
+ if (!corona1)
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0,
+ aPickupColors[colorId].r * 0.25f, aPickupColors[colorId].g * 0.25f, aPickupColors[colorId].b * 0.25f,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ } else
+ CCoronas::RegisterCorona((uintptr)entity + 1, 0, 0, 0, 255, pos, 0.45f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
CObject *object = (CObject*)entity;
- if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue) {
+ if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue || object->m_nCostValue) {
+
float dist = Distance2D(pos, TheCamera.GetPosition());
- const float MAXDIST = 12.0f;
+ const float MAXDIST = 14.0f;
if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
RwV3d vecOut;
@@ -744,20 +1135,30 @@ CPickups::DoPickUpEffects(CEntity *entity)
aMessages[NumMessages].m_dist.x = fDistX;
aMessages[NumMessages].m_dist.y = fDistY;
aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
- aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
- aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
- aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
+ aMessages[NumMessages].m_color.red = aPickupColors[colorId].r;
+ aMessages[NumMessages].m_color.green = aPickupColors[colorId].g;
+ aMessages[NumMessages].m_color.blue = aPickupColors[colorId].b;
aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
aMessages[NumMessages].m_quantity = object->m_nBonusValue;
+ aMessages[NumMessages].money = object->m_nCostValue;
NumMessages++;
}
}
}
+ uint32 model = entity->GetModelIndex();
+ CColModel *colModel = entity->GetColModel();
+ CVector colLength = colModel->boundingBox.max - colModel->boundingBox.min;
+ float maxDimension = Max(colLength.x, Max(colLength.y, colLength.z));
+
+ float scale = (Max(1.f, 1.2f / maxDimension) - 1.0f) * 0.6f + 1.0f;
+ if (model == MI_MINIGUN || model == MI_MINIGUN2)
+ scale = 1.2f;
+
float angle = (float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800);
- float c = Cos(angle) * aWeaponScale[colorId];
- float s = Sin(angle) * aWeaponScale[colorId];
+ float c = Cos(angle) * scale;
+ float s = Sin(angle) * scale;
// we know from SA they were setting each field manually like this
entity->GetMatrix().rx = c;
@@ -768,7 +1169,57 @@ CPickups::DoPickUpEffects(CEntity *entity)
entity->GetMatrix().fz = 0.0f;
entity->GetMatrix().ux = 0.0f;
entity->GetMatrix().uy = 0.0f;
- entity->GetMatrix().uz = aWeaponScale[colorId];
+ entity->GetMatrix().uz = scale;
+
+ if (entity->GetModelIndex() == MI_MINIGUN2) {
+ CMatrix matrix1;
+ CMatrix matrix2; // unused
+ entity->SetPosition(pickup->m_vecPos);
+ matrix1.SetRotateX(0.0f);
+ matrix1.Rotate(DEGTORAD(4.477f), DEGTORAD(-29.731f), DEGTORAD(-1.064f));
+ matrix1.Translate(CVector(0.829f, -0.001f, 0.226f));
+ entity->GetMatrix() *= matrix1;
+ }
+
+ if (doOuterGlow) {
+ CVector scale(0.0f, 0.0f, 0.0f);
+ if (colLength.x == maxDimension)
+ scale.x = colLength.x;
+ else if (colLength.y == maxDimension)
+ scale.y = colLength.y;
+ else
+ scale.z = colLength.z;
+
+ for (int i = 0; i < 4; i++) {
+ CVector pos = entity->GetMatrix() * (scale * ((float)i / 3.0f));
+ CCoronas::RegisterCorona(
+ (uintptr)entity + 8 + i,
+ aPickupColors[colorId].r * 0.15f,
+ aPickupColors[colorId].g * 0.15f,
+ aPickupColors[colorId].b * 0.15f,
+ 255,
+ pos,
+ 1.0f,
+ 65.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE,
+ CCoronas::REFLECTION_OFF,
+ CCoronas::LOSCHECK_OFF,
+ CCoronas::STREAK_OFF,
+ 0.0f,
+ false,
+ -0.5f);
+ }
+ }
+
+ if (doInnerGlow)
+ CCoronas::RegisterCorona(
+#ifdef FIX_BUGS
+ (uintptr)entity + 8 + 4,
+#else
+ (uintptr)entity + 9,
+#endif
+ 126, 69, 121, 255, entity->GetPosition(), 1.2f, 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
}
}
@@ -823,7 +1274,7 @@ CPickups::DoCollectableEffects(CEntity *entity)
int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, color, color, color, 4.0f,
1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_HEX, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
}
entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
@@ -834,13 +1285,17 @@ CPickups::RenderPickUpText()
{
wchar *strToPrint;
for (int32 i = 0; i < NumMessages; i++) {
- if (aMessages[i].m_quantity <= 39) {
+
+ if (aMessages[i].money != 0) {
+ sprintf(gString, "$%d", aMessages[i].money);
+ AsciiToUnicode(gString, gUString);
+ strToPrint = gUString;
+ } else {
switch (aMessages[i].m_quantity) // could use some enum maybe
{
case 0:
- if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
- // what is this??
- sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
+ if (aMessages[i].m_weaponType == WEAPONTYPE_HEALTH || aMessages[i].m_weaponType == WEAPONTYPE_ARMOUR) {
+ strToPrint = nil;
} else {
if (aMessages[i].m_bOutOfStock)
strToPrint = TheText.Get("STOCK");
@@ -852,176 +1307,181 @@ CPickups::RenderPickUpText()
}
break;
case 1:
- strToPrint = TheText.Get("SECURI");
+ strToPrint = TheText.Get("OUTFT1");
break;
case 2:
- strToPrint = TheText.Get("MOONBM");
+ strToPrint = TheText.Get("OUTFT2");
break;
case 3:
- strToPrint = TheText.Get("COACH");
+ strToPrint = TheText.Get("OUTFT3");
break;
case 4:
- strToPrint = TheText.Get("FLATBED");
+ strToPrint = TheText.Get("OUTFT4");
break;
case 5:
- strToPrint = TheText.Get("LINERUN");
+ strToPrint = TheText.Get("OUTFT5");
break;
case 6:
- strToPrint = TheText.Get("TRASHM");
+ strToPrint = TheText.Get("OUTFT6");
break;
case 7:
- strToPrint = TheText.Get("PATRIOT");
+ strToPrint = TheText.Get("OUTFT7");
break;
case 8:
- strToPrint = TheText.Get("WHOOPEE");
+ strToPrint = TheText.Get("OUTFT8");
break;
case 9:
- strToPrint = TheText.Get("BLISTA");
+ strToPrint = TheText.Get("OUTFT9");
break;
case 10:
- strToPrint = TheText.Get("MULE");
+ strToPrint = TheText.Get("OUTFT10");
break;
case 11:
- strToPrint = TheText.Get("YANKEE");
+ strToPrint = TheText.Get("OUTFT11");
break;
case 12:
- strToPrint = TheText.Get("BOBCAT");
+ strToPrint = TheText.Get("OUTFT12");
break;
case 13:
- strToPrint = TheText.Get("DODO");
- break;
- case 14:
- strToPrint = TheText.Get("BUS");
- break;
- case 15:
- strToPrint = TheText.Get("RUMPO");
- break;
- case 16:
- strToPrint = TheText.Get("PONY");
- break;
- case 17:
- strToPrint = TheText.Get("SENTINL");
- break;
- case 18:
- strToPrint = TheText.Get("CHEETAH");
- break;
- case 19:
- strToPrint = TheText.Get("BANSHEE");
- break;
- case 20:
- strToPrint = TheText.Get("IDAHO");
- break;
- case 21:
- strToPrint = TheText.Get("INFERNS");
- break;
- case 22:
- strToPrint = TheText.Get("TAXI");
- break;
- case 23:
- strToPrint = TheText.Get("KURUMA");
- break;
- case 24:
- strToPrint = TheText.Get("STRETCH");
- break;
- case 25:
- strToPrint = TheText.Get("PEREN");
- break;
- case 26:
- strToPrint = TheText.Get("STINGER");
- break;
- case 27:
- strToPrint = TheText.Get("MANANA");
- break;
- case 28:
- strToPrint = TheText.Get("LANDSTK");
- break;
- case 29:
- strToPrint = TheText.Get("STALION");
- break;
- case 30:
- strToPrint = TheText.Get("BFINJC");
- break;
- case 31:
- strToPrint = TheText.Get("CABBIE");
- break;
- case 32:
- strToPrint = TheText.Get("ESPERAN");
- break;
- case 33:
- strToPrint = TheText.Get("FIRETRK");
- break;
- case 34:
- strToPrint = TheText.Get("AMBULAN");
- break;
- case 35:
- strToPrint = TheText.Get("ENFORCR");
- break;
- case 36:
- strToPrint = TheText.Get("FBICAR");
- break;
- case 37:
- strToPrint = TheText.Get("RHINO");
- break;
- case 38:
- strToPrint = TheText.Get("BARRCKS");
- break;
- case 39:
- strToPrint = TheText.Get("POLICAR");
+ strToPrint = TheText.Get("OUTFT13");
break;
default:
break;
}
}
+ if (strToPrint == nil)
+ continue;
CFont::SetPropOn();
CFont::SetBackgroundOff();
- const float MAX_SCALE = 1.0f;
+#ifdef FIX_BUGS
+ const float MAX_SCALE = SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH;
+#else
+ float MAX_SCALE = RsGlobal.width / DEFAULT_SCREEN_WIDTH;
+#endif
- float fScaleY = aMessages[i].m_dist.y / 100.0f;
+ float fScaleY = aMessages[i].m_dist.y / 30.0f;
if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
- float fScaleX = aMessages[i].m_dist.x / 100.0f;
+ float fScaleX = aMessages[i].m_dist.x / 30.0f;
if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
-#ifdef FIX_BUGS
- CFont::SetScale(SCREEN_SCALE_X(fScaleX), SCREEN_SCALE_Y(fScaleY));
-#else
- CFont::SetScale(fScaleX, fScaleY);
-#endif
+ CFont::SetScale(fScaleX, fScaleY); // this shouldn't be scaled
CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_WIDTH);
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
}
NumMessages = 0;
}
void
+CPickups::CreateSomeMoney(CVector pos, int money)
+{
+ bool found;
+
+ int pickupCount = Min(money / 20 + 1, 7);
+ int moneyPerPickup = money / pickupCount;
+
+ for (int i = 0; i < pickupCount; i++) {
+ // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.
+ pos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128);
+ pos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128);
+ pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 0.5f;
+ if (found) {
+ CPickups::GenerateNewOne(CVector(pos.x, pos.y, pos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3));
+ }
+ }
+}
+
+void
+CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType weaponType)
+{
+ uint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;
+ if (CWeaponInfo::IsWeaponSlotAmmoMergeable(weaponSlot)) {
+ for (int slot = 0; slot < NUMPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_ONCE || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) {
+ if (aPickUps[slot].m_pObject) {
+ if (CWeaponInfo::GetWeaponInfo(WeaponForModel(aPickUps[slot].m_pObject->GetModelIndex()))->m_nWeaponSlot == weaponSlot &&
+ aPickUps[slot].m_nQuantity == 0) {
+ CWorld::Remove(aPickUps[slot].m_pObject);
+ delete aPickUps[slot].m_pObject;
+ aPickUps[slot].m_bRemoved = true;
+ aPickUps[slot].m_pObject = nil;
+ aPickUps[slot].m_eType = PICKUP_NONE;
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CPickups::DetonateMinesHitByGunShot(CVector *vec1, CVector *vec2)
+{
+ for (int i = 0; i < NUMGENERALPICKUPS; i++) {
+ if (aPickUps[i].m_eType == PICKUP_NAUTICAL_MINE_ARMED)
+ aPickUps[i].ProcessGunShot(vec1, vec2);
+ }
+}
+
+void
+CPickups::RemoveUnnecessaryPickups(const CVector& center, float radius)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[i].m_eType == PICKUP_MONEY) {
+ if (Distance(center, aPickUps[i].m_vecPos) < radius) {
+ aPickUps[i].GetRidOfObjects();
+ aPickUps[i].m_bRemoved = true;
+ aPickUps[i].m_eType = PICKUP_NONE;
+ }
+ }
+ }
+}
+
+void
CPickups::Load(uint8 *buf, uint32 size)
{
INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) {
#ifdef COMPATIBLE_SAVES
- ReadSaveBuf(&aPickUps[i].m_eType, buf);
- ReadSaveBuf(&aPickUps[i].m_bRemoved, buf);
+ ReadSaveBuf(&aPickUps[i].m_vecPos, buf);
+ ReadSaveBuf(&aPickUps[i].m_fRevenue, buf);
+ int32 tmp_pObject;
+ ReadSaveBuf(&tmp_pObject, buf);
+ int32 tmp_pExtraObject;
+ ReadSaveBuf(&tmp_pExtraObject, buf);
ReadSaveBuf(&aPickUps[i].m_nQuantity, buf);
- int32 tmp;
- ReadSaveBuf(&tmp, buf);
- aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil;
ReadSaveBuf(&aPickUps[i].m_nTimer, buf);
+ ReadSaveBuf(&aPickUps[i].m_nMoneySpeed, buf);
ReadSaveBuf(&aPickUps[i].m_eModelIndex, buf);
ReadSaveBuf(&aPickUps[i].m_nIndex, buf);
- ReadSaveBuf(&aPickUps[i].m_vecPos, buf);
+ memcpy(aPickUps[i].m_sTextKey, buf, sizeof(aPickUps[i].m_sTextKey));
+ SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey));
+ ReadSaveBuf(&aPickUps[i].m_eType, buf);
+ ReadSaveBuf(&aPickUps[i].m_bRemoved, buf);
+ uint8 flags;
+ ReadSaveBuf(&flags, buf);
+ aPickUps[i].m_bWasAmmoCollected = !!(flags & BIT(0));
+ aPickUps[i].m_bWasControlMessageShown = !!(flags & BIT(1));
+ SkipSaveBuf(buf, 3);
+
+ aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pObject - 1) : nil;
+ aPickUps[i].m_pExtraObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pExtraObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pExtraObject - 1) : nil;
#else
ReadSaveBuf(&aPickUps[i], buf);
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
- aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1);
+ if (aPickUps[i].m_eType != PICKUP_NONE) {
+ if (aPickUps[i].m_pObject != nil)
+ aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1);
+ if (aPickUps[i].m_pExtraObject != nil)
+ aPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1);
+ }
#endif
}
@@ -1038,25 +1498,41 @@ VALIDATESAVEBUF(size)
void
CPickups::Save(uint8 *buf, uint32 *size)
{
- *size = PICKUPS_SAVE_SIZE + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
+ *size = PICKUPS_SAVE_SIZE;
+ *size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) {
#ifdef COMPATIBLE_SAVES
- WriteSaveBuf(buf, aPickUps[i].m_eType);
- WriteSaveBuf(buf, aPickUps[i].m_bRemoved);
- WriteSaveBuf(buf, aPickUps[i].m_nQuantity);
+ WriteSaveBuf(buf, aPickUps[i].m_vecPos);
+ WriteSaveBuf(buf, aPickUps[i].m_fRevenue);
int32 tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pObject) + 1 : 0;
WriteSaveBuf(buf, tmp);
+ tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pExtraObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pExtraObject) + 1 : 0;
+ WriteSaveBuf(buf, tmp);
+ WriteSaveBuf(buf, aPickUps[i].m_nQuantity);
WriteSaveBuf(buf, aPickUps[i].m_nTimer);
+ WriteSaveBuf(buf, aPickUps[i].m_nMoneySpeed);
WriteSaveBuf(buf, aPickUps[i].m_eModelIndex);
WriteSaveBuf(buf, aPickUps[i].m_nIndex);
- WriteSaveBuf(buf, aPickUps[i].m_vecPos);
+ memcpy(buf, aPickUps[i].m_sTextKey, sizeof(aPickUps[i].m_sTextKey));
+ SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey));
+ WriteSaveBuf(buf, aPickUps[i].m_eType);
+ WriteSaveBuf(buf, aPickUps[i].m_bRemoved);
+ uint8 flags = 0;
+ if (aPickUps[i].m_bWasAmmoCollected) flags |= BIT(0);
+ if (aPickUps[i].m_bWasControlMessageShown) flags |= BIT(1);
+ WriteSaveBuf(buf, flags);
+ ZeroSaveBuf(buf, 3);
#else
CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
- if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
- buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);
+ if (buf_pickup->m_eType != PICKUP_NONE) {
+ if (buf_pickup->m_pObject != nil)
+ buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);
+ if (buf_pickup->m_pExtraObject != nil)
+ buf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pExtraObject) + 1);
+ }
#endif
}
@@ -1072,40 +1548,6 @@ VALIDATESAVEBUF(*size)
void
CPacManPickup::Update()
{
- if (FindPlayerVehicle() == nil) return;
-
- CVehicle *veh = FindPlayerVehicle();
-
- if (DistanceSqr2D(FindPlayerVehicle()->GetPosition(), m_vecPosn.x, m_vecPosn.y) < 100.0f && veh->IsSphereTouchingVehicle(m_vecPosn.x, m_vecPosn.y, m_vecPosn.z, 1.5f)) {
- switch (m_eType)
- {
- case PACMAN_SCRAMBLE:
- {
- veh->m_nPacManPickupsCarried++;
- veh->m_vecMoveSpeed *= 0.65f;
- float massMult = (veh->m_fMass + 250.0f) / veh->m_fMass;
- veh->m_fMass *= massMult;
- veh->m_fTurnMass *= massMult;
- veh->m_fForceMultiplier *= massMult;
- FindPlayerPed()->m_pWanted->m_nChaos += 10;
- FindPlayerPed()->m_pWanted->UpdateWantedLevel();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0);
- break;
- }
- case PACMAN_RACE:
- CPacManPickups::PillsEatenInRace++;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PILL, 0);
- break;
- default:
- break;
- }
- m_eType = PACMAN_NONE;
- if (m_pObject != nil) {
- CWorld::Remove(m_pObject);
- delete m_pObject;
- m_pObject = nil;
- }
- }
}
int32 CollectGameState;
@@ -1119,96 +1561,16 @@ bool CPacManPickups::bPMActive;
void
CPacManPickups::Init()
{
- for (int i = 0; i < NUMPACMANPICKUPS; i++)
- aPMPickUps[i].m_eType = PACMAN_NONE;
- bPMActive = false;
}
void
CPacManPickups::Update()
{
- if (FindPlayerVehicle()) {
- float dist = Distance(FindPlayerCoors(), CVector(1072.0f, -948.0f, 14.5f));
- switch (CollectGameState) {
- case 1:
- if (dist < 10.0f) {
- ThingsToCollect -= FindPlayerVehicle()->m_nPacManPickupsCarried;
- FindPlayerVehicle()->m_nPacManPickupsCarried = 0;
- FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier;
- FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier;
- FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
- }
- if (ThingsToCollect <= 0) {
- CollectGameState = 2;
- ClearPMPickUps();
- }
- break;
- case 2:
- if (dist > 11.0f)
- CollectGameState = 0;
- break;
- case 20:
- if (Distance(FindPlayerCoors(), LastPickUpCoors) > 30.0f) {
- LastPickUpCoors = FindPlayerCoors();
- printf("%f, %f, %f,\n", LastPickUpCoors.x, LastPickUpCoors.y, LastPickUpCoors.z);
- }
- break;
- default:
- break;
- }
- }
- if (bPMActive) {
-#define PACMANPICKUPS_FRAME_SPAN (4)
- for (uint32 i = (CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i < ((CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) + 1) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i++) {
- if (aPMPickUps[i].m_eType != PACMAN_NONE)
- aPMPickUps[i].Update();
- }
-#undef PACMANPICKUPS_FRAME_SPAN
- }
}
void
CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type)
{
- int i = 0;
- while (count > 0) {
- while (aPMPickUps[i].m_eType != PACMAN_NONE)
- i++;
-
- bool bPickupCreated = false;
- while (!bPickupCreated) {
- CVector newPos = pos;
- CColPoint colPoint;
- CEntity *pRoad;
- uint16 nRand = CGeneral::GetRandomNumber();
- newPos.x += ((nRand & 0xFF) - 128) * scrambleMult / 128.0f;
- newPos.y += (((nRand >> 8) & 0xFF) - 128) * scrambleMult / 128.0f;
- newPos.z = 1000.0f;
- if (CWorld::ProcessVerticalLine(newPos, -1000.0f, colPoint, pRoad, true, false, false, false, true, false, nil) && pRoad->IsBuilding() && ((CBuilding*)pRoad)->GetIsATreadable()) {
- newPos.z = 0.7f + colPoint.point.z;
- aPMPickUps[i].m_eType = type;
- aPMPickUps[i].m_vecPosn = newPos;
- CObject *obj = new CObject(MI_BULLION, true);
- if (obj != nil) {
- obj->ObjectCreatedBy = MISSION_OBJECT;
- obj->SetPosition(aPMPickUps[i].m_vecPosn);
- obj->SetOrientation(0.0f, 0.0f, -HALFPI);
- obj->GetMatrix().UpdateRW();
- obj->UpdateRwFrame();
-
- obj->bAffectedByGravity = false;
- obj->bExplosionProof = true;
- obj->bUsesCollision = false;
- obj->bIsPickup = false;
- CWorld::Add(obj);
- }
- aPMPickUps[i].m_pObject = obj;
- bPickupCreated = true;
- }
- }
- count--;
- }
- bPMActive = true;
}
// diablo porn mission pickups
@@ -1218,271 +1580,69 @@ static const CVector aRacePoints1[] = {
CVector(913.27899f, -93.524231f, 7.4325991f),
CVector(912.60852f, -63.15905f, 7.4533591f),
CVector(934.22144f, -42.049122f, 7.4511471f),
- CVector(958.88092f, -23.863735f, 7.4652338f),
- CVector(978.50812f, -0.78458798f, 5.13515f),
- CVector(1009.4175f, -2.1041219f, 2.4461579f),
- CVector(1040.6313f, -2.0793829f, 2.293175f),
- CVector(1070.7863f, -2.084095f, 2.2789791f),
- CVector(1100.5773f, -8.468729f, 5.3248072f),
- CVector(1119.9341f, -31.738031f, 7.1913071f),
- CVector(1122.1664f, -62.762737f, 7.4703908f),
- CVector(1122.814f, -93.650566f, 8.5577497f),
- CVector(1125.8253f, -124.26616f, 9.9803305f),
- CVector(1153.8727f, -135.47169f, 14.150617f),
- CVector(1184.0831f, -135.82845f, 14.973998f),
- CVector(1192.0432f, -164.57816f, 19.18627f),
- CVector(1192.7761f, -194.28871f, 24.799675f),
- CVector(1215.1527f, -215.0714f, 25.74975f),
- CVector(1245.79f, -215.39304f, 28.70726f),
- CVector(1276.2477f, -216.39485f, 33.71236f),
- CVector(1306.5535f, -216.71007f, 39.711472f),
- CVector(1335.0244f, -224.59329f, 46.474979f),
- CVector(1355.4879f, -246.27664f, 49.934841f),
- CVector(1362.6003f, -276.47064f, 49.96265f),
- CVector(1363.027f, -307.30847f, 49.969173f),
- CVector(1365.343f, -338.08609f, 49.967789f),
- CVector(1367.5957f, -368.01105f, 50.092304f),
- CVector(1368.2749f, -398.38049f, 50.061268f),
- CVector(1366.9034f, -429.98483f, 50.057545f),
- CVector(1356.8534f, -459.09259f, 50.035545f),
- CVector(1335.5819f, -481.13544f, 47.217903f),
- CVector(1306.7552f, -491.07443f, 40.202629f),
- CVector(1275.5978f, -491.33194f, 33.969223f),
- CVector(1244.702f, -491.46451f, 29.111021f),
- CVector(1213.2222f, -491.8754f, 25.771168f),
- CVector(1182.7729f, -492.19995f, 24.749964f),
- CVector(1152.6874f, -491.42221f, 21.70038f),
- CVector(1121.5352f, -491.94604f, 20.075182f),
- CVector(1090.7056f, -492.63751f, 17.585758f),
- CVector(1059.6008f, -491.65762f, 14.848632f),
- CVector(1029.113f, -489.66031f, 14.918498f),
- CVector(998.20679f, -486.78107f, 14.945688f),
- CVector(968.00555f, -484.91266f, 15.001229f),
- CVector(937.74939f, -492.09015f, 14.958629f),
- CVector(927.17352f, -520.97736f, 14.972308f),
- CVector(929.29749f, -552.08643f, 14.978855f),
- CVector(950.69525f, -574.47778f, 14.972788f),
- CVector(974.02826f, -593.56024f, 14.966445f),
- CVector(989.04779f, -620.12854f, 14.951016f),
- CVector(1014.1639f, -637.3905f, 14.966736f),
- CVector(1017.5961f, -667.3736f, 14.956415f),
- CVector(1041.9735f, -685.94391f, 15.003841f),
- CVector(1043.3064f, -716.11298f, 14.974236f),
- CVector(1043.5337f, -746.63855f, 14.96919f),
- CVector(1044.142f, -776.93823f, 14.965424f),
- CVector(1044.2657f, -807.29395f, 14.97171f),
- CVector(1017.0797f, -820.1076f, 14.975431f),
- CVector(986.23865f, -820.37103f, 14.972883f),
- CVector(956.10065f, -820.23291f, 14.981133f),
- CVector(925.86914f, -820.19049f, 14.976553f),
- CVector(897.69702f, -831.08734f, 14.962709f),
- CVector(868.06586f, -835.99237f, 14.970685f),
- CVector(836.93054f, -836.84387f, 14.965049f),
- CVector(811.63586f, -853.7915f, 15.067576f),
- CVector(811.46344f, -884.27368f, 12.247812f),
- CVector(811.60651f, -914.70959f, 9.2393751f),
- CVector(811.10425f, -945.16272f, 5.817255f),
- CVector(816.54584f, -975.64587f, 4.998558f),
- CVector(828.2951f, -1003.3685f, 5.0471172f),
- CVector(852.28839f, -1021.5963f, 4.9371028f),
- CVector(882.50067f, -1025.4459f, 5.14077f),
- CVector(912.84821f, -1026.7874f, 8.3415451f),
- CVector(943.68274f, -1026.6914f, 11.341879f),
- CVector(974.4129f, -1027.3682f, 14.410345f),
- CVector(1004.1079f, -1036.0778f, 14.92961f),
- CVector(1030.1144f, -1051.1224f, 14.850387f),
- CVector(1058.7585f, -1060.342f, 14.821624f),
- CVector(1087.7797f, -1068.3263f, 14.800561f),
- CVector(1099.8807f, -1095.656f, 11.877907f),
- CVector(1130.0005f, -1101.994f, 11.853914f),
- CVector(1160.3809f, -1101.6355f, 11.854824f),
- CVector(1191.8524f, -1102.1577f, 11.853843f),
- CVector(1223.3307f, -1102.7448f, 11.852233f),
- CVector(1253.564f, -1098.1045f, 11.853944f),
- CVector(1262.0203f, -1069.1785f, 14.8147f),
- CVector(1290.9998f, -1059.1882f, 14.816016f),
- CVector(1316.246f, -1041.0635f, 14.81109f),
- CVector(1331.7539f, -1013.835f, 14.81207f),
- CVector(1334.0579f, -983.55402f, 14.827253f),
- CVector(1323.2429f, -954.23083f, 14.954678f),
- CVector(1302.7495f, -932.21216f, 14.962917f),
- CVector(1317.418f, -905.89325f, 14.967506f),
- CVector(1337.9503f, -883.5025f, 14.969675f),
- CVector(1352.6929f, -855.96954f, 14.967854f),
- CVector(1357.2388f, -826.26971f, 14.97295f),
- CVector(1384.8668f, -812.47693f, 12.907736f),
- CVector(1410.8983f, -795.39056f, 12.052228f),
- CVector(1433.901f, -775.55811f, 11.96265f),
- CVector(1443.8615f, -746.92511f, 11.976114f),
- CVector(1457.7015f, -720.00903f, 11.971177f),
- CVector(1481.5685f, -701.30237f, 11.977908f),
- CVector(1511.4004f, -696.83295f, 11.972709f),
- CVector(1542.1796f, -695.61676f, 11.970441f),
- CVector(1570.3301f, -684.6239f, 11.969202f),
CVector(0.0f, 0.0f, 0.0f),
};
void
CPacManPickups::GeneratePMPickUpsForRace(int32 race)
{
- const CVector *pPos = nil;
- int i = 0;
-
- if (race == 0) pPos = aRacePoints1; // there's only one available
- assert(pPos != nil);
-
- while (!pPos->IsZero()) {
- while (aPMPickUps[i].m_eType != PACMAN_NONE)
- i++;
-
- aPMPickUps[i].m_eType = PACMAN_RACE;
- aPMPickUps[i].m_vecPosn = *(pPos++);
- if (race == 0) {
- CObject* obj = new CObject(MI_DONKEYMAG, true);
- if (obj != nil) {
- obj->ObjectCreatedBy = MISSION_OBJECT;
-
- obj->SetPosition(aPMPickUps[i].m_vecPosn);
- obj->SetOrientation(0.0f, 0.0f, -HALFPI);
- obj->GetMatrix().UpdateRW();
- obj->UpdateRwFrame();
-
- obj->bAffectedByGravity = false;
- obj->bExplosionProof = true;
- obj->bUsesCollision = false;
- obj->bIsPickup = false;
-
- CWorld::Add(obj);
- }
- aPMPickUps[i].m_pObject = obj;
- } else
- aPMPickUps[i].m_pObject = nil;
- }
- bPMActive = true;
}
void
CPacManPickups::GenerateOnePMPickUp(CVector pos)
{
- bPMActive = true;
- aPMPickUps[0].m_eType = PACMAN_RACE;
- aPMPickUps[0].m_vecPosn = pos;
}
void
CPacManPickups::Render()
{
- if (!bPMActive) return;
-
- PUSH_RENDERGROUP("CPacManPickups::Render");
-
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[6]));
-
- RwV3d pos;
- float w, h;
-
- for (int i = 0; i < NUMPACMANPICKUPS; i++) {
- switch (aPMPickUps[i].m_eType)
- {
- case PACMAN_SCRAMBLE:
- case PACMAN_RACE:
- if (CSprite::CalcScreenCoors(aPMPickUps[i].m_vecPosn, &pos, &w, &h, true) && pos.z < 100.0f) {
- if (aPMPickUps[i].m_pObject != nil) {
- aPMPickUps[i].m_pObject->GetMatrix().SetRotateZOnly((CTimer::GetTimeInMilliseconds() % 1024) * TWOPI / 1024.0f);
- aPMPickUps[i].m_pObject->GetMatrix().UpdateRW();
- aPMPickUps[i].m_pObject->UpdateRwFrame();
- }
- float fsin = Sin((CTimer::GetTimeInMilliseconds() % 1024) * 6.28f / 1024.0f); // yes, it is 6.28f when it was TWOPI just now...
- CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z, 0.8f * w * fsin, 0.8f * h, 100, 50, 5, 255, 1.0f / pos.z, 255);
- }
- break;
- default:
- break;
- }
- }
-
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE);
-
- POP_RENDERGROUP();
}
void
CPacManPickups::ClearPMPickUps()
{
- bPMActive = false;
-
- for (int i = 0; i < NUMPACMANPICKUPS; i++) {
- if (aPMPickUps[i].m_pObject != nil) {
- CWorld::Remove(aPMPickUps[i].m_pObject);
- delete aPMPickUps[i].m_pObject;
- aPMPickUps[i].m_pObject = nil;
- }
- aPMPickUps[i].m_eType = PACMAN_NONE;
- }
}
void
CPacManPickups::StartPacManRace(int32 race)
{
- GeneratePMPickUpsForRace(race);
- PillsEatenInRace = 0;
}
void
CPacManPickups::StartPacManRecord()
{
- CollectGameState = 20;
- LastPickUpCoors = FindPlayerCoors();
}
uint32
CPacManPickups::QueryPowerPillsEatenInRace()
{
- return PillsEatenInRace;
+ return 0;
}
void
CPacManPickups::ResetPowerPillsEatenInRace()
{
- PillsEatenInRace = 0;
}
void
CPacManPickups::CleanUpPacManStuff()
{
- ClearPMPickUps();
}
void
CPacManPickups::StartPacManScramble(CVector pos, float scrambleMult, int16 count)
{
- GeneratePMPickUps(pos, scrambleMult, count, PACMAN_SCRAMBLE);
}
uint32
CPacManPickups::QueryPowerPillsCarriedByPlayer()
{
- if (FindPlayerVehicle())
- return FindPlayerVehicle()->m_nPacManPickupsCarried;
return 0;
}
void
CPacManPickups::ResetPowerPillsCarriedByPlayer()
{
- if (FindPlayerVehicle() != nil) {
- FindPlayerVehicle()->m_nPacManPickupsCarried = 0;
- FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier;
- FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier;
- FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
- }
}
void
@@ -1493,54 +1653,60 @@ CPed::CreateDeadPedMoney(void)
int mi = GetModelIndex();
- if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
+ if ((mi >= MI_COP && mi <= MI_FIREMAN) || (CharCreatedBy == MISSION_CHAR && !bMoneyHasBeenGivenByScript) || bInVehicle)
return;
- int money = CGeneral::GetRandomNumber() % 60;
+ int money = m_nPedMoney;
if (money < 10)
return;
- if (money == 43)
- money = 700;
-
- int pickupCount = money / 40 + 1;
- int moneyPerPickup = money / pickupCount;
-
- for(int i = 0; i < pickupCount; i++) {
- // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.
- float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x;
- float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y;
- bool found = false;
- float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;
- if (found) {
- CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
- }
- }
+ CVector pickupPos = GetPosition();
+ CPickups::CreateSomeMoney(pickupPos, money);
+ m_nPedMoney = 0;
}
void
CPed::CreateDeadPedWeaponPickups(void)
{
- bool found = false;
- float angleToPed;
CVector pickupPos;
if (bInVehicle)
return;
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ for(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
eWeaponType weapon = GetWeapon(i).m_eWeaponType;
int weaponAmmo = GetWeapon(i).m_nAmmoTotal;
- if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0)
+ if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee()))
continue;
- angleToPed = i * 1.75f;
+ int quantity = Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon] / 2);
+ CreateDeadPedPickupCoors(&pickupPos.x, &pickupPos.y, &pickupPos.z);
+ pickupPos.z += 0.3f;
+ if (!CPickups::TryToMerge_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, quantity, false)) {
+ CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, quantity));
+ }
+ }
+ ClearWeapons();
+}
+
+void
+CPed::CreateDeadPedPickupCoors(float *x, float *y, float *z)
+{
+ bool found = false;
+ CVector pickupPos;
+
+#define NUMBER_OF_ATTEMPTS 32
+ for (int i = 0; i < NUMBER_OF_ATTEMPTS; i++) {
+
pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
+ pickupPos.x = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x;
+ pickupPos.y = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y;
pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+ if (!found)
+ continue;
+
CVector pedPos = GetPosition();
pedPos.z += 0.3f;
@@ -1548,21 +1714,29 @@ CPed::CreateDeadPedWeaponPickups(void)
float distance = pedToPickup.Magnitude();
// outer edge of pickup
- distance = (distance + 0.3f) / distance;
+ distance = (distance + 0.4f) / distance;
CVector pickupPos2 = pedPos;
pickupPos2 += distance * pedToPickup;
- // pickup must be on ground and line to its edge must be clear
- if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) {
- // otherwise try another position (but disregard second check apparently)
- angleToPed += 3.14f;
- pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
- pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
+ if ((pickupPos - FindPlayerCoors()).Magnitude2D() > 2.0f || i > NUMBER_OF_ATTEMPTS / 2) {
+
+ if (i > NUMBER_OF_ATTEMPTS / 2 || !CPickups::TestForPickupsInBubble(pickupPos, 1.3f)) {
+
+ if (CWorld::GetIsLineOfSightClear(pickupPos2, pedPos,
+ true, i < NUMBER_OF_ATTEMPTS / 2, false, i < NUMBER_OF_ATTEMPTS / 2, false, false, false)) {
+
+ if (i > NUMBER_OF_ATTEMPTS / 2 || !CWorld::TestSphereAgainstWorld(pickupPos, 1.2f, nil, false, true, false, false, false, false)) {
+ *x = pickupPos.x;
+ *y = pickupPos.y;
+ *z = pickupPos.z;
+ return;
+ }
+ }
+ }
}
- if (found)
- CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
}
- ClearWeapons();
+ *x = GetPosition().x;
+ *y = GetPosition().y;
+ *z = GetPosition().z + 0.4f;
+#undef NUMBER_OF_ATTEMPTS
} \ No newline at end of file
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index 4e1c7643..0de7f827 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -8,6 +8,7 @@ enum ePickupType
PICKUP_ON_STREET,
PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT,
+ PICKUP_ONCE_TIMEOUT_SLOW,
PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY,
@@ -18,6 +19,9 @@ enum ePickupType
PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW,
+ PICKUP_ASSET_REVENUE,
+ PICKUP_PROPERTY_LOCKED,
+ PICKUP_PROPERTY_FORSALE,
PICKUP_NUMOFTYPES
};
@@ -29,20 +33,29 @@ class CPlayerPed;
class CPickup
{
public:
- uint8 m_eType;
- bool m_bRemoved;
- uint16 m_nQuantity;
+ CVector m_vecPos;
+ float m_fRevenue;
CObject *m_pObject;
+ CObject *m_pExtraObject;
+ uint32 m_nQuantity;
uint32 m_nTimer;
+ uint16 m_nMoneySpeed;
int16 m_eModelIndex;
uint16 m_nIndex;
- CVector m_vecPos;
+ char m_sTextKey[8];
+ uint8 m_eType;
+ bool m_bRemoved;
+ uint8 m_bWasAmmoCollected:1;
+ uint8 m_bWasControlMessageShown:1;
- CObject *GiveUsAPickUpObject(int32 handle);
+ CObject *GiveUsAPickUpObject(CObject **object, CObject **extraObject, int32 handle, int32 extraHandle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
+ void GetRidOfObjects();
+ void ExtractAmmoFromPickup(CPlayerPed *player);
+ void ProcessGunShot(CVector *vec1, CVector *vec2);
private:
inline bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
- inline bool CanBePickedUp(CPlayerPed *player);
+ inline bool CanBePickedUp(CPlayerPed *player, int playerId);
inline void Remove();
};
@@ -54,8 +67,9 @@ struct tPickupMessage
eWeaponType m_weaponType;
CVector2D m_dist;
CRGBA m_color;
- uint8 m_bOutOfStock : 1;
+ uint8 m_bOutOfStock;
uint8 m_quantity;
+ uint16 money;
};
class CPickups
@@ -65,6 +79,8 @@ class CPickups
static int16 NumMessages;
static tPickupMessage aMessages[NUMPICKUPMESSAGES];
public:
+ static int32 PlayerOnWeaponPickup;
+
static void Init();
static void Update();
static void RenderPickUpText();
@@ -72,19 +88,22 @@ public:
static void DoMoneyEffects(CEntity *ent);
static void DoMineEffects(CEntity *ent);
static void DoPickUpEffects(CEntity *ent);
- static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
+ static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate = 0, bool highPriority = false, char* pText = nil);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex);
- static void RemoveAllFloatingPickups();
static void AddToCollectedPickupsArray(int32 index);
static bool IsPickUpPickedUp(int32 pickupId);
static int32 ModelForWeapon(eWeaponType weaponType);
static enum eWeaponType WeaponForModel(int32 model);
- static int32 FindColourIndexForWeaponMI(int32 model);
static int32 GetActualPickupIndex(int32 index);
static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
+ static bool TestForPickupsInBubble(CVector pos, float range);
+ static bool TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused);
+ static void CreateSomeMoney(CVector, int);
+ static void DetonateMinesHitByGunShot(CVector *vec1, CVector *vec2);
+ static void RemoveUnnecessaryPickups(const CVector& center, float radius);
static void Load(uint8 *buf, uint32 size);
static void Save(uint8 *buf, uint32 *size);
@@ -95,11 +114,16 @@ public:
static CVehicle *pPlayerVehicle;
static CVector StaticCamCoors;
static uint32 StaticCamStartTime;
+
+ static void RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType);
+ static CPickup *FindPickUpForThisObject(CEntity*);
};
-extern uint16 AmmoForWeapon[20];
-extern uint16 AmmoForWeapon_OnStreet[20];
-extern uint16 CostOfWeapon[20];
+extern uint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1];
+extern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1];
+extern uint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3];
+
+extern int32 CollectPickupBuffer;
enum ePacmanPickupType
{
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index 7f636ec2..5e6c7cdb 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -9,521 +9,99 @@
#include "Timer.h"
#include "VehicleModelInfo.h"
#include "World.h"
-#include "Frontend.h"
uint16 CRecordDataForGame::RecordingState;
-uint8* CRecordDataForGame::pDataBuffer;
-uint8* CRecordDataForGame::pDataBufferPointer;
-int CRecordDataForGame::FId;
-tGameBuffer CRecordDataForGame::pDataBufferForFrame;
-
-#define MEMORY_FOR_GAME_RECORD (150000)
void CRecordDataForGame::Init(void)
{
RecordingState = STATE_NONE;
- delete[] pDataBuffer;
- pDataBufferPointer = nil;
- pDataBuffer = nil;
-#ifndef GTA_PS2 // this stuff is not present on PS2
- FId = CFileMgr::OpenFile("playback.dat", "r");
- if (FId <= 0) {
- if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0)
- RecordingState = STATE_NONE;
- else {
- CFileMgr::CloseFile(FId);
- FId = CFileMgr::OpenFileForWriting("record.dat");
- RecordingState = STATE_RECORD;
- }
- }
- else {
- RecordingState = STATE_PLAYBACK;
- }
- if (RecordingState == STATE_PLAYBACK) {
- pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
- pDataBuffer = pDataBufferPointer;
- pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
- CFileMgr::CloseFile(FId);
- }
-#else
- RecordingState = STATE_NONE; // second time to make sure
-#endif
}
void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
{
- switch (RecordingState) {
- case STATE_RECORD:
- {
- pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep();
- pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds();
- pDataBufferForFrame.m_nSizeOfPads[0] = 0;
- pDataBufferForFrame.m_nSizeOfPads[1] = 0;
- pDataBufferForFrame.m_nChecksum = CalcGameChecksum();
- uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2;
- uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2;
- uint8* pEndPtr = pController2;
- if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1)
- pEndPtr += 2;
- CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame);
- break;
- }
- case STATE_PLAYBACK:
- if (pDataBufferPointer[8] == (uint8)-1)
- CPad::GetPad(0)->NewState.Clear();
- else {
- tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
- CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds);
- CTimer::SetTimeStep(pData->m_fTimeStep);
- uint8 size1 = pData->m_nSizeOfPads[0];
- uint8 size2 = pData->m_nSizeOfPads[1];
- pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer;
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState);
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState);
- if ((size1 + size2) & 1)
- pDataBufferPointer += 2;
- if (pData->m_nChecksum != CalcGameChecksum())
- printf("Playback out of sync\n");
- }
- }
}
-#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
- do { \
- if (os->field != ns->field){ \
- *buf++ = id; \
- *buf++ = ns->field; \
- } \
- } while (0);
-
uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)
{
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19);
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_STORE
-
-#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break;
uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)
{
- for (uint8 i = 0; i < total; i++) {
- switch (*buf++) {
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19);
- }
- }
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_RESTORE
-
uint16 CRecordDataForGame::CalcGameChecksum(void)
{
- uint32 checksum = 0;
- int i = CPools::GetPedPool()->GetSize();
- while (i--) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x;
- }
- i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x;
- }
- return checksum ^ checksum >> 16;
+ return 0;
}
uint8 CRecordDataForChase::Status;
-int CRecordDataForChase::PositionChanges;
-uint8 CRecordDataForChase::CurrentCar;
-CAutomobile* CRecordDataForChase::pChaseCars[NUM_CHASE_CARS];
-uint32 CRecordDataForChase::AnimStartTime;
-float CRecordDataForChase::AnimTime;
-CCarStateEachFrame* CRecordDataForChase::pBaseMemForCar[NUM_CHASE_CARS];
-float CRecordDataForChase::TimeMultiplier;
-int CRecordDataForChase::FId2;
-
-#define CHASE_SCENE_LENGTH_IN_SECONDS (80)
-#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame
-#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND)
-#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2)
void CRecordDataForChase::Init(void)
{
Status = STATE_NONE;
- PositionChanges = 0;
- CurrentCar = 0;
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- pChaseCars[i] = nil;
- AnimStartTime = 0;
}
void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- {
- if ((CTimer::GetFrameCounter() & 1) == 0)
- StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]);
- if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2)
- return;
- CFileMgr::SetDir("data\\paths");
- sprintf(gString, "chase%d.dat", CurrentCar);
- int fid = CFileMgr::OpenFileForWriting(gString);
- uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame);
- printf("FileSize:%d\n", fs);
- CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs);
- CFileMgr::CloseFile(fid);
- CFileMgr::SetDir("");
- sprintf(gString, "car%d.max", CurrentCar);
- int fid2 = CFileMgr::OpenFileForWriting(gString);
- for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) {
- // WTF? Was it ever used?
-#ifdef FIX_BUGS
- CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar];
-#else
- CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar];
-#endif
- CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- CVector up = CrossProduct(right, forward);
- sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", right.x, right.y, right.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", up.x, up.y, up.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- }
- CFileMgr::CloseFile(fid2);
- }
- case STATE_PLAYBACK:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- case STATE_PLAYBACK_INIT:
- break;
- }
}
-struct tCoors {
- CVector pos;
- float angle;
-};
-
-// I guess developer was filling this with actual data before running the game
-tCoors NewCoorsForRecordedCars[7];
-
void CRecordDataForChase::SaveOrRetrieveCarPositions(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (i != CurrentCar && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- }
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[CurrentCar]->GetMatrix().UpdateRW();
- pChaseCars[CurrentCar]->UpdateRwFrame();
- }
- if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) {
- if (!CPad::GetPad(0)->GetRightShockJustDown()) {
- pChaseCars[CurrentCar]->SetPosition(NewCoorsForRecordedCars[PositionChanges].pos);
- pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle));
- ++PositionChanges;
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING) {
- Status = STATE_RECORD;
- pChaseCars[CurrentCar]->SetStatus(STATUS_PLAYER);
- }
- }
- break;
- case STATE_PLAYBACK_INIT:
- Status = STATE_PLAYBACK;
- break;
- case STATE_PLAYBACK:
- {
- TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds();
- float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * Min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier);
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pBaseMemForCar[i])
- continue;
- if (!pChaseCars[i])
- continue;
- if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) {
- int FlooredEOFTime = EndOfFrameTime;
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false);
- CMatrix tmp;
- float dp = EndOfFrameTime - FlooredEOFTime;
- RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]);
- pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp;
- pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp;
- pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp;
- pChaseCars[i]->GetMatrix().GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp;
- }
- else{
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true);
- if (i == 0)
- pChaseCars[i]->GetMatrix().GetPosition().z += 0.2f;
- }
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- pChaseCars[i]->RemoveAndAdd();
- }
- break;
- }
- }
}
void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)
{
- pState->rightX = INT8_MAX * pCar->GetRight().x;
- pState->rightY = INT8_MAX * pCar->GetRight().y;
- pState->rightZ = INT8_MAX * pCar->GetRight().z;
- pState->forwardX = INT8_MAX * pCar->GetForward().x;
- pState->forwardY = INT8_MAX * pCar->GetForward().y;
- pState->forwardZ = INT8_MAX * pCar->GetForward().z;
- pState->pos = pCar->GetPosition();
- pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x;
- pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y;
- pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z;
- pState->wheel = 20 * pCar->m_fSteerAngle;
- pState->gas = 100 * pCar->m_fGasPedal;
- pState->brake = 100 * pCar->m_fBrakePedal;
- pState->handbrake = pCar->bIsHandbrakeOn;
}
void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)
{
- matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward());
- matrix.GetPosition() = pState->pos;
}
void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)
{
- CVector oldPos = pCar->GetPosition();
- RestoreInfoForMatrix(pCar->GetMatrix(), pState);
- pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f);
- pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- pCar->m_fSteerAngle = pState->wheel / 20.0f;
- pCar->m_fGasPedal = pState->gas / 100.0f;
- pCar->m_fBrakePedal = pState->brake / 100.0f;
- pCar->bIsHandbrakeOn = pState->handbrake;
- if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) {
- if (pCar == pChaseCars[14]) {
- pCar->m_currentColour1 = 58;
- pCar->m_currentColour2 = 1;
- }
- else
- pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2);
- }
- pCar->m_fHealth = Min(pCar->m_fHealth, 500.0f);
- if (stop) {
- pCar->m_fGasPedal = 0.0f;
- pCar->m_fBrakePedal = 0.0f;
- pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pCar->bIsHandbrakeOn = false;
- }
}
void CRecordDataForChase::ProcessControlCars(void)
{
- if (Status != STATE_PLAYBACK)
- return;
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pChaseCars[i])
- pChaseCars[i]->ProcessControl();
- }
}
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
{
- // may be wrong
- if (Status == STATE_PLAYBACK_INIT) // this is useless but ps2 def checks if it's STATE_PLAYBACK_INIT
- return false;
-
- if (Status == STATE_RECORD)
- return pad != 0;
-
return false;
}
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
{
- CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
- CStreaming::LoadAllRequestedModels(false);
- if (!CStreaming::HasModelLoaded(mi))
- return;
- CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE);
- pCar->SetPosition(pos);
- pCar->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
- pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle));
- pCar->pDriver = nil;
- pCar->m_currentColour1 = colour1;
- pCar->m_currentColour2 = colour2;
- CWorld::Add(pCar);
- *ppCar = pCar;
}
void RemoveUnusedCollision(void)
{
- static const char* dontDeleteArray[] = {
- "rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
- "road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
- "cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04",
- "com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22"
- };
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_GENERIC;
- CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
}
void CRecordDataForChase::StartChaseScene(float startTime)
{
- char filename[28];
- SetUpCarsForChaseScene();
- Status = STATE_PLAYBACK;
- AnimTime = startTime;
- AnimStartTime = CTimer::GetTimeInMilliseconds();
-#ifdef NO_ISLAND_LOADING
- if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_LOW)
-#endif
- RemoveUnusedCollision();
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- CGame::TidyUpMemory(true, true);
- CStreaming::ImGonnaUseStreamingMemory();
- CFileMgr::SetDir("data\\paths");
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pChaseCars[i]) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- sprintf(filename, "chase%d.dat", i);
- FId2 = CFileMgr::OpenFile(filename, "rb");
- if (FId2 <= 0) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING];
- for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) {
- CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame));
- CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1);
- }
- CFileMgr::CloseFile(FId2);
- }
- CFileMgr::SetDir("");
- CStreaming::IHaveUsedStreamingMemory();
- TimeMultiplier = 0.0f;
}
void CRecordDataForChase::CleanUpChaseScene(void)
{
- if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK)
- return;
- Status = STATE_NONE;
- CleanUpCarsForChaseScene();
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pBaseMemForCar[i]) {
- delete[] pBaseMemForCar[i];
- pBaseMemForCar[i] = nil;
- }
- }
}
void CRecordDataForChase::SetUpCarsForChaseScene(void)
{
- GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1);
- GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1);
- GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6);
- GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5);
- GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53);
- GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1);
- GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10);
- GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1);
- GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6);
- GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1);
- GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76);
- GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75);
- GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0);
}
void CRecordDataForChase::CleanUpCarsForChaseScene(void)
{
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- RemoveCarFromChase(i);
}
void CRecordDataForChase::RemoveCarFromChase(int32 i)
{
- if (!pChaseCars[i])
- return;
- CWorld::Remove(pChaseCars[i]);
- delete pChaseCars[i];
- pChaseCars[i] = nil;
}
CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)
{
- CVehicle* pVehicle = pChaseCars[i];
- pChaseCars[i] = nil;
- pVehicle->SetStatus(STATUS_PHYSICS);
- return pVehicle;
+ return nil;
}
diff --git a/src/control/Remote.cpp b/src/control/Remote.cpp
index 904e9023..047b19f3 100644
--- a/src/control/Remote.cpp
+++ b/src/control/Remote.cpp
@@ -35,17 +35,24 @@ CRemote::GivePlayerRemoteControlledCar(float x, float y, float z, float rot, uin
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = car;
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle);
- TheCamera.TakeControl(car, CCam::MODE_BEHINDCAR, INTERPOLATION, CAMCONTROL_SCRIPT);
+ if (car->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE || car->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI) {
+ TheCamera.TakeControl(car, CCam::MODE_CAM_ON_A_STRING, INTERPOLATION, CAMCONTROL_SCRIPT);
+ TheCamera.SetZoomValueCamStringScript(0);
+ } else
+ TheCamera.TakeControl(car, CCam::MODE_BEHINDCAR, INTERPOLATION, CAMCONTROL_SCRIPT);
}
void
-CRemote::TakeRemoteControlledCarFromPlayer(void)
+CRemote::TakeRemoteControlledCarFromPlayer(bool blowUp)
{
- CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy = RANDOM_VEHICLE;
- CCarCtrl::NumMissionCars--;
- CCarCtrl::NumRandomCars++;
+ if (CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
+ CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy = RANDOM_VEHICLE;
+ CCarCtrl::NumMissionCars--;
+ CCarCtrl::NumRandomCars++;
+ }
CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bIsLocked = false;
CWorld::Players[CWorld::PlayerInFocus].m_nTimeLostRemoteCar = CTimer::GetTimeInMilliseconds();
CWorld::Players[CWorld::PlayerInFocus].m_bInRemoteMode = true;
- CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bRemoveFromWorld = true;
+ CWorld::Players[CWorld::PlayerInFocus].field_D5 = blowUp;
+ CWorld::Players[CWorld::PlayerInFocus].field_D6 = true;
}
diff --git a/src/control/Remote.h b/src/control/Remote.h
index 5e474586..72cabb7c 100644
--- a/src/control/Remote.h
+++ b/src/control/Remote.h
@@ -4,5 +4,5 @@ class CRemote
{
public:
static void GivePlayerRemoteControlledCar(float, float, float, float, uint16);
- static void TakeRemoteControlledCarFromPlayer(void);
+ static void TakeRemoteControlledCarFromPlayer(bool blowUp = true);
};
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index b9b5530c..71b28f7a 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1,19 +1,22 @@
#include "common.h"
#ifdef GTA_REPLAY
+#include "AnimBlendAssocGroup.h"
#include "AnimBlendAssociation.h"
+#include "Bike.h"
#include "Boat.h"
#include "SpecialFX.h"
#include "CarCtrl.h"
#include "CivilianPed.h"
+#include "CopPed.h"
#include "Wanted.h"
#include "Clock.h"
#include "DMAudio.h"
#include "Draw.h"
+#include "Explosion.h"
#include "FileMgr.h"
-#ifdef FIX_BUGS
#include "Fire.h"
+#include "Frontend.h"
#include "Garages.h"
-#endif
#include "Heli.h"
#include "main.h"
#include "Matrix.h"
@@ -21,15 +24,15 @@
#include "ModelInfo.h"
#include "Object.h"
#include "Pad.h"
+#include "Particle.h"
+#include "PedAttractor.h"
#include "Phones.h"
#include "Pickups.h"
#include "Plane.h"
#include "Pools.h"
#include "Population.h"
-#ifdef FIX_BUGS
#include "Projectile.h"
#include "ProjectileInfo.h"
-#endif
#include "Replay.h"
#include "References.h"
#include "Pools.h"
@@ -37,6 +40,7 @@
#include "RwHelper.h"
#include "CutsceneMgr.h"
#include "Skidmarks.h"
+#include "Stinger.h"
#include "Streaming.h"
#include "Timer.h"
#include "Train.h"
@@ -46,6 +50,8 @@
#include "Text.h"
#include "Camera.h"
#include "Radar.h"
+#include "Fluff.h"
+#include "WaterCreatures.h"
uint8 CReplay::Mode;
CAddressInReplayBuffer CReplay::Record;
@@ -55,7 +61,7 @@ CAutomobile *CReplay::pBuf1;
uint8 *CReplay::pBuf2;
CPlayerPed *CReplay::pBuf3;
uint8 *CReplay::pBuf4;
-CCutsceneHead *CReplay::pBuf5;
+CCutsceneObject *CReplay::pBuf5;
uint8 *CReplay::pBuf6;
CPtrNode *CReplay::pBuf7;
uint8 *CReplay::pBuf8;
@@ -109,12 +115,32 @@ bool CReplay::bPlayerInRCBuggy;
float CReplay::fDistanceLookAroundCam;
float CReplay::fBetaAngleLookAroundCam;
float CReplay::fAlphaAngleLookAroundCam;
-#ifdef FIX_BUGS
+int CReplay::ms_nNumCivMale_Stored;
+int CReplay::ms_nNumCivFemale_Stored;
+int CReplay::ms_nNumCop_Stored;
+int CReplay::ms_nNumEmergency_Stored;
+int CReplay::ms_nNumGang1_Stored;
+int CReplay::ms_nNumGang2_Stored;
+int CReplay::ms_nNumGang3_Stored;
+int CReplay::ms_nNumGang4_Stored;
+int CReplay::ms_nNumGang5_Stored;
+int CReplay::ms_nNumGang6_Stored;
+int CReplay::ms_nNumGang7_Stored;
+int CReplay::ms_nNumGang8_Stored;
+int CReplay::ms_nNumGang9_Stored;
+int CReplay::ms_nNumDummy_Stored;
+int CReplay::ms_nTotalCarPassengerPeds_Stored;
+int CReplay::ms_nTotalCivPeds_Stored;
+int CReplay::ms_nTotalGangPeds_Stored;
+int CReplay::ms_nTotalPeds_Stored;
+int CReplay::ms_nTotalMissionPeds_Stored;
uint8* CReplay::pGarages;
CFire* CReplay::FireArray;
uint32 CReplay::NumOfFires;
uint8* CReplay::paProjectileInfo;
uint8* CReplay::paProjectiles;
+uint8 CReplay::CurrArea;
+#ifdef FIX_BUGS
int CReplay::nHandleOfPlayerPed[NUMPLAYERS];
#endif
@@ -123,9 +149,15 @@ static void(*CBArray[])(CAnimBlendAssociation*, void*) =
nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB,
&CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB,
&CPed::PedAnimPullPedOutCB, &CPed::PedAnimDoorCloseCB, &CPed::PedSetInCarCB, &CPed::PedSetOutCarCB, &CPed::PedAnimAlignCB,
- &CPed::PedSetDraggedOutCarCB, &CPed::PedAnimStepOutCarCB, &CPed::PedSetInTrainCB, &CPed::PedSetOutTrainCB, &CPed::FinishedAttackCB,
+ &CPed::PedSetDraggedOutCarCB, &CPed::PedAnimStepOutCarCB, &CPed::PedSetInTrainCB,
+#ifdef GTA_TRAIN
+ &CPed::PedSetOutTrainCB,
+#endif
+ &CPed::FinishedAttackCB,
&CPed::FinishFightMoveCB, &PhonePutDownCB, &PhonePickUpCB, &CPed::PedAnimDoorCloseRollingCB, &CPed::FinishJumpCB,
- &CPed::PedLandCB, &FinishFuckUCB, &CPed::RestoreHeadingRateCB, &CPed::PedSetQuickDraggedOutCarPositionCB, &CPed::PedSetDraggedOutCarPositionCB
+ &CPed::PedLandCB, &CPed::RestoreHeadingRateCB, &CPed::PedSetQuickDraggedOutCarPositionCB, &CPed::PedSetDraggedOutCarPositionCB,
+ &CPed::PedSetPreviousStateCB, &CPed::FinishedReloadCB, &CPed::PedSetGetInCarPositionCB,
+ &CPed::PedAnimShuffleCB, &CPed::DeleteSunbatheIdleAnimCB, &StartTalkingOnMobileCB, &FinishTalkingOnMobileCB
};
static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*))
@@ -221,6 +253,7 @@ void CReplay::Init(void)
SlowMotion = 1;
FramesActiveLookAroundCam = 0;
bDoLoadSceneWhenDone = false;
+ MarkEverythingAsNew();
}
void CReplay::DisableReplays(void)
@@ -236,8 +269,10 @@ void CReplay::EnableReplays(void)
void PlayReplayFromHD(void);
void CReplay::Update(void)
{
- if (CCutsceneMgr::IsCutsceneProcessing() || CTimer::GetIsPaused())
+ if (CCutsceneMgr::IsCutsceneProcessing() || CPad::GetPad(0)->ArePlayerControlsDisabled() || CScriptPaths::IsOneActive() || FrontEndMenuManager.GetIsMenuActive()) {
+ Init();
return;
+ }
switch (Mode){
case MODE_RECORD:
RecordThisFrame();
@@ -268,13 +303,16 @@ void CReplay::Update(void)
void CReplay::RecordThisFrame(void)
{
-#ifdef FIX_REPLAY_BUGS
- uint32 memory_required = sizeof(tGeneralPacket) + sizeof(tClockPacket) + sizeof(tWeatherPacket) + sizeof(tTimerPacket);
+ uint32 memory_required = sizeof(tGeneralPacket) + sizeof(tClockPacket) + sizeof(tWeatherPacket) + sizeof(tTimerPacket) + sizeof(tMiscPacket);
CVehiclePool* vehiclesT = CPools::GetVehiclePool();
for (int i = 0; i < vehiclesT->GetSize(); i++) {
CVehicle* v = vehiclesT->GetSlot(i);
- if (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN)
- memory_required += sizeof(tVehicleUpdatePacket);
+ if (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN) {
+ if (v->IsBike())
+ memory_required += sizeof(tBikeUpdatePacket);
+ else
+ memory_required += sizeof(tVehicleUpdatePacket);
+ }
}
CPedPool* pedsT = CPools::GetPedPool();
for (int i = 0; i < pedsT->GetSize(); i++) {
@@ -292,17 +330,8 @@ void CReplay::RecordThisFrame(void)
memory_required += sizeof(tBulletTracePacket);
}
memory_required += sizeof(tEndOfFramePacket) + 1; // 1 for Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
- if (Record.m_nOffset + memory_required > REPLAYBUFFERSIZE) {
- Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
- BufferStatus[Record.m_bSlot] = REPLAYBUFFER_PLAYBACK;
- Record.m_bSlot = (Record.m_bSlot + 1) % NUM_REPLAYBUFFERS;
- BufferStatus[Record.m_bSlot] = REPLAYBUFFER_RECORD;
- Record.m_pBase = Buffers[Record.m_bSlot];
- Record.m_nOffset = 0;
- *Record.m_pBase = REPLAYPACKET_END;
- MarkEverythingAsNew();
- }
-#endif
+ if (Record.m_nOffset + memory_required > REPLAYBUFFERSIZE - 16)
+ GoToNextBlock();
tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];
general->type = REPLAYPACKET_GENERAL;
general->camera_pos.CopyOnlyMatrix(TheCamera.GetMatrix());
@@ -327,8 +356,12 @@ void CReplay::RecordThisFrame(void)
CVehiclePool* vehicles = CPools::GetVehiclePool();
for (int i = 0; i < vehicles->GetSize(); i++){
CVehicle* v = vehicles->GetSlot(i);
- if (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN)
- StoreCarUpdate(v, i);
+ if (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN) {
+ if (v->IsBike())
+ StoreBikeUpdate(v, i);
+ else
+ StoreCarUpdate(v, i);
+ }
}
CPedPool* peds = CPools::GetPedPool();
for (int i = 0; i < peds->GetSize(); i++) {
@@ -352,23 +385,27 @@ void CReplay::RecordThisFrame(void)
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
bt->type = REPLAYPACKET_BULLET_TRACES;
bt->index = i;
- bt->frames = CBulletTraces::aTraces[i].m_framesInUse;
- bt->lifetime = CBulletTraces::aTraces[i].m_lifeTime;
- bt->inf = CBulletTraces::aTraces[i].m_vecCurrentPos;
- bt->sup = CBulletTraces::aTraces[i].m_vecTargetPos;
+ bt->inf = CBulletTraces::aTraces[i].m_vecStartPos;
+ bt->sup = CBulletTraces::aTraces[i].m_vecEndPos;
Record.m_nOffset += sizeof(*bt);
}
+ tMiscPacket* misc = (tMiscPacket*)&Record.m_pBase[Record.m_nOffset];
+ misc->type = REPLAYPACKET_MISC;
+ misc->cam_shake_start = TheCamera.m_uiCamShakeStart;
+ misc->cam_shake_strength = TheCamera.m_fCamShakeForce;
+ misc->cur_area = CGame::currArea;
+ misc->video_cam = CSpecialFX::bVideoCam;
+ misc->lift_cam = CSpecialFX::bLiftCam;
+ Record.m_nOffset += sizeof(*misc);
tEndOfFramePacket* eof = (tEndOfFramePacket*)&Record.m_pBase[Record.m_nOffset];
eof->type = REPLAYPACKET_ENDOFFRAME;
Record.m_nOffset += sizeof(*eof);
Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
-#ifndef FIX_REPLAY_BUGS
- if (Record.m_nOffset <= REPLAYBUFFERSIZE - 3000){
- /* Unsafe assumption which can cause buffer overflow
- * if size of next frame exceeds 3000 bytes.
- * Most notably it causes various timecyc errors. */
- return;
- }
+}
+
+void CReplay::GoToNextBlock(void)
+{
+ Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
BufferStatus[Record.m_bSlot] = REPLAYBUFFER_PLAYBACK;
Record.m_bSlot = (Record.m_bSlot + 1) % NUM_REPLAYBUFFERS;
BufferStatus[Record.m_bSlot] = REPLAYBUFFER_RECORD;
@@ -376,7 +413,28 @@ void CReplay::RecordThisFrame(void)
Record.m_nOffset = 0;
*Record.m_pBase = REPLAYPACKET_END;
MarkEverythingAsNew();
-#endif
+}
+
+void CReplay::RecordParticle(tParticleType type, const CVector& vecPos, const CVector& vecDir, float fSize, const RwRGBA& color)
+{
+ if (Record.m_nOffset > REPLAYBUFFERSIZE - 16 - sizeof(tParticlePacket))
+ GoToNextBlock();
+ tParticlePacket* pp = (tParticlePacket*)&Record.m_pBase[Record.m_nOffset];
+ pp->type = REPLAYPACKET_PARTICLE;
+ pp->particle_type = type;
+ pp->pos_x = 4.0f * vecPos.x;
+ pp->pos_y = 4.0f * vecPos.y;
+ pp->pos_z = 4.0f * vecPos.z;
+ pp->dir_x = 120.0f * Clamp(vecDir.x, -1.0f, 1.0f);
+ pp->dir_y = 120.0f * Clamp(vecDir.y, -1.0f, 1.0f);
+ pp->dir_z = 120.0f * Clamp(vecDir.z, -1.0f, 1.0f);
+ pp->size = fSize;
+ pp->r = color.red;
+ pp->g = color.green;
+ pp->b = color.blue;
+ pp->a = color.alpha;
+ Record.m_nOffset += sizeof(tParticlePacket);
+ Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
}
void CReplay::StorePedUpdate(CPed *ped, int id)
@@ -387,6 +445,7 @@ void CReplay::StorePedUpdate(CPed *ped, int id)
pp->heading = 128.0f / PI * ped->m_fRotationCur;
pp->matrix.CompressFromFullMatrix(ped->GetMatrix());
pp->assoc_group_id = ped->m_animGroup;
+ pp->is_visible = ped->bIsVisible;
/* Would be more sane to use GetJustIndex(ped->m_pMyVehicle) in following assignment */
if (ped->InVehicle())
pp->vehicle_index = (CPools::GetVehiclePool()->GetIndex(ped->m_pMyVehicle) >> 8) + 1;
@@ -406,21 +465,25 @@ void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state)
state->animId = main->animId;
state->time = 255.0f / 4.0f * Clamp(main->currentTime, 0.0f, 4.0f);
state->speed = 255.0f / 3.0f * Clamp(main->speed, 0.0f, 3.0f);
+ state->groupId = main->groupId;
}else{
state->animId = 3;
state->time = 0;
state->speed = 85;
+ state->groupId = 0;
}
if (second) {
state->secAnimId = second->animId;
state->secTime = 255.0f / 4.0f * Clamp(second->currentTime, 0.0f, 4.0f);
state->secSpeed = 255.0f / 3.0f * Clamp(second->speed, 0.0f, 3.0f);
state->blendAmount = 255.0f / 2.0f * Clamp(blend_amount, 0.0f, 2.0f);
+ state->secGroupId = second->groupId;
}else{
state->secAnimId = 0;
state->secTime = 0;
state->secSpeed = 0;
state->blendAmount = 0;
+ state->secGroupId = 0;
}
CAnimBlendAssociation* partial = RpAnimBlendClumpGetMainPartialAssociation((RpClump*)ped->m_rwObject);
if (partial) {
@@ -428,11 +491,13 @@ void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state)
state->partAnimTime = 255.0f / 4.0f * Clamp(partial->currentTime, 0.0f, 4.0f);
state->partAnimSpeed = 255.0f / 3.0f * Clamp(partial->speed, 0.0f, 3.0f);
state->partBlendAmount = 255.0f / 2.0f * Clamp(partial->blendAmount, 0.0f, 2.0f);
+ state->partGroupId = partial->groupId;
}else{
state->partAnimId = 0;
state->partAnimTime = 0;
state->partAnimSpeed = 0;
state->partBlendAmount = 0;
+ state->partGroupId = 0;
}
}
@@ -445,10 +510,9 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
state->aCurTime[i] = 255.0f / 4.0f * Clamp(assoc->currentTime, 0.0f, 4.0f);
state->aSpeed[i] = 255.0f / 3.0f * Clamp(assoc->speed, 0.0f, 3.0f);
state->aBlendAmount[i] = 255.0f / 2.0f * Clamp(assoc->blendAmount, 0.0f, 2.0f);
-#ifdef FIX_REPLAY_BUGS
state->aBlendDelta[i] = 127.0f / 32.0f * Clamp(assoc->blendDelta, -16.0f, 16.0f);
-#endif
state->aFlags[i] = assoc->flags;
+ state->aGroupId[i] = assoc->groupId;
if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {
state->aFunctionCallbackID[i] = FindCBFunctionID(assoc->callback);
if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)
@@ -462,6 +526,7 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
state->aSpeed[i] = 85;
state->aFunctionCallbackID[i] = 0;
state->aFlags[i] = 0;
+ state->aGroupId[i] = 0;
}
}
for (int i = 0; i < NUM_PARTIAL_ANIMS_IN_REPLAY; i++) {
@@ -471,10 +536,9 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
state->aCurTime2[i] = 255.0f / 4.0f * Clamp(assoc->currentTime, 0.0f, 4.0f);
state->aSpeed2[i] = 255.0f / 3.0f * Clamp(assoc->speed, 0.0f, 3.0f);
state->aBlendAmount2[i] = 255.0f / 2.0f * Clamp(assoc->blendAmount, 0.0f, 2.0f);
-#ifdef FIX_REPLAY_BUGS
state->aBlendDelta2[i] = 127.0f / 16.0f * Clamp(assoc->blendDelta, -16.0f, 16.0f);
-#endif
state->aFlags2[i] = assoc->flags;
+ state->aGroupId2[i] = assoc->groupId;
if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {
state->aFunctionCallbackID2[i] = FindCBFunctionID(assoc->callback);
if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)
@@ -489,6 +553,7 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
state->aSpeed2[i] = 85;
state->aFunctionCallbackID2[i] = 0;
state->aFlags2[i] = 0;
+ state->aGroupId2[i] = 0;
}
}
}
@@ -510,7 +575,7 @@ void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayB
ped->GetMatrix() += CMatrix(interpolation) * ped_matrix;
if (pp->vehicle_index) {
ped->m_pMyVehicle = CPools::GetVehiclePool()->GetSlot(pp->vehicle_index - 1);
- ped->bInVehicle = pp->vehicle_index;
+ ped->bInVehicle = true;
}
else {
ped->m_pMyVehicle = nil;
@@ -521,21 +586,39 @@ void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayB
if (ped == FindPlayerPed())
((CPlayerPed*)ped)->ReApplyMoveAnims();
}
+ ped->bIsVisible = pp->is_visible;
+ if (FramesActiveLookAroundCam && ped->m_nPedType == PEDTYPE_PLAYER1)
+ ped->bIsVisible = true;
RetrievePedAnimation(ped, &pp->anim_state);
ped->RemoveWeaponModel(-1);
- if (pp->weapon_model != (uint8)-1)
- ped->AddWeaponModel(pp->weapon_model);
+ if (pp->weapon_model != (uint16)-1) {
+ if (CStreaming::HasModelLoaded(pp->weapon_model))
+ ped->AddWeaponModel(pp->weapon_model);
+ else
+ CStreaming::RequestModel(pp->weapon_model, 0);
+ }
CWorld::Remove(ped);
CWorld::Add(ped);
buffer->m_nOffset += sizeof(tPedUpdatePacket);
}
+bool HasAnimGroupLoaded(uint8 group)
+{
+ CAnimBlendAssocGroup* pGroup = &CAnimManager::GetAnimAssocGroups()[group];
+ return pGroup->animBlock && pGroup->animBlock->isLoaded;
+}
+
void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)
{
- CAnimBlendAssociation* anim1 = CAnimManager::BlendAnimation(
- (RpClump*)ped->m_rwObject,
- (state->animId > 3) ? ASSOCGRP_STD : ped->m_animGroup,
- (AnimationId)state->animId, 100.0f);
+ CAnimBlendAssociation* anim1;
+ if (state->animId <= ANIM_STD_IDLE)
+ anim1 = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject, ped->m_animGroup, (AnimationId)state->animId, 100.0f);
+ else if (HasAnimGroupLoaded(state->groupId))
+ anim1 = CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, (AssocGroupId)state->groupId, (AnimationId)state->animId, 100.0f);
+ else
+ anim1 = CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_STD_WALK, 100.0f);
+
anim1->SetCurrentTime(state->time * 4.0f / 255.0f);
anim1->speed = state->speed * 3.0f / 255.0f;
anim1->SetBlend(1.0f, 1.0f);
@@ -546,7 +629,7 @@ void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)
float blend = state->blendAmount * 2.0f / 255.0f;
CAnimBlendAssociation* anim2 = CAnimManager::BlendAnimation(
(RpClump*)ped->m_rwObject,
- (state->secAnimId > 3) ? ASSOCGRP_STD : ped->m_animGroup,
+ (state->secAnimId > ANIM_STD_IDLE) ? (AssocGroupId)state->secGroupId : ped->m_animGroup,
(AnimationId)state->secAnimId, 100.0f);
anim2->SetCurrentTime(time);
anim2->speed = speed;
@@ -558,9 +641,9 @@ void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)
float time = state->partAnimTime * 4.0f / 255.0f;
float speed = state->partAnimSpeed * 3.0f / 255.0f;
float blend = state->partBlendAmount * 2.0f / 255.0f;
- if (blend > 0.0f && state->partAnimId != ANIM_STD_IDLE){
+ if (blend > 0.0f && state->partAnimId != ANIM_STD_IDLE && HasAnimGroupLoaded(state->partGroupId)){
CAnimBlendAssociation* anim3 = CAnimManager::BlendAnimation(
- (RpClump*)ped->m_rwObject, ASSOCGRP_STD, (AnimationId)state->partAnimId, 1000.0f);
+ (RpClump*)ped->m_rwObject, (AssocGroupId)state->partGroupId, (AnimationId)state->partAnimId, 1000.0f);
anim3->SetCurrentTime(time);
anim3->speed = speed;
anim3->SetBlend(blend, 0.0f);
@@ -570,33 +653,20 @@ void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)
void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state)
{
-#ifdef FIX_REPLAY_BUGS
CAnimBlendAssociation* assoc;
for (int i = 0; ((assoc = RpAnimBlendClumpGetMainAssociation_N(ped->GetClump(), i))); i++)
assoc->SetBlend(0.0f, -1.0f);
for (int i = 0; ((assoc = RpAnimBlendClumpGetMainPartialAssociation_N(ped->GetClump(), i))); i++)
assoc->SetBlend(0.0f, -1.0f);
-#endif
for (int i = 0; i < NUM_MAIN_ANIMS_IN_REPLAY; i++) {
if (state->aAnimId[i] == ANIM_STD_NUM)
continue;
-#ifdef FIX_REPLAY_BUGS
CAnimBlendAssociation* anim = CAnimManager::AddAnimation(ped->GetClump(),
- state->aAnimId[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
+ state->aAnimId[i] > ANIM_STD_IDLE ? (AssocGroupId)state->aGroupId[i] : ped->m_animGroup,
(AnimationId)state->aAnimId[i]);
-#else
- CAnimBlendAssociation* anim = CAnimManager::BlendAnimation(
- (RpClump*)ped->m_rwObject,
- state->aAnimId[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
- (AnimationId)state->aAnimId[i], 100.0f);
-#endif
anim->SetCurrentTime(state->aCurTime[i] * 4.0f / 255.0f);
anim->speed = state->aSpeed[i] * 3.0f / 255.0f;
-#ifdef FIX_REPLAY_BUGS
anim->SetBlend(state->aBlendAmount[i] * 2.0f / 255.0f, state->aBlendDelta[i] * 16.0f / 127.0f);
-#else
- anim->SetBlend(state->aBlendAmount[i], 1.0f);
-#endif
anim->flags = state->aFlags[i];
uint8 callback = state->aFunctionCallbackID[i];
if (!callback)
@@ -609,23 +679,12 @@ void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationSt
for (int i = 0; i < NUM_PARTIAL_ANIMS_IN_REPLAY; i++) {
if (state->aAnimId2[i] == ANIM_STD_NUM)
continue;
-#ifdef FIX_REPLAY_BUGS
CAnimBlendAssociation* anim = CAnimManager::AddAnimation(ped->GetClump(),
- state->aAnimId2[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
+ state->aAnimId2[i] > ANIM_STD_IDLE ? (AssocGroupId)state->aGroupId2[i] : ped->m_animGroup,
(AnimationId)state->aAnimId2[i]);
-#else
- CAnimBlendAssociation* anim = CAnimManager::BlendAnimation(
- (RpClump*)ped->m_rwObject,
- state->aAnimId2[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
- (AnimationId)state->aAnimId2[i], 100.0f);
-#endif
anim->SetCurrentTime(state->aCurTime2[i] * 4.0f / 255.0f);
anim->speed = state->aSpeed2[i] * 3.0f / 255.0f;
-#ifdef FIX_REPLAY_BUGS
anim->SetBlend(state->aBlendAmount2[i] * 2.0f / 255.0f, state->aBlendDelta2[i] * 16.0f / 127.0f);
-#else
- anim->SetBlend(state->aBlendAmount2[i], 1.0f);
-#endif
anim->flags = state->aFlags2[i];
uint8 callback = state->aFunctionCallbackID2[i];
if (!callback)
@@ -664,7 +723,6 @@ void CReplay::PlaybackThisFrame(void)
// next two functions are only found in mobile version
// most likely they were optimized out for being unused
-
void CReplay::TriggerPlaybackLastCoupleOfSeconds(uint32 start, uint8 cam_mode, float cam_x, float cam_y, float cam_z, uint32 slomo)
{
if (Mode != MODE_RECORD)
@@ -718,9 +776,47 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id)
vp->door_status |= BIT(i);
}
}
+ if (vehicle->GetModelIndex() == MI_SKIMMER)
+ vp->skimmer_speed = 50.0f * ((CBoat*)vehicle)->m_fMovingSpeed;
+ vp->render_scorched = vehicle->bRenderScorched;
+ vp->vehicle_type = vehicle->m_vehType;
Record.m_nOffset += sizeof(tVehicleUpdatePacket);
}
+void CReplay::StoreBikeUpdate(CVehicle* vehicle, int id)
+{
+ CBike* bike = (CBike*)vehicle;
+ tBikeUpdatePacket* vp = (tBikeUpdatePacket*)&Record.m_pBase[Record.m_nOffset];
+ vp->type = REPLAYPACKET_BIKE;
+ vp->index = id;
+ vp->matrix.CompressFromFullMatrix(vehicle->GetMatrix());
+ vp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */
+ vp->acceleration = vehicle->m_fGasPedal * 100.0f;
+#ifdef FIX_BUGS // originally it's undefined behaviour - different fields are copied on PC and mobile
+ for (int i = 0; i < 2; i++)
+ vp->wheel_rotation[i] = 128.0f / PI * bike->m_aWheelRotation[i];
+ for (int i = 0; i < 2; i++)
+ vp->wheel_rotation[i + 2] = 128.0f / PI * bike->m_aWheelSpeed[i];
+ for (int i = 0; i < 4; i++)
+ vp->wheel_susp_dist[i] = 50.0f * bike->m_aSuspensionSpringRatio[i];
+#else
+ for (int i = 0; i < 4; i++) {
+ vp->wheel_susp_dist[i] = 50.0f * bike->m_aSuspensionSpringRatio[i];
+ vp->wheel_rotation[i] = 128.0f / PI * bike->m_aWheelRotation[i];
+ }
+#endif
+ vp->velocityX = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().x)); /* 8000!? */
+ vp->velocityY = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().y));
+ vp->velocityZ = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().z));
+ vp->mi = vehicle->GetModelIndex();
+ vp->primary_color = vehicle->m_currentColour1;
+ vp->secondary_color = vehicle->m_currentColour2;
+ vp->wheel_state = 50.0f * vehicle->m_fSteerAngle;
+ vp->lean_angle = 50.0f * bike->m_fLeanLRAngle;
+ vp->wheel_angle = 50.0f * bike->m_fWheelAngle;
+ Record.m_nOffset += sizeof(tBikeUpdatePacket);
+}
+
void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer)
{
tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];
@@ -789,20 +885,53 @@ void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressI
CWorld::Add(vehicle);
if (vehicle->IsBoat())
((CBoat*)vehicle)->m_bIsAnchored = false;
+ vehicle->bRenderScorched = vp->render_scorched;
+ if (vehicle->GetModelIndex() == MI_SKIMMER)
+ ((CBoat*)vehicle)->m_fMovingSpeed = vp->skimmer_speed / 50.0f;
}
-bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer){
- /* Mistake. Not even sure what this is even doing here...
- * PlayerWanted is a backup to restore at the end of replay.
- * Setting current wanted pointer to it makes it useless.
- * Causes picking up bribes in replays reducing wanted level bug.
- * Obviously fact of picking them up is a bug on its own,
- * but it doesn't cancel this one.
- */
-#ifndef FIX_REPLAY_BUGS
- FindPlayerPed()->m_pWanted = &PlayerWanted;
+void CReplay::ProcessBikeUpdate(CVehicle* vehicle, float interpolation, CAddressInReplayBuffer* buffer)
+{
+ CBike* bike = (CBike*)vehicle;
+ tBikeUpdatePacket* vp = (tBikeUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];
+ if (!vehicle) {
+ printf("Replay:Car wasn't there");
+ return;
+ }
+ CMatrix vehicle_matrix;
+ vp->matrix.DecompressIntoFullMatrix(vehicle_matrix);
+ vehicle->GetMatrix() = vehicle->GetMatrix() * CMatrix(1.0f - interpolation);
+ vehicle->GetMatrix().GetPosition() *= (1.0f - interpolation);
+ vehicle->GetMatrix() += CMatrix(interpolation) * vehicle_matrix;
+ vehicle->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ vehicle->m_fHealth = 4 * vp->health;
+ vehicle->m_fGasPedal = vp->acceleration / 100.0f;
+ vehicle->m_vecMoveSpeed = CVector(vp->velocityX / 8000.0f, vp->velocityY / 8000.0f, vp->velocityZ / 8000.0f);
+ vehicle->m_fSteerAngle = vp->wheel_state / 50.0f;
+ vehicle->bEngineOn = true;
+#ifdef FIX_BUGS
+ for (int i = 0; i < 2; i++)
+ bike->m_aWheelRotation[i] = vp->wheel_rotation[i] / (128.0f / PI);
+ for (int i = 0; i < 2; i++)
+ bike->m_aWheelSpeed[i] = vp->wheel_rotation[i + 2] / (128.0f / PI);
+ for (int i = 0; i < 4; i++)
+ bike->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;
+#else
+ for (int i = 0; i < 4; i++) {
+ bike->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;
+ bike->m_aWheelRotation[i] = vp->wheel_rotation[i] / (128.0f / PI);
+ }
#endif
+ bike->m_fLeanLRAngle = vp->lean_angle / 50.0f;
+ bike->m_fWheelAngle = vp->wheel_angle / 50.0f;
+ bike->bLeanMatrixClean = false;
+ bike->CalculateLeanMatrix();
+ CWorld::Remove(vehicle);
+ CWorld::Add(vehicle);
+}
+bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer)
+{
CBulletTraces::Init();
float split = 1.0f - interpolation;
int ped_min_index = 0; /* Optimization due to peds and vehicles placed in buffer sequentially. */
@@ -848,20 +977,25 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
CStreaming::RequestModel(mi, 0);
}
else {
- if (mi == MI_DEADDODO || mi == MI_AIRTRAIN) {
- new_v = new(vp->index << 8) CPlane(mi, 2);
- }
- else if (mi == MI_TRAIN) {
+ switch (vp->vehicle_type) {
+ case VEHICLE_TYPE_CAR:
+ new_v = new(vp->index << 8) CAutomobile(mi, 2);
+ break;
+ case VEHICLE_TYPE_BOAT:
+ new_v = new(vp->index << 8) CBoat(mi, 2);
+ break;
+ case VEHICLE_TYPE_TRAIN:
new_v = new(vp->index << 8) CTrain(mi, 2);
- }
- else if (mi == MI_CHOPPER || mi == MI_ESCAPE) {
+ break;
+ case VEHICLE_TYPE_HELI:
new_v = new(vp->index << 8) CHeli(mi, 2);
- }
- else if (CModelInfo::IsBoatModel(mi)){
- new_v = new(vp->index << 8) CBoat(mi, 2);
- }
- else{
- new_v = new(vp->index << 8) CAutomobile(mi, 2);
+ break;
+ case VEHICLE_TYPE_PLANE:
+ new_v = new(vp->index << 8) CPlane(mi, 2);
+ break;
+ case VEHICLE_TYPE_BIKE: // not possible
+ new_v = new(vp->index << 8) CBike(mi, 2);
+ break;
}
new_v->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
vp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix());
@@ -874,15 +1008,51 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
buffer->m_nOffset += sizeof(tVehicleUpdatePacket);
break;
}
+ case REPLAYPACKET_BIKE:
+ {
+ tBikeUpdatePacket* vp = (tBikeUpdatePacket*)&ptr[offset];
+ for (int i = vehicle_min_index; i < vp->index; i++) {
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
+ if (!v)
+ continue;
+ /* Removing vehicles not present in this frame. */
+ CWorld::Remove(v);
+ delete v;
+ }
+ vehicle_min_index = vp->index + 1;
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(vp->index);
+ CVehicle* new_v;
+ if (!v) {
+ int mi = vp->mi;
+ if (CStreaming::ms_aInfoForModel[mi].m_loadState != 1) {
+ CStreaming::RequestModel(mi, 0);
+ }
+ else {
+ new_v = new(vp->index << 8) CBike(mi, 2);
+ new_v->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
+ vp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix());
+ new_v->m_currentColour1 = vp->primary_color;
+ new_v->m_currentColour2 = vp->secondary_color;
+ CWorld::Add(new_v);
+ }
+ }
+ ProcessBikeUpdate(CPools::GetVehiclePool()->GetSlot(vp->index), interpolation, buffer);
+ buffer->m_nOffset += sizeof(tBikeUpdatePacket);
+ break;
+ }
case REPLAYPACKET_PED_HEADER:
{
tPedHeaderPacket* ph = (tPedHeaderPacket*)&ptr[offset];
if (!CPools::GetPedPool()->GetSlot(ph->index)) {
- if (CStreaming::ms_aInfoForModel[ph->mi].m_loadState != 1) {
+ if (!CStreaming::HasModelLoaded(ph->mi) || (ph->mi >= MI_SPECIAL01 && ph->mi < MI_LAST_PED)) {
CStreaming::RequestModel(ph->mi, 0);
}
else {
- CPed* new_p = new(ph->index << 8) CCivilianPed((ePedType)ph->pedtype, ph->mi);
+ CPed* new_p;
+ if (ph->pedtype != PEDTYPE_PLAYER1)
+ new_p = new(ph->index << 8) CCivilianPed((ePedType)ph->pedtype, ph->mi);
+ else
+ new_p = new(ph->index << 8) CPlayerPed();
new_p->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
new_p->GetMatrix().SetUnity();
CWorld::Add(new_p);
@@ -960,11 +1130,35 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
{
tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset];
CBulletTraces::aTraces[pb->index].m_bInUse = true;
- CBulletTraces::aTraces[pb->index].m_framesInUse = pb->frames;
- CBulletTraces::aTraces[pb->index].m_lifeTime = pb->lifetime;
- CBulletTraces::aTraces[pb->index].m_vecCurrentPos = pb->inf;
- CBulletTraces::aTraces[pb->index].m_vecTargetPos = pb->sup;
+ CBulletTraces::aTraces[pb->index].m_vecStartPos = pb->inf;
+ CBulletTraces::aTraces[pb->index].m_vecEndPos = pb->sup;
buffer->m_nOffset += sizeof(tBulletTracePacket);
+ break;
+ }
+ case REPLAYPACKET_PARTICLE:
+ {
+ tParticlePacket* pp = (tParticlePacket*)&ptr[offset];
+ CVector pos(pp->pos_x / 4.0f, pp->pos_y / 4.0f, pp->pos_z / 4.0f);
+ CVector dir(pp->dir_x / 120.0f, pp->dir_y / 120.0f, pp->dir_z / 120.0f);
+ RwRGBA color;
+ color.red = pp->r;
+ color.green = pp->g;
+ color.blue = pp->b;
+ color.alpha = pp->a;
+ CParticle::AddParticle((tParticleType)pp->particle_type, pos, dir, nil, pp->size, color);
+ buffer->m_nOffset += sizeof(tParticlePacket);
+ break;
+ }
+ case REPLAYPACKET_MISC:
+ {
+ tMiscPacket* pm = (tMiscPacket*)&ptr[offset];
+ TheCamera.m_uiCamShakeStart = pm->cam_shake_start;
+ TheCamera.m_fCamShakeForce = pm->cam_shake_strength;
+ CSpecialFX::bVideoCam = pm->video_cam;
+ CSpecialFX::bLiftCam = pm->lift_cam;
+ CGame::currArea = pm->cur_area;
+ buffer->m_nOffset += sizeof(tMiscPacket);
+ break;
}
default:
break;
@@ -1072,6 +1266,8 @@ void CReplay::ProcessReplayCamera(void)
RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));
}
+extern CWeaponEffects gCrossHair;
+
void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene)
{
if (Mode != MODE_RECORD)
@@ -1088,6 +1284,8 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);
DMAudio.SetEffectsFadeVol(0);
DMAudio.SetMusicFadeVol(0);
+ CEscalators::Shutdown();
+ CWaterCreatures::RemoveAll();
int current;
for (current = 0; current < NUM_REPLAYBUFFERS; current++)
if (BufferStatus[current] == REPLAYBUFFER_RECORD)
@@ -1120,6 +1318,13 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
}
if (cam_mode == REPLAYCAMMODE_ASSTORED)
TheCamera.CarZoomIndicator = CAM_ZOOM_CINEMATIC;
+ gCrossHair.m_bActive = false;
+ CExplosion::ClearAllExplosions();
+ CPlaneBanners::Init();
+#ifndef FIX_BUGS // this doesn't do anything useful and accesses destroyed player ped
+ TheCamera.Restore();
+#endif
+ CDraw::SetFOV(70.0f);
}
void CReplay::StoreStuffInMem(void)
@@ -1128,6 +1333,14 @@ void CReplay::StoreStuffInMem(void)
for (int i = 0; i < NUMPLAYERS; i++)
nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed);
#endif
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i >= 0) {
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (!ped)
+ continue;
+ if (ped->m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(ped, ped->m_attractor);
+ }
CPools::GetVehiclePool()->Store(pBuf0, pBuf1);
CPools::GetPedPool()->Store(pBuf2, pBuf3);
CPools::GetObjectPool()->Store(pBuf4, pBuf5);
@@ -1159,9 +1372,28 @@ void CReplay::StoreStuffInMem(void)
OldWeatherType = CWeather::OldWeatherType;
NewWeatherType = CWeather::NewWeatherType;
WeatherInterpolationValue = CWeather::InterpolationValue;
+ CurrArea = CGame::currArea;
TimeStepNonClipped = CTimer::GetTimeStepNonClipped();
TimeStep = CTimer::GetTimeStep();
TimeScale = CTimer::GetTimeScale();
+ ms_nNumCivMale_Stored = CPopulation::ms_nNumCivMale;
+ ms_nNumCivFemale_Stored = CPopulation::ms_nNumCivFemale;
+ ms_nNumCop_Stored = CPopulation::ms_nNumCop;
+ ms_nNumEmergency_Stored = CPopulation::ms_nNumEmergency;
+ ms_nNumGang1_Stored = CPopulation::ms_nNumGang1;
+ ms_nNumGang2_Stored = CPopulation::ms_nNumGang2;
+ ms_nNumGang3_Stored = CPopulation::ms_nNumGang3;
+ ms_nNumGang4_Stored = CPopulation::ms_nNumGang4;
+ ms_nNumGang5_Stored = CPopulation::ms_nNumGang5;
+ ms_nNumGang6_Stored = CPopulation::ms_nNumGang6;
+ ms_nNumGang7_Stored = CPopulation::ms_nNumGang7;
+ ms_nNumGang8_Stored = CPopulation::ms_nNumGang8;
+ ms_nNumGang9_Stored = CPopulation::ms_nNumGang9;
+ ms_nNumDummy_Stored = CPopulation::ms_nNumDummy;
+ ms_nTotalCivPeds_Stored = CPopulation::ms_nTotalCivPeds;
+ ms_nTotalGangPeds_Stored = CPopulation::ms_nTotalGangPeds;
+ ms_nTotalPeds_Stored = CPopulation::ms_nTotalPeds;
+ ms_nTotalMissionPeds_Stored = CPopulation::ms_nTotalMissionPeds;
int size = CPools::GetPedPool()->GetSize();
pPedAnims = new CStoredDetailedAnimationState[size];
for (int i = 0; i < size; i++) {
@@ -1169,7 +1401,6 @@ void CReplay::StoreStuffInMem(void)
if (ped)
StoreDetailedPedAnimation(ped, &pPedAnims[i]);
}
-#ifdef FIX_BUGS
pGarages = new uint8[sizeof(CGarages::aGarages)];
memcpy(pGarages, CGarages::aGarages, sizeof(CGarages::aGarages));
FireArray = new CFire[NUM_FIRES];
@@ -1179,7 +1410,7 @@ void CReplay::StoreStuffInMem(void)
memcpy(paProjectileInfo, gaProjectileInfo, sizeof(gaProjectileInfo));
paProjectiles = new uint8[sizeof(CProjectileInfo::ms_apProjectile)];
memcpy(paProjectiles, CProjectileInfo::ms_apProjectile, sizeof(CProjectileInfo::ms_apProjectile));
-#endif
+ CScriptPaths::Save_ForReplay();
}
void CReplay::RestoreStuffFromMem(void)
@@ -1234,8 +1465,24 @@ void CReplay::RestoreStuffFromMem(void)
ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped);
DMAudio.SetEntityStatus(ped->m_audioEntityId, TRUE);
CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false);
- if (ped->m_wepModelID >= 0)
+ for (int j = 0; j < TOTAL_WEAPON_SLOTS; j++) {
+ int mi1 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModelId;
+ if (mi1 != -1)
+ CStreaming::RequestModel(mi1, STREAMFLAGS_DEPENDENCY);
+ int mi2 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModel2Id;
+ if (mi2 != -1)
+ CStreaming::RequestModel(mi2, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ ped->m_weapons[j].Initialise(ped->m_weapons[j].m_eWeaponType, ped->m_weapons[j].m_nAmmoTotal);
+ }
+ if (ped->m_wepModelID >= 0) {
+ ped->m_pWeaponModel = nil;
+ if (ped->IsPlayer())
+ ((CPlayerPed*)ped)->m_pMinigunTopAtomic = nil;
ped->AddWeaponModel(ped->m_wepModelID);
+ }
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ((CCopPed*)ped)->m_pStinger = new CStinger;
}
i = CPools::GetVehiclePool()->GetSize();
while (--i >= 0) {
@@ -1248,14 +1495,26 @@ void CReplay::RestoreStuffFromMem(void)
vehicle->m_rwObject = nil;
vehicle->m_modelIndex = -1;
vehicle->SetModelIndex(mi);
- if (mi == MI_DODO){
- CAutomobile* dodo = (CAutomobile*)vehicle;
- RpAtomicSetFlags((RpAtomic*)GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0);
- CMatrix tmp1;
- tmp1.Attach(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_RF]), false);
- CMatrix tmp2(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_LF]), false);
- tmp1.GetPosition() += CVector(tmp2.GetPosition().x + 0.1f, 0.0f, tmp2.GetPosition().z);
- tmp1.UpdateRW();
+ if (vehicle->IsCar()) {
+ CAutomobile* car = (CAutomobile*)vehicle;
+ if (mi == MI_DODO) {
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
+ CMatrix tmp1;
+ tmp1.Attach(RwFrameGetMatrix(car->m_aCarNodes[CAR_WHEEL_RF]), false);
+ CMatrix tmp2(RwFrameGetMatrix(car->m_aCarNodes[CAR_WHEEL_LF]), false);
+ tmp1.GetPosition() += CVector(tmp2.GetPosition().x + 0.1f, 0.0f, tmp2.GetPosition().z);
+ tmp1.UpdateRW();
+ }
+ else if (mi == MI_HUNTER) {
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
+ }
+ else if (vehicle->IsRealHeli()) {
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);
+ RpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);
+ }
}
if (vehicle->IsCar()){
CAutomobile* car = (CAutomobile*)vehicle;
@@ -1302,14 +1561,10 @@ void CReplay::RestoreStuffFromMem(void)
if (!object)
continue;
int mi = object->GetModelIndex();
- CStreaming::RequestModel(mi, 0);
- CStreaming::LoadAllRequestedModels(false);
object->m_rwObject = nil;
object->m_modelIndex = -1;
- object->SetModelIndex(mi);
+ object->SetModelIndexNoCreate(mi);
object->GetMatrix().m_attachment = nil;
- if (RwObjectGetType(object->m_rwObject) == rpATOMIC)
- object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)object->m_rwObject)), false);
}
i = CPools::GetDummyPool()->GetSize();
while (--i >= 0) {
@@ -1317,15 +1572,12 @@ void CReplay::RestoreStuffFromMem(void)
if (!dummy)
continue;
int mi = dummy->GetModelIndex();
- CStreaming::RequestModel(mi, 0);
- CStreaming::LoadAllRequestedModels(false);
dummy->m_rwObject = nil;
dummy->m_modelIndex = -1;
- dummy->SetModelIndex(mi);
+ dummy->SetModelIndexNoCreate(mi);
dummy->GetMatrix().m_attachment = nil;
- if (RwObjectGetType(dummy->m_rwObject) == rpATOMIC)
- dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)dummy->m_rwObject)), false);
}
+ ++ClockMinutes;
CTimer::SetTimeInMilliseconds(Time1);
CTimer::SetTimeInMillisecondsNonClipped(Time2);
CTimer::SetPreviousTimeInMilliseconds(Time3);
@@ -1338,6 +1590,25 @@ void CReplay::RestoreStuffFromMem(void)
CWeather::OldWeatherType = OldWeatherType;
CWeather::NewWeatherType = NewWeatherType;
CWeather::InterpolationValue = WeatherInterpolationValue;
+ CGame::currArea = CurrArea;
+ CPopulation::ms_nNumCivMale = ms_nNumCivMale_Stored;
+ CPopulation::ms_nNumCivFemale = ms_nNumCivFemale_Stored;
+ CPopulation::ms_nNumCop = ms_nNumCop_Stored;
+ CPopulation::ms_nNumEmergency = ms_nNumEmergency_Stored;
+ CPopulation::ms_nNumGang1 = ms_nNumGang1_Stored;
+ CPopulation::ms_nNumGang2 = ms_nNumGang2_Stored;
+ CPopulation::ms_nNumGang3 = ms_nNumGang3_Stored;
+ CPopulation::ms_nNumGang4 = ms_nNumGang4_Stored;
+ CPopulation::ms_nNumGang5 = ms_nNumGang5_Stored;
+ CPopulation::ms_nNumGang6 = ms_nNumGang6_Stored;
+ CPopulation::ms_nNumGang7 = ms_nNumGang7_Stored;
+ CPopulation::ms_nNumGang8 = ms_nNumGang8_Stored;
+ CPopulation::ms_nNumGang9 = ms_nNumGang9_Stored;
+ CPopulation::ms_nNumDummy = ms_nNumDummy_Stored;
+ CPopulation::ms_nTotalCivPeds = ms_nTotalCivPeds_Stored;
+ CPopulation::ms_nTotalGangPeds = ms_nTotalGangPeds_Stored;
+ CPopulation::ms_nTotalPeds = ms_nTotalPeds_Stored;
+ CPopulation::ms_nTotalMissionPeds = ms_nTotalMissionPeds_Stored;
for (int i = 0; i < CPools::GetPedPool()->GetSize(); i++) {
CPed* ped = CPools::GetPedPool()->GetSlot(i);
if (!ped)
@@ -1346,7 +1617,6 @@ void CReplay::RestoreStuffFromMem(void)
}
delete[] pPedAnims;
pPedAnims = nil;
-#ifdef FIX_BUGS
memcpy(CGarages::aGarages, pGarages, sizeof(CGarages::aGarages));
delete[] pGarages;
pGarages = nil;
@@ -1360,8 +1630,8 @@ void CReplay::RestoreStuffFromMem(void)
memcpy(CProjectileInfo::ms_apProjectile, paProjectiles, sizeof(CProjectileInfo::ms_apProjectile));
delete[] paProjectiles;
paProjectiles = nil;
- //CExplosion::ClearAllExplosions(); not in III
-#endif
+ CScriptPaths::Load_ForReplay();
+ CExplosion::ClearAllExplosions();
DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);
DMAudio.SetRadioInCar(OldRadioStation);
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
@@ -1499,6 +1769,9 @@ void CReplay::StreamAllNecessaryCarsAndPeds(void)
case REPLAYPACKET_VEHICLE:
CStreaming::RequestModel(((tVehicleUpdatePacket*)&Buffers[slot][offset])->mi, 0);
break;
+ case REPLAYPACKET_BIKE:
+ CStreaming::RequestModel(((tBikeUpdatePacket*)&Buffers[slot][offset])->mi, 0);
+ break;
case REPLAYPACKET_PED_HEADER:
CStreaming::RequestModel(((tPedHeaderPacket*)&Buffers[slot][offset])->mi, 0);
break;
@@ -1595,6 +1868,7 @@ size_t CReplay::FindSizeOfPacket(uint8 type)
switch (type) {
case REPLAYPACKET_END: return 4;
case REPLAYPACKET_VEHICLE: return sizeof(tVehicleUpdatePacket);
+ case REPLAYPACKET_BIKE: return sizeof(tBikeUpdatePacket);
case REPLAYPACKET_PED_HEADER: return sizeof(tPedHeaderPacket);
case REPLAYPACKET_PED_UPDATE: return sizeof(tPedUpdatePacket);
case REPLAYPACKET_GENERAL: return sizeof(tGeneralPacket);
@@ -1603,6 +1877,8 @@ size_t CReplay::FindSizeOfPacket(uint8 type)
case REPLAYPACKET_ENDOFFRAME: return 4;
case REPLAYPACKET_TIMER: return sizeof(tTimerPacket);
case REPLAYPACKET_BULLET_TRACES:return sizeof(tBulletTracePacket);
+ case REPLAYPACKET_PARTICLE: return sizeof(tParticlePacket);
+ case REPLAYPACKET_MISC: return sizeof(tMiscPacket);
default: assert(false); break;
}
return 0;
@@ -1628,7 +1904,7 @@ void CReplay::Display()
CFont::SetCentreOff();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200));
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
if (Mode == MODE_PLAYBACK)
CFont::PrintString(SCREEN_WIDTH/15, SCREEN_HEIGHT/10, TheText.Get("REPLAY"));
}
diff --git a/src/control/Replay.h b/src/control/Replay.h
index 68da9cc3..5dd8b651 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -2,6 +2,8 @@
#include "Pools.h"
#include "World.h"
+#include "WeaponEffects.h"
+#include "ParticleType.h"
#ifdef FIX_BUGS
#ifndef DONT_FIX_REPLAY_BUGS
@@ -24,14 +26,17 @@ struct CStoredAnimationState
uint8 animId;
uint8 time;
uint8 speed;
+ uint8 groupId;
uint8 secAnimId;
uint8 secTime;
uint8 secSpeed;
+ uint8 secGroupId;
uint8 blendAmount;
uint8 partAnimId;
uint8 partAnimTime;
uint8 partAnimSpeed;
uint8 partBlendAmount;
+ uint8 partGroupId;
};
enum {
@@ -45,20 +50,18 @@ struct CStoredDetailedAnimationState
uint8 aCurTime[NUM_MAIN_ANIMS_IN_REPLAY];
uint8 aSpeed[NUM_MAIN_ANIMS_IN_REPLAY];
uint8 aBlendAmount[NUM_MAIN_ANIMS_IN_REPLAY];
-#ifdef FIX_REPLAY_BUGS
int8 aBlendDelta[NUM_MAIN_ANIMS_IN_REPLAY];
-#endif
uint8 aFunctionCallbackID[NUM_MAIN_ANIMS_IN_REPLAY];
uint16 aFlags[NUM_MAIN_ANIMS_IN_REPLAY];
+ uint8 aGroupId[NUM_MAIN_ANIMS_IN_REPLAY];
uint8 aAnimId2[NUM_PARTIAL_ANIMS_IN_REPLAY];
uint8 aCurTime2[NUM_PARTIAL_ANIMS_IN_REPLAY];
uint8 aSpeed2[NUM_PARTIAL_ANIMS_IN_REPLAY];
uint8 aBlendAmount2[NUM_PARTIAL_ANIMS_IN_REPLAY];
-#ifdef FIX_REPLAY_BUGS
int8 aBlendDelta2[NUM_PARTIAL_ANIMS_IN_REPLAY];
-#endif
uint8 aFunctionCallbackID2[NUM_PARTIAL_ANIMS_IN_REPLAY];
uint16 aFlags2[NUM_PARTIAL_ANIMS_IN_REPLAY];
+ uint8 aGroupId2[NUM_PARTIAL_ANIMS_IN_REPLAY];
};
#ifdef GTA_REPLAY
@@ -76,21 +79,24 @@ class CReplay
enum {
REPLAYCAMMODE_ASSTORED = 0,
- REPLAYCAMMODE_TOPDOWN = 1,
- REPLAYCAMMODE_FIXED = 2
+ REPLAYCAMMODE_TOPDOWN,
+ REPLAYCAMMODE_FIXED
};
enum {
REPLAYPACKET_END = 0,
- REPLAYPACKET_VEHICLE = 1,
- REPLAYPACKET_PED_HEADER = 2,
- REPLAYPACKET_PED_UPDATE = 3,
- REPLAYPACKET_GENERAL = 4,
- REPLAYPACKET_CLOCK = 5,
- REPLAYPACKET_WEATHER = 6,
- REPLAYPACKET_ENDOFFRAME = 7,
- REPLAYPACKET_TIMER = 8,
- REPLAYPACKET_BULLET_TRACES = 9
+ REPLAYPACKET_VEHICLE,
+ REPLAYPACKET_BIKE,
+ REPLAYPACKET_PED_HEADER,
+ REPLAYPACKET_PED_UPDATE,
+ REPLAYPACKET_GENERAL,
+ REPLAYPACKET_CLOCK,
+ REPLAYPACKET_WEATHER,
+ REPLAYPACKET_ENDOFFRAME,
+ REPLAYPACKET_TIMER,
+ REPLAYPACKET_BULLET_TRACES,
+ REPLAYPACKET_PARTICLE,
+ REPLAYPACKET_MISC
};
enum {
@@ -179,8 +185,9 @@ class CReplay
int8 vehicle_index;
CStoredAnimationState anim_state;
CCompressedMatrixNotAligned matrix;
+ uint16 weapon_model;
int8 assoc_group_id;
- uint8 weapon_model;
+ bool is_visible;
};
VALIDATE_SIZE(tPedUpdatePacket, 40);
@@ -206,8 +213,65 @@ class CReplay
uint8 door_status;
uint8 primary_color;
uint8 secondary_color;
+ bool render_scorched;
+ int8 skimmer_speed;
+ int8 vehicle_type;
+
+ };
+ VALIDATE_SIZE(tVehicleUpdatePacket, 52);
+
+ struct tBikeUpdatePacket
+ {
+ uint8 type;
+ uint8 index;
+ uint8 health;
+ uint8 acceleration;
+ CCompressedMatrixNotAligned matrix;
+ int8 door_angles[2];
+ uint16 mi;
+ int8 velocityX;
+ int8 velocityY;
+ int8 velocityZ;
+ int8 wheel_state;
+ uint8 wheel_susp_dist[4];
+ uint8 wheel_rotation[4];
+ uint8 primary_color;
+ uint8 secondary_color;
+ int8 lean_angle;
+ int8 wheel_angle;
+
+ };
+ VALIDATE_SIZE(tBikeUpdatePacket, 44);
+
+ struct tParticlePacket
+ {
+ uint8 type;
+ uint8 particle_type;
+ int8 dir_x;
+ int8 dir_y;
+ int8 dir_z;
+ uint8 r;
+ uint8 g;
+ uint8 b;
+ uint8 a;
+ int16 pos_x;
+ int16 pos_y;
+ int16 pos_z;
+ float size;
+ };
+ VALIDATE_SIZE(tParticlePacket, 20);
+
+ struct tMiscPacket
+ {
+ uint8 type;
+ uint32 cam_shake_start;
+ float cam_shake_strength;
+ uint8 cur_area;
+ uint8 video_cam : 1;
+ uint8 lift_cam : 1;
};
- VALIDATE_SIZE(tVehicleUpdatePacket, 48);
+
+ VALIDATE_SIZE(tMiscPacket, 16);
private:
static uint8 Mode;
@@ -218,7 +282,7 @@ private:
static uint8* pBuf2;
static CPlayerPed* pBuf3;
static uint8* pBuf4;
- static CCutsceneHead* pBuf5;
+ static CCutsceneObject* pBuf5;
static uint8* pBuf6;
static CPtrNode* pBuf7;
static uint8* pBuf8;
@@ -272,12 +336,32 @@ private:
static float fDistanceLookAroundCam;
static float fAlphaAngleLookAroundCam;
static float fBetaAngleLookAroundCam;
-#ifdef FIX_BUGS
+ static int ms_nNumCivMale_Stored;
+ static int ms_nNumCivFemale_Stored;
+ static int ms_nNumCop_Stored;
+ static int ms_nNumEmergency_Stored;
+ static int ms_nNumGang1_Stored;
+ static int ms_nNumGang2_Stored;
+ static int ms_nNumGang3_Stored;
+ static int ms_nNumGang4_Stored;
+ static int ms_nNumGang5_Stored;
+ static int ms_nNumGang6_Stored;
+ static int ms_nNumGang7_Stored;
+ static int ms_nNumGang8_Stored;
+ static int ms_nNumGang9_Stored;
+ static int ms_nNumDummy_Stored;
+ static int ms_nTotalCarPassengerPeds_Stored;
+ static int ms_nTotalCivPeds_Stored;
+ static int ms_nTotalGangPeds_Stored;
+ static int ms_nTotalPeds_Stored;
+ static int ms_nTotalMissionPeds_Stored;
static uint8* pGarages;
static CFire* FireArray;
static uint32 NumOfFires;
static uint8* paProjectileInfo;
static uint8* paProjectiles;
+ static uint8 CurrArea;
+#ifdef FIX_BUGS
static int nHandleOfPlayerPed[NUMPLAYERS];
#endif
@@ -291,6 +375,7 @@ public:
static void Display(void) REPLAY_STUB;
static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) REPLAY_STUB;
static void StreamAllNecessaryCarsAndPeds(void) REPLAY_STUB;
+ static void RecordParticle(tParticleType type, CVector const& vecPos, CVector const& vecDir, float fSize, RwRGBA const& color) REPLAY_STUB;
#ifndef GTA_REPLAY
static bool ShouldStandardCameraBeProcessed(void) { return true; }
@@ -312,7 +397,9 @@ private:
static void TriggerPlaybackLastCoupleOfSeconds(uint32, uint8, float, float, float, uint32);
static bool FastForwardToTime(uint32);
static void StoreCarUpdate(CVehicle *vehicle, int id);
+ static void StoreBikeUpdate(CVehicle* vehicle, int id);
static void ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer);
+ static void ProcessBikeUpdate(CVehicle* vehicle, float interpolation, CAddressInReplayBuffer* buffer);
static bool PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer);
static void ProcessReplayCamera(void);
static void StoreStuffInMem(void);
@@ -325,5 +412,6 @@ private:
static void FindFirstFocusCoordinate(CVector *coord);
static void ProcessLookAroundCam(void);
static size_t FindSizeOfPacket(uint8);
+ static void GoToNextBlock(void);
#endif
};
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index 2f5e3d45..af38537d 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -4,6 +4,7 @@
#include "SaveBuf.h"
#include "Zones.h"
#include "PathFind.h"
+#include "SaveBuf.h"
uint8 CRestart::OverrideHospitalLevel;
uint8 CRestart::OverridePoliceStationLevel;
@@ -81,13 +82,13 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);
float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_GENERIC ? OverrideHospitalLevel : curlevel)) {
+ if (CTheZones::GetLevelFromPosition(&HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_GENERIC ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
@@ -128,13 +129,13 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);
float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_GENERIC ? OverridePoliceStationLevel : curlevel)) {
+ if (CTheZones::GetLevelFromPosition(&PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_GENERIC ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 4c3307c5..e30313bf 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -14,23 +14,30 @@
#include "Camera.h"
#include "CarCtrl.h"
#include "General.h"
+#include "Object.h"
-#define ROADBLOCKDIST (80.0f)
+#define ROADBLOCKDIST (90.0f)
+#define ROADBLOCK_OBJECT_WIDTH (4.0f)
int16 CRoadBlocks::NumRoadBlocks;
-int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS];
+int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
+CScriptRoadblock CRoadBlocks::aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];
+
+#ifdef SECUROM
+uint8 roadBlocksPirateCheck = 0;
+#endif
void
CRoadBlocks::Init(void)
{
int i;
NumRoadBlocks = 0;
- for (i = 0; i < ThePaths.m_numMapObjects; i++) {
- if (ThePaths.m_objectFlags[i] & UseInRoadBlock) {
+ for(i = 0; i < ThePaths.m_numCarPathNodes; i++){
+ if(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){
if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true;
- RoadBlockObjects[NumRoadBlocks] = i;
+ RoadBlockNodes[NumRoadBlocks] = i;
NumRoadBlocks++;
} else {
#ifndef MASTER
@@ -41,10 +48,12 @@ CRoadBlocks::Init(void)
}
}
}
+
+ ClearScriptRoadBlocks();
}
void
-CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
+CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType)
{
static const CVector vecRoadBlockOffets[6] = { CVector(-1.5, 1.8f, 0.0f), CVector(-1.5f, -1.8f, 0.0f), CVector(1.5f, 1.8f, 0.0f),
CVector(1.5f, -1.8f, 0.0f), CVector(-1.5f, 0.0f, 0.0f), CVector(1.5, 0.0, 0.0) };
@@ -60,7 +69,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
eCopType copType = COP_STREET;
switch (pVehicle->GetModelIndex())
{
- case MI_FBICAR:
+ case MI_FBIRANCH:
modelInfoId = MI_FBI;
copType = COP_FBI;
break;
@@ -85,8 +94,10 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
pCopPed->SetIdle();
pCopPed->bKindaStayInSamePlace = true;
pCopPed->bNotAllowedToDuck = false;
- pCopPed->m_nRoadblockNode = roadBlockNode;
- pCopPed->bCrouchWhenShooting = roadBlockType != 2;
+ pCopPed->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ pCopPed->m_nRoadblockVeh = pVehicle;
+ pCopPed->m_nRoadblockVeh->RegisterReference((CEntity**)&pCopPed->m_nRoadblockVeh);
+ pCopPed->bCrouchWhenShooting = roadBlockType == 2 ? false : true;
if (pEntityToAttack) {
pCopPed->SetWeaponLockOnTarget(pEntityToAttack);
pCopPed->SetAttack(pEntityToAttack);
@@ -102,96 +113,186 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
void
CRoadBlocks::GenerateRoadBlocks(void)
{
+ CMatrix tmp1, tmp2;
+ static int16 unk;
#ifdef SQUEEZE_PERFORMANCE
if (FindPlayerPed()->m_pWanted->m_RoadblockDensity == 0)
return;
#endif
- CMatrix offsetMatrix;
uint32 frame = CTimer::GetFrameCounter() & 0xF;
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
- CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]];
- CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
+ int16 node = RoadBlockNodes[nRoadblockNode];
+ CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[node].GetPosition();
if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&
vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST &&
vecDistance.Magnitude() < ROADBLOCKDIST) {
if (!InOrOut[nRoadblockNode]) {
InOrOut[nRoadblockNode] = true;
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
- CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
- float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
- int32 vehicleId = MI_POLICE;
- if (pPlayerWanted->AreArmyRequired())
- vehicleId = MI_BARRACKS;
- else if (pPlayerWanted->AreFbiRequired())
- vehicleId = MI_FBICAR;
- else if (pPlayerWanted->AreSwatRequired())
- vehicleId = MI_ENFORCER;
- if (!CStreaming::HasModelLoaded(vehicleId))
- vehicleId = MI_POLICE;
- CColModel *pVehicleColModel = CModelInfo::GetColModel(vehicleId);
- float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
- int16 radius = (int16)(fMapObjectRadius / fModelRadius);
- if (radius >= 6)
- continue;
- CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->GetPosition();
- float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->GetForward());
- float fOffset = 0.5f * fModelRadius * (float)(radius - 1);
- for (int16 i = 0; i < radius; i++) {
- uint8 nRoadblockType = fDotProduct < 0.0f;
- if (CGeneral::GetRandomNumber() & 1) {
- offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI);
- }
- else {
- nRoadblockType = !nRoadblockType;
- offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI);
- }
- if (ThePaths.m_objectFlags[RoadBlockObjects[nRoadblockNode]] & ObjectEastWest)
- offsetMatrix.GetPosition() = CVector(0.0f, i * fModelRadius - fOffset, 0.6f);
- else
- offsetMatrix.GetPosition() = CVector(i * fModelRadius - fOffset, 0.0f, 0.6f);
- CMatrix vehicleMatrix = mapObject->GetMatrix() * offsetMatrix;
- float fModelRadius = CModelInfo::GetColModel(vehicleId)->boundingSphere.radius - 0.25f;
- int16 colliding = 0;
- CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
- if (!colliding) {
- CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
- pVehicle->SetStatus(STATUS_ABANDONED);
- // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
- vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
- pVehicle->SetMatrix(vehicleMatrix);
- pVehicle->PlaceOnRoadProperly();
- pVehicle->SetIsStatic(false);
- pVehicle->GetMatrix().UpdateRW();
- pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->bIsLocked = false;
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pVehicle->AutoPilot.m_nCurrentLane = 0;
- pVehicle->AutoPilot.m_nNextLane = 0;
- pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f;
- pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f;
- pVehicle->bExtendedRange = true;
- if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
- pVehicle->m_bSirenOrAlarm = true;
- if (pVehicle->GetUp().z > 0.94f) {
- CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
- CWorld::Add(pVehicle);
- pVehicle->bCreateRoadBlockPeds = true;
- pVehicle->m_nRoadblockType = nRoadblockType;
- pVehicle->m_nRoadblockNode = nRoadblockNode;
- }
- else {
- delete pVehicle;
- }
- }
+ CCarPathLink* pLink1 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink]];
+ CCarPathLink* pLink2 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink + 1]];
+ int lanes = Min(pLink1->numRightLanes + pLink1->numLeftLanes, pLink2->numLeftLanes + pLink2->numRightLanes);
+ float length = LANE_WIDTH * (lanes + 1);
+ CVector forward(pLink2->GetY() - pLink1->GetY(), -(pLink2->GetX() - pLink1->GetX()), 0.0f);
+ forward.Normalise();
+ if (ThePaths.m_pathNodes[node].HasDivider()) {
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward,
+ ThePaths.m_pathNodes[node].GetPosition() + ThePaths.m_pathNodes[node].GetDividerWidth() * forward);
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() - ThePaths.m_pathNodes[node].GetDividerWidth() * forward,
+ ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward);
+ }
+ else {
+ CreateRoadBlockBetween2Points(
+ ThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f) * forward,
+ ThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f) * forward);
}
}
}
- } else {
+ }
+ else {
InOrOut[nRoadblockNode] = false;
}
}
+ int i = CTimer::GetFrameCounter() & 0xF;
+ if (!aScriptRoadBlocks[i].m_bInUse)
+ return;
+ if ((aScriptRoadBlocks[i].GetPosition() - FindPlayerCoors()).Magnitude() < 100.0f) {
+ CreateRoadBlockBetween2Points(aScriptRoadBlocks[i].m_vInf, aScriptRoadBlocks[i].m_vSup);
+ aScriptRoadBlocks[i].m_bInUse = false;
+ }
+}
+
+void
+CRoadBlocks::ClearScriptRoadBlocks(void)
+{
+ for (int i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++)
+ aScriptRoadBlocks[i].m_bInUse = false;
+}
+
+void
+CRoadBlocks::RegisterScriptRoadBlock(CVector vInf, CVector vSup)
+{
+ int32 i;
+ for (i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++) {
+ if (!aScriptRoadBlocks[i].m_bInUse)
+ break;
+ }
+ if (i == NUM_SCRIPT_ROADBLOCKS)
+ return;
+ aScriptRoadBlocks[i].m_bInUse = true;
+ aScriptRoadBlocks[i].m_vInf = vInf;
+ aScriptRoadBlocks[i].m_vSup = vSup;
+}
+
+void
+CRoadBlocks::CreateRoadBlockBetween2Points(CVector point1, CVector point2)
+{
+#ifdef SECUROM
+ if (roadBlocksPirateCheck == 0)
+ // if not pirated game
+ // roadBlocksPirateCheck = 1;
+ // else
+ roadBlocksPirateCheck = 2;
+#endif
+ CMatrix tmp;
+ CVector forward = (point2 - point1);
+ float distBetween = forward.Magnitude();
+ CVector pos = (point1 + point2) / 2;
+ CVector right(forward.y, -forward.x, 0.0f);
+ forward.Normalise();
+ right.Normalise();
+ if (DotProduct(FindPlayerCoors() - pos, right) < 0.0f) {
+ right *= -1.0f;
+ }
+ int32 vehicleId = MI_POLICE;
+ if (FindPlayerPed()->m_pWanted->AreArmyRequired())
+ vehicleId = MI_BARRACKS;
+ else if (FindPlayerPed()->m_pWanted->AreFbiRequired())
+ vehicleId = MI_FBICAR;
+ else if (FindPlayerPed()->m_pWanted->AreSwatRequired())
+ vehicleId = MI_ENFORCER;
+ if (!CStreaming::HasModelLoaded(vehicleId))
+ vehicleId = MI_POLICE;
+ CColModel *pVehicleColModel = CModelInfo::GetColModel(vehicleId);
+ float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
+ int16 numRoadblockVehicles = Min(6, (int16)(distBetween / fModelRadius));
+ for (int16 i = 0; i < numRoadblockVehicles; i++) {
+ float offset = fModelRadius * (i - numRoadblockVehicles / 2);
+ tmp.SetTranslate(0.0f, 0.0f, 0.0f);
+ tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);
+ tmp.GetForward() = forward;
+ tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);
+ if (CGeneral::GetRandomNumber() & 1)
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + 3.1416f);
+ tmp.SetTranslateOnly(offset * forward + pos);
+ tmp.GetPosition().z += 0.6f;
+ float fModelRadius = CModelInfo::GetColModel(vehicleId)->boundingSphere.radius - 0.25f;
+ int16 colliding = 0;
+ CWorld::FindObjectsKindaColliding(tmp.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
+ pVehicle->SetStatus(STATUS_ABANDONED);
+ // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
+ tmp.GetPosition().z += fModelRadius - 0.6f;
+ pVehicle->SetMatrix(tmp);
+ pVehicle->PlaceOnRoadProperly();
+ pVehicle->SetIsStatic(false);
+ pVehicle->GetMatrix().UpdateRW();
+ pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->bIsLocked = false;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;
+ pVehicle->AutoPilot.m_nCruiseSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0;
+ pVehicle->bExtendedRange = true;
+ if (pVehicle->UsesSiren() && CGeneral::GetRandomNumber() & 1)
+ pVehicle->m_bSirenOrAlarm = true;
+ if (pVehicle->GetUp().z > 0.94f) {
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ CWorld::Add(pVehicle);
+ pVehicle->bCreateRoadBlockPeds = true;
+ pVehicle->m_nRoadblockType = DotProduct(pVehicle->GetRight(), pVehicle->GetPosition() - FindPlayerCoors()) >= 0.0f;
+ pVehicle->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 7000;
+ }
+ else {
+ delete pVehicle;
+ }
+ }
+ }
+ int numBarriers = distBetween / ROADBLOCK_OBJECT_WIDTH;
+ CStreaming::RequestModel(MI_ROADWORKBARRIER1, STREAMFLAGS_DONT_REMOVE);
+ if (!CStreaming::HasModelLoaded(MI_ROADWORKBARRIER1))
+ return;
+ for (int i = 0; i < numBarriers; i++) {
+ float offset = ROADBLOCK_OBJECT_WIDTH * (i - numBarriers / 2);
+ tmp.SetTranslate(0.0f, 0.0f, 0.0f);
+ tmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);
+ tmp.GetForward() = forward;
+ tmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ tmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);
+ tmp.SetTranslateOnly(5.0f * right + offset * forward + pos);
+ tmp.GetPosition().x += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;
+ tmp.GetPosition().y += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;
+ bool found;
+ tmp.GetPosition().z = CWorld::FindGroundZFor3DCoord(tmp.GetPosition().x, tmp.GetPosition().y, tmp.GetPosition().z + 2.0f, &found);
+ if (!found)
+ continue;
+ int16 colliding = 0;
+ CBaseModelInfo* pMI = CModelInfo::GetModelInfo(MI_ROADWORKBARRIER1);
+ tmp.GetPosition().z -= pMI->GetColModel()->boundingBox.min.z;
+ CWorld::FindObjectsKindaColliding(tmp.GetPosition(), pMI->GetColModel()->boundingSphere.radius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (colliding == 0) {
+ CObject* pObject = new CObject(MI_ROADWORKBARRIER1, true);
+ pObject->GetMatrix() = tmp;
+ pObject->ObjectCreatedBy = TEMP_OBJECT;
+ pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 600000;
+ CWorld::Add(pObject);
+ }
+ }
}
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 0f0c1882..ef614950 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -3,14 +3,28 @@
class CVehicle;
+class CScriptRoadblock
+{
+public:
+ CVector m_vInf;
+ CVector m_vSup;
+ bool m_bInUse;
+ CVector GetPosition() { return (m_vInf + m_vSup) / 2; }
+};
+
class CRoadBlocks
{
public:
static int16 NumRoadBlocks;
- static int16 RoadBlockObjects[NUMROADBLOCKS];
+ static int16 RoadBlockNodes[NUMROADBLOCKS];
static bool InOrOut[NUMROADBLOCKS];
+ static CScriptRoadblock aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];
static void Init(void);
- static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
+ static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType);
static void GenerateRoadBlocks(void);
+
+ static void CreateRoadBlockBetween2Points(CVector, CVector);
+ static void RegisterScriptRoadBlock(CVector, CVector);
+ static void ClearScriptRoadBlocks();
};
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
index 42dadee0..74d81327 100644
--- a/src/control/SceneEdit.cpp
+++ b/src/control/SceneEdit.cpp
@@ -88,7 +88,7 @@ static int32 NextValidModelId(int32 mi, int32 step)
continue;
if (pInfo->GetModelType() == MITYPE_PED
#ifdef FIX_BUGS
- && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL04)
+ && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL21)
#endif
|| pInfo->GetModelType() == MITYPE_VEHICLE &&
#ifdef FIX_BUGS
@@ -269,7 +269,7 @@ void CSceneEdit::Draw(void)
CFont::SetRightJustifyWrap(0.0f);
CFont::SetBackGroundOnlyTextOff();
#ifdef FIX_BUGS
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
CFont::SetPropOn();
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetDropShadowPosition(1);
@@ -312,7 +312,7 @@ void CSceneEdit::Draw(void)
CFont::SetScale(0.7f, 0.7f);
#endif
#ifdef FIX_BUGS
- CFont::SetFontStyle(FONT_BANK);
+ CFont::SetFontStyle(FONT_STANDARD);
#else
CFont::SetFontStyle(FONT_HEADING);
#endif
@@ -1098,7 +1098,7 @@ bool CSceneEdit::SelectWeapon(void)
}
if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) {
if (++m_nWeaponType >= WEAPONTYPE_DETONATOR)
- m_nWeaponType = WEAPONTYPE_BASEBALLBAT;
+ m_nWeaponType = WEAPONTYPE_BRASSKNUCKLE;
pActors[m_nActor]->ClearWeapons();
pActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000);
pActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId);
@@ -1106,7 +1106,7 @@ bool CSceneEdit::SelectWeapon(void)
}
else if (CPad::GetPad(1)->GetRightShoulder1JustDown()){
if (--m_nWeaponType <= WEAPONTYPE_UNARMED)
- m_nWeaponType = WEAPONTYPE_GRENADE;
+ m_nWeaponType = WEAPONTYPE_MINIGUN;
pActors[m_nActor]->ClearWeapons();
pActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000);
pActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId);
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index f1c8b348..5b5825eb 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -37,16 +37,28 @@
#include "Wanted.h"
#include "Weather.h"
#include "Zones.h"
+#include "main.h"
+#include "Ropes.h"
+#include "ColStore.h"
+#include "Fluff.h"
+#include "GameLogic.h"
+#include "MBlur.h"
+#include "PedRoutes.h"
+#include "RoadBlocks.h"
+#include "SpecialFX.h"
+#include "Timecycle.h"
+#include "TxdStore.h"
+#include "Bike.h"
+#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
+#include <stdarg.h>
+#endif
uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE];
CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS];
-int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS];
-int32 CTheScripts::OnAMissionForContactFlag[MAX_NUM_CONTACTS];
intro_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
-tCollectiveData CTheScripts::CollectiveArray[MAX_NUM_COLLECTIVES];
tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS];
int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@@ -67,8 +79,6 @@ uint16 CTheScripts::NumberOfMissionScripts;
uint32 CTheScripts::LargestMissionScriptSize;
uint32 CTheScripts::MainScriptSize;
uint8 CTheScripts::FailCurrentMission;
-uint8 CTheScripts::CountdownToMakePlayerUnsafe;
-uint8 CTheScripts::DelayMakingPlayerUnsafeThisTime;
uint16 CTheScripts::NumScriptDebugLines;
uint16 CTheScripts::NumberOfIntroRectanglesThisFrame;
uint16 CTheScripts::NumberOfIntroTextLinesThisFrame;
@@ -79,6 +89,15 @@ CStuckCarCheck CTheScripts::StuckCars;
uint16 CTheScripts::CommandsExecuted;
uint16 CTheScripts::ScriptsUpdated;
int32 ScriptParams[32];
+uint8 CTheScripts::RiotIntensity;
+uint32 CTheScripts::LastMissionPassedTime;
+uint16 CTheScripts::NumberOfExclusiveMissionScripts;
+bool CTheScripts::bPlayerHasMetDebbieHarry;
+bool CTheScripts::bPlayerIsInTheStatium;
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+int16 CTheScripts::CardStack[CARDS_IN_DECK * MAX_DECKS];
+int16 CTheScripts::CardStackPosition;
+#endif
#ifdef MISSION_REPLAY
@@ -97,7 +116,97 @@ static const char* nonMissionScripts[] = {
"rc4",
"hj",
"usj",
- "mayhem"
+ "mayhem",
+ "range",
+ "race",
+ "pizza",
+ "rcheli",
+ "rcplne1",
+ "rcrace1",
+ "cokerun",
+ "buypro1",
+ "carbuy1",
+ "buypro2",
+ "icecut",
+ "icecre1",
+ "buypro3",
+ "buypro4",
+ "buypro5",
+ "buypro6",
+ "buypro7",
+ "buypro8",
+ "buypro9",
+ "buypro10",
+ "buypro11",
+ "ovalrng",
+ "mm",
+ "kickst",
+ "heli1sc",
+ "heli2sc",
+ "heli3sc",
+ "heli4sc",
+ "carpark_1",
+ "bmx_1",
+ "bmx_2"
+};
+
+static const char* MissionScripts[] = {
+ "LAWYER1",
+ "LAWYER2",
+ "LAWYER3",
+ "LAWYER4",
+ "GENERL1",
+ "COL2",
+ "GENERL3",
+ "COL_4",
+ "COL_5",
+ "baron1",
+ "baron2",
+ "baron3",
+ "baron4",
+ "kent1",
+ "baron5",
+ "serg1",
+ "serg2",
+ "serg3",
+ "bankjo1",
+ "bankjo2",
+ "bankjo3",
+ "bankjo4",
+ "phil1",
+ "phil2",
+ "porno1",
+ "porno2",
+ "porno3",
+ "porno4",
+ "protec1",
+ "protec2",
+ "protec3",
+ "count1",
+ "count2",
+ "CAP_1",
+ "FIN_1",
+ "bike1",
+ "bike2",
+ "bike3",
+ "rockb1",
+ "rockb2",
+ "rockb3",
+ "cuban1",
+ "cuban2",
+ "cuban3",
+ "cuban4",
+ "hait1",
+ "hait2",
+ "hait3",
+ "assin1",
+ "assin2",
+ "assin3",
+ "assin4",
+ "assin5",
+ "taxwar1",
+ "taxwar2",
+ "taxwar3"
};
int AllowMissionReplay;
@@ -109,6 +218,14 @@ float oldTargetX;
float oldTargetY;
int missionRetryScriptIndex;
bool doingMissionRetry;
+bool gbTryingPorn4Again;
+int IsInAmmunation;
+int MissionSkipLevel;
+
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+bool UsingMobileScript;
+bool AlreadySavedGame;
+#endif
#endif
@@ -157,6 +274,46 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
{
for (int i = 0; i < MAX_CLEANUP; i++){
if (m_sEntities[i].type == type && m_sEntities[i].id == id){
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (pVehicle) {
+ if (pVehicle->bIsStaticWaitingForCollision) {
+ pVehicle->bIsStaticWaitingForCollision = false;
+ if (!pVehicle->GetIsStatic())
+ pVehicle->AddToMovingList();
+ }
+ }
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (pPed) {
+ if (pPed->bIsStaticWaitingForCollision) {
+ pPed->bIsStaticWaitingForCollision = false;
+ if (!pPed->GetIsStatic())
+ pPed->AddToMovingList();
+ }
+ }
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (pObject) {
+ if (pObject->bIsStaticWaitingForCollision) {
+ pObject->bIsStaticWaitingForCollision = false;
+ if (!pObject->GetIsStatic())
+ pObject->AddToMovingList();
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
m_sEntities[i].id = 0;
m_sEntities[i].type = CLEANUP_UNUSED;
m_nCount--;
@@ -164,15 +321,76 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
}
}
+void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects()
+{
+ for (int i = 0; i < MAX_CLEANUP; i++) {
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (pVehicle) {
+ if (pVehicle->bIsStaticWaitingForCollision) {
+ if (CColStore::HasCollisionLoaded(pVehicle->GetPosition())) {
+ pVehicle->bIsStaticWaitingForCollision = false;
+ if (!pVehicle->GetIsStatic())
+ pVehicle->AddToMovingList();
+ }
+ }
+ }
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (pPed) {
+ if (pPed->bIsStaticWaitingForCollision) {
+ if (CColStore::HasCollisionLoaded(pPed->GetPosition())) {
+ pPed->bIsStaticWaitingForCollision = false;
+ if (!pPed->GetIsStatic())
+ pPed->AddToMovingList();
+ }
+ }
+ }
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (pObject) {
+ if (pObject->bIsStaticWaitingForCollision) {
+ if (CColStore::HasCollisionLoaded(pObject->GetPosition())) {
+ pObject->bIsStaticWaitingForCollision = false;
+ if (!pObject->GetIsStatic())
+ pObject->AddToMovingList();
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
void CMissionCleanup::Process()
{
CPopulation::m_AllRandomPedsThisType = -1;
CPopulation::PedDensityMultiplier = 1.0f;
CCarCtrl::CarDensityMultiplier = 1.0f;
+ CPed::nThreatReactionRangeMultiplier = 1;
+ CPed::nEnterCarRangeMultiplier = 1;
FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f;
- TheCamera.Restore();
+ CRoadBlocks::ClearScriptRoadBlocks();
+ CRouteNode::Initialise();
+ if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
+ TheCamera.Restore();
TheCamera.SetWideScreenOff();
- DMAudio.ClearMissionAudio();
+ CSpecialFX::bLiftCam = false;
+ CSpecialFX::bVideoCam = false;
+ CTimeCycle::StopExtraColour(0);
+ for (int i = 0; i < MISSION_AUDIO_SLOTS; i++)
+ DMAudio.ClearMissionAudio(i);
CWeather::ReleaseWeather();
for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++)
CStreaming::SetMissionDoesntRequireSpecialChar(i);
@@ -182,9 +400,19 @@ void CMissionCleanup::Process()
CHud::m_ItemToFlash = -1;
CHud::SetHelpMessage(nil, false);
CUserDisplay::OnscnTimer.m_bDisabled = false;
+ CTheScripts::RemoveScriptTextureDictionary();
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false;
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CWorld::Players[0].MakePlayerSafe(false);
+ CWorld::Players[0].m_pPed->m_nFadeDrunkenness = 1;
+ CWorld::Players[0].m_pPed->m_nDrunkCountdown = 0;
+ CPad::GetPad(0)->SetDrunkInputDelay(0);
+ CWorld::Players[0].m_bDriveByAllowed = true;
+ DMAudio.ShutUpPlayerTalking(FALSE);
+ CVehicle::bDisableRemoteDetonation = false;
+ CVehicle::bDisableRemoteDetonationOnContact = false;
+ CGameLogic::ClearShortCut();
+ CTheScripts::RiotIntensity = 0;
CTheScripts::StoreVehicleIndex = -1;
CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::UpsideDownCars.Init();
@@ -217,10 +445,14 @@ void CMissionCleanup::Process()
default:
break;
}
- m_sEntities[i].id = 0;
- m_sEntities[i].type = CLEANUP_UNUSED;
- m_nCount--;
+ RemoveEntityFromList(m_sEntities[i].id, m_sEntities[i].type);
+ }
+#ifdef SECUROM
+ if ((myrand() & 3) == 2){
+ // if pirated game
+ CWeather::ForceHurricaneWeather();
}
+#endif
}
/* NB: CUpsideDownCarCheck is not used by actual script at all
@@ -385,11 +617,11 @@ bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)
void CRunningScript::CollectParameters(uint32* pIp, int16 total)
{
for (int16 i = 0; i < total; i++){
- float tmp;
uint16 varIndex;
switch (CTheScripts::Read1ByteFromScript(pIp))
{
case ARGUMENT_INT32:
+ case ARGUMENT_FLOAT:
ScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp);
break;
case ARGUMENT_GLOBALVAR:
@@ -408,10 +640,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
case ARGUMENT_INT16:
ScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp);
break;
- case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(pIp);
- ScriptParams[i] = *(int32*)&tmp;
- break;
default:
script_assert(0);
break;
@@ -422,7 +650,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
{
uint32* pIp = &ip;
- float tmp;
switch (CTheScripts::Read1ByteFromScript(pIp))
{
case ARGUMENT_INT32:
@@ -436,8 +663,7 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
case ARGUMENT_INT16:
return CTheScripts::Read2BytesFromScript(pIp);
case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(pIp);
- return *(int32*)&tmp;
+ return CTheScripts::Read4BytesFromScript(pIp);
default:
script_assert(0);
}
@@ -485,6 +711,7 @@ void CRunningScript::Init()
m_anStack[i] = 0;
m_nStackPointer = 0;
m_nWakeTime = 0;
+ m_bIsActive = false;
m_bCondResult = false;
m_bIsMissionScript = false;
m_bSkipWakeTime = false;
@@ -505,7 +732,7 @@ int CTheScripts::OpenScript()
CFileMgr::ChangeDir("\\");
switch (ScriptToLoad) {
case 0: return CFileMgr::OpenFile("data\\main.scm", "rb");
- case 1: return CFileMgr::OpenFile("data\\main_freeroam.scm", "rb");
+ case 1: return CFileMgr::OpenFile("data\\freeroam_miami.scm", "rb");
case 2: return CFileMgr::OpenFile("data\\main_d.scm", "rb");
}
return CFileMgr::OpenFile("data\\main.scm", "rb");
@@ -542,15 +769,7 @@ void CTheScripts::Init()
StoreVehicleIndex = -1;
StoreVehicleWasRandom = true;
OnAMissionFlag = 0;
- for (int i = 0; i < MAX_NUM_CONTACTS; i++){
- BaseBriefIdForContact[i] = 0;
- OnAMissionForContactFlag[i] = 0;
- }
- for (int i = 0; i < MAX_NUM_COLLECTIVES; i++){
- CollectiveArray[i].colIndex = -1;
- CollectiveArray[i].pedIndex = 0;
- }
- NextFreeCollectiveIndex = 0;
+ LastMissionPassedTime = (uint32)-1;
LastRandomPedId = -1;
for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){
memset(&UsedObjectArray[i].name, 0, sizeof(UsedObjectArray[i].name));
@@ -563,15 +782,17 @@ void CTheScripts::Init()
bUsingAMultiScriptFile = true;
for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++)
MultiScriptArray[i] = 0;
+ NumberOfExclusiveMissionScripts = 0;
NumberOfMissionScripts = 0;
LargestMissionScriptSize = 0;
MainScriptSize = 0;
ReadMultiScriptFileOffsetsFromScript();
FailCurrentMission = 0;
- CountdownToMakePlayerUnsafe = 0;
DbgFlag = false;
- DelayMakingPlayerUnsafeThisTime = 1;
NumScriptDebugLines = 0;
+ RiotIntensity = 0;
+ bPlayerHasMetDebbieHarry = false;
+ bPlayerIsInTheStatium = false;
for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){
ScriptSphereArray[i].m_bInUse = false;
ScriptSphereArray[i].m_Index = 1;
@@ -592,6 +813,7 @@ void CTheScripts::Init()
IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255);
}
NumberOfIntroRectanglesThisFrame = 0;
+ RemoveScriptTextureDictionary();
for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){
BuildingSwapArray[i].m_pBuilding = nil;
BuildingSwapArray[i].m_nNewModel = -1;
@@ -603,6 +825,19 @@ void CTheScripts::Init()
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
LogAfterScriptInitializing();
#endif
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ UsingMobileScript = false;
+ AlreadySavedGame = false;
+#endif
+}
+
+void CTheScripts::RemoveScriptTextureDictionary()
+{
+ for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
+ CTheScripts::ScriptSprites[i].Delete();
+ int slot = CTxdStore::FindTxdSlot("script");
+ if (slot != -1)
+ CTxdStore::RemoveTxd(slot);
}
void CRunningScript::RemoveScriptFromList(CRunningScript** ppScript)
@@ -632,6 +867,7 @@ CRunningScript* CTheScripts::StartNewScript(uint32 ip)
pNew->Init();
pNew->SetIP(ip);
pNew->AddScriptToList(&pActiveScripts);
+ pNew->m_bIsActive = true;
return pNew;
}
@@ -644,13 +880,10 @@ void CTheScripts::Process()
float timeStep = CTimer::GetTimeStepInMilliseconds();
UpsideDownCars.UpdateTimers();
StuckCars.Process();
+ MissionCleanUp.CheckIfCollisionHasLoadedForMissionObjects();
DrawScriptSpheres();
if (FailCurrentMission)
--FailCurrentMission;
- if (CountdownToMakePlayerUnsafe){
- if (--CountdownToMakePlayerUnsafe == 0)
- CWorld::Players[0].MakePlayerSafe(false);
- }
if (UseTextCommands){
for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++)
IntroTextLines[i].Reset();
@@ -666,6 +899,7 @@ void CTheScripts::Process()
#ifdef MISSION_REPLAY
static uint32 TimeToWaitTill;
+ static bool AlreadyResetHealth;
switch (AllowMissionReplay) {
case MISSION_RETRY_STAGE_START_PROCESSING:
AllowMissionReplay = MISSION_RETRY_STAGE_WAIT_FOR_DELAY;
@@ -681,9 +915,19 @@ void CTheScripts::Process()
break;
case MISSION_RETRY_STAGE_START_RESTARTING:
AllowMissionReplay = MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART;
+ AlreadyResetHealth = false;
TimeToWaitTill = CTimer::GetTimeInMilliseconds() + 500;
break;
case MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART:
+ if (!AlreadyResetHealth) {
+ AlreadyResetHealth = true;
+ CPlayerPed* pPlayerPed = FindPlayerPed();
+ if (pPlayerPed) {
+ CPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed();
+ if (pPlayerInfo)
+ pPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth;
+ }
+ }
if (TimeToWaitTill < CTimer::GetTimeInMilliseconds()) {
AllowMissionReplay = MISSION_RETRY_STAGE_NORMAL;
return;
@@ -711,6 +955,8 @@ void CTheScripts::Process()
script->UpdateTimers(timeStep);
script->Process();
script = next;
+ if (script && !script->m_bIsActive)
+ script = nil;
}
DbgFlag = false;
@@ -786,24 +1032,30 @@ int8 CRunningScript::ProcessOneCommand()
retval = ProcessCommands800To899(command);
else if (command < 1000)
retval = ProcessCommands900To999(command);
-#if GTA_VERSION <= GTA3_PS2_160
- else if (command < 1200)
- retval = ProcessCommands1000To1099(command);
-#else
else if (command < 1100)
retval = ProcessCommands1000To1099(command);
else if (command < 1200)
retval = ProcessCommands1100To1199(command);
+ else if (command < 1300)
+ retval = ProcessCommands1200To1299(command);
+ else if (command < 1400)
+ retval = ProcessCommands1300To1399(command);
+ else if (command < 1500)
+ retval = ProcessCommands1400To1499(command);
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ if (!AlreadySavedGame) // we need to ignore first "fake" command which actually just saves the game
#endif
+ {
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
- LogAfterProcessingCommand(command);
+ LogAfterProcessingCommand(command);
#elif defined USE_BASIC_SCRIPT_DEBUG_OUTPUT
- if (m_bMissionFlag) {
- char tmp[128];
- sprintf(tmp, "Comm %d Cmp %d", command, m_bCondResult);
- CDebug::DebugAddText(tmp);
- }
+ if (m_bMissionFlag) {
+ char tmp[128];
+ sprintf(tmp, "Comm %d Cmp %d", command, m_bCondResult);
+ CDebug::DebugAddText(tmp);
+ }
#endif
+ }
return retval;
}
@@ -1231,13 +1483,11 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*ptr1 == *ptr2);
return 0;
}
- /* Following commands are not implemented, and go to default case
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR:
- case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:
- case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR:
- */
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR:
+ //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:
+ //case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR:
case COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER:
{
int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
@@ -1273,19 +1523,18 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);
return 0;
}
- /* Following commands are not implemented, and go to default case
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER:
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR:
- case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:
- case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR:
- */
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER:
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR:
+ //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:
+ //case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR:
+ /*
case COMMAND_GOTO_IF_TRUE:
CollectParameters(&m_nIp, 1);
if (m_bCondResult)
SetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);
- /* Check COMMAND_GOTO note. */
return 0;
+ */
case COMMAND_GOTO_IF_FALSE:
CollectParameters(&m_nIp, 1);
if (!m_bCondResult)
@@ -1297,6 +1546,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
CTheScripts::bAlreadyRunningAMissionScript = false;
RemoveScriptFromList(&CTheScripts::pActiveScripts);
AddScriptToList(&CTheScripts::pIdleScripts);
+ m_bIsActive = false;
#ifdef MISSION_REPLAY
if (m_bMissionFlag) {
CPlayerInfo* pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus];
@@ -1316,6 +1566,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
CollectParameters(&m_nIp, 1);
script_assert(ScriptParams[0] >= 0);
CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);
+ pNew->m_bIsActive = true;
int8 type = CTheScripts::Read1ByteFromScript(&m_nIp);
float tmp;
for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) {
@@ -1363,7 +1614,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
{
CollectParameters(&m_nIp, 4);
int32 index = ScriptParams[0];
- script_assert(index < 1); /* Constant? Also no more double player glitch */
+ script_assert(index < NUMPLAYERS);
printf("&&&&&&&&&&&&&Creating player: %d\n", index);
if (!CStreaming::HasModelLoaded(MI_PLAYER)) {
CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
@@ -1403,20 +1654,49 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CPlayerPed* ped = CWorld::Players[index].m_pPed;
- if (!ped->bInVehicle) {
- pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
- ped->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (ped->bInVehicle) {
+ pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
+ ped->m_pMyVehicle->Teleport(pos); // removed dumb stuff that was present here
+ CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle);
return 0;
}
- pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel();
- if (ped->m_pMyVehicle->IsBoat())
- ped->m_pMyVehicle->Teleport(pos);
- else
- ped->m_pMyVehicle->Teleport(pos);
- /* I'll keep this condition here but obviously it is absolutely pointless */
- /* It's clearly present in disassembly so it had to be in original code */
- CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle);
+ pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
+ CVector vOldPos = ped->GetPosition();
+ ped->Teleport(pos);
+ CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (ped) { // great time to check
+ for (int i = 0; i < ped->m_numNearPeds; i++) {
+ CPed* pTestedPed = ped->m_nearPeds[i];
+ if (!pTestedPed || !IsPedPointerValid(pTestedPed))
+ continue;
+ if (pTestedPed->m_pedInObjective == ped && pTestedPed->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+ CVector vFollowerPos = pTestedPed->GetFormationPosition();
+ CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);
+ bool bFound = false;
+ vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;
+ if (bFound) {
+ if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {
+ pTestedPed->Teleport(vFollowerPos);
+ }
+ }
+ }
+ else if (pTestedPed->m_leader == ped) {
+ CVector vFollowerPos;
+ if (pTestedPed->m_pedFormation)
+ vFollowerPos = pTestedPed->GetFormationPosition();
+ else
+ vFollowerPos = ped->GetPosition() + pTestedPed->GetPosition() - vOldPos;
+ CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);
+ bool bFound = false;
+ vFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;
+ if (bFound) {
+ if (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {
+ pTestedPed->Teleport(vFollowerPos);
+ }
+ }
+ }
+ }
+ }
return 0;
}
case COMMAND_IS_PLAYER_IN_AREA_2D:
@@ -1852,6 +2132,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->CharCreatedBy = MISSION_CHAR;
ped->bRespondsToThreats = false;
ped->bAllowMedicsToReviveMe = false;
+ ped->bIsPlayerFriend = false;
CVector pos = *(CVector*)&ScriptParams[2];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -1859,6 +2140,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -1872,24 +2155,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- if (ped) {
- if (ped->InVehicle()) {
- if (ped->m_pMyVehicle->pDriver == ped) {
- ped->m_pMyVehicle->RemoveDriver();
- ped->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- if (ped->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- ped->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- if (ped->m_nPedType == PEDTYPE_COP && ped->m_pMyVehicle->IsLawEnforcementVehicle())
- ped->m_pMyVehicle->ChangeLawEnforcerState(0);
- }
- else {
- ped->m_pMyVehicle->RemovePassenger(ped);
- }
- }
- CWorld::RemoveReferencesToDeletedObject(ped);
- delete ped;
- --CPopulation::ms_nTotalMissionPeds;
- }
+ CTheScripts::RemoveThisPed(ped);
if (m_bIsMissionScript)
CTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);
return 0;
@@ -1908,22 +2174,31 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
#else
path = CGeneral::GetRandomNumberInRange(0, 7);
#endif
+
ped->SetWanderPath(path);
return 0;
}
- /* Not implemented.
- case COMMAND_CHAR_WANDER_RANGE:
- */
+ //case COMMAND_CHAR_WANDER_RANGE:
case COMMAND_CHAR_FOLLOW_PATH:
{
- CollectParameters(&m_nIp, 4);
+ CollectParameters(&m_nIp, 6);
CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(ped);
+ if (ped->GetPedState() == PED_ATTACK || ped->GetPedState() == PED_FIGHT || !ped->IsPedInControl())
+ return 0;
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ float radius = *(float*)&ScriptParams[4];
+ eMoveState state;
+ switch (ScriptParams[5]) {
+ case 0: state = PEDMOVE_WALK; break;
+ case 1: state = PEDMOVE_RUN; break;
+ default: assert(0);
+ }
ped->ClearAll();
- ped->SetFollowPath(pos);
+ ped->m_pathNodeTimer = 0;
+ ped->SetFollowPath(pos, radius, state, nil, nil, 999999);
return 0;
}
case COMMAND_CHAR_SET_IDLE:
@@ -1968,44 +2243,27 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- /* The following block was once again written
- * by someone not familiar with virtual functions.
- * It doesn't require any ifs at all.
- * To keep as close to original as possible, I'll keep it.
- * Maybe there was more commented out/debug
- * stuff, but I doubt it.
- */
+ // removed dumb stuff again
if (!vehicle) {
pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
ped->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
- }
- else if (vehicle->IsBoat()) {
- pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel();
- vehicle->Teleport(pos);
- CTheScripts::ClearSpaceForMissionEntity(pos, vehicle);
+ for (int i = 0; i < ped->m_numNearPeds; i++) {
+ CPed* pNearPed = ped->m_nearPeds[i];
+ if (pNearPed->m_leader == ped) {
+ pNearPed->Teleport(pos);
+ pNearPed->PositionAnyPedOutOfCollision();
+ }
+ }
}
else {
pos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel();
vehicle->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, vehicle);
}
- /* Short version of this command.
- *
- * CollectParameters(&m_nIp, 4);
- * CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- * script_assert(ped);
- * CEntity* entityToMove = ped->bInVehicle ? ped->m_pMyVehicle : ped;
- * CVector pos = *(CVector*)&ScriptParams[1];
- * if (pos.z <= MAP_Z_LOW_LIMIT)
- * pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- * pos.z += entityToMove->GetDistanceFromCentreOfMassToBaseOfModel();
- * entityToMove->Teleport(pos);
- * CTheScripts::ClearSpaceForMissionEntity(pos, entityToMove);
- *
- */
return 0;
}
+ /*
case COMMAND_IS_CHAR_STILL_ALIVE:
{
CollectParameters(&m_nIp, 1);
@@ -2013,6 +2271,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
UpdateCompareFlag(ped && ped->GetPedState() != PED_DEAD && ped->GetPedState() != PED_DIE);
return 0;
}
+ */
case COMMAND_IS_CHAR_IN_AREA_2D:
{
CollectParameters(&m_nIp, 6);
@@ -2078,15 +2337,22 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
boat->SetStatus(STATUS_ABANDONED);
boat->bIsLocked = true;
boat->AutoPilot.m_nCarMission = MISSION_NONE;
- boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
+ boat->AutoPilot.m_nTempAction = TEMPACT_NONE;
boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f;
+ if (m_bIsMissionScript)
+ boat->bIsStaticWaitingForCollision = true;
CWorld::Add(boat);
handle = CPools::GetVehiclePool()->GetIndex(boat);
}
else {
CVehicle* car;
+
if (!CModelInfo::IsBikeModel(ScriptParams[0]))
car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE);
+ else {
+ car = new CBike(ScriptParams[0], MISSION_VEHICLE);
+ ((CBike*)(car))->bIsStanding = true;
+ }
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -2097,13 +2363,15 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->bIsLocked = true;
CCarCtrl::JoinCarWithRoadSystem(car);
car->AutoPilot.m_nCarMission = MISSION_NONE;
- car->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
+ car->AutoPilot.m_nTempAction = TEMPACT_NONE;
car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;
car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0;
car->bEngineOn = false;
car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
car->bHasBeenOwnedByPlayer = true;
+ if (m_bIsMissionScript)
+ car->bIsStaticWaitingForCollision = true;
CWorld::Add(car);
handle = CPools::GetVehiclePool()->GetIndex(car);
}
@@ -2141,7 +2409,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS;
car->SetStatus(STATUS_PHYSICS);
car->bEngineOn = true;
- car->AutoPilot.m_nCruiseSpeed = Max(6, car->AutoPilot.m_nCruiseSpeed);
+ car->AutoPilot.m_nCruiseSpeed = Max(1, car->AutoPilot.m_nCruiseSpeed);
car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
return 0;
}
@@ -2153,7 +2421,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
CCarCtrl::JoinCarWithRoadSystem(car);
car->AutoPilot.m_nCarMission = MISSION_CRUISE;
car->bEngineOn = true;
- car->AutoPilot.m_nCruiseSpeed = Max(6, car->AutoPilot.m_nCruiseSpeed);
+ car->AutoPilot.m_nCruiseSpeed = Max(1, car->AutoPilot.m_nCruiseSpeed);
car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
return 0;
}
@@ -2225,6 +2493,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
}
return 0;
}
+ /*
case COMMAND_IS_CAR_STILL_ALIVE:
{
CollectParameters(&m_nIp, 1);
@@ -2232,19 +2501,13 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
UpdateCompareFlag(car && car->GetStatus() != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater));
return 0;
}
+ */
case COMMAND_SET_CAR_CRUISE_SPEED:
{
CollectParameters(&m_nIp, 2);
CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(car);
-#if defined MISSION_REPLAY && defined SIMPLIER_MISSIONS
- car->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
- if (missionRetryScriptIndex == 40 && car->GetModelIndex() == MI_CHEETAH) // Turismo
- car->AutoPilot.m_nCruiseSpeed = 8 * car->AutoPilot.m_nCruiseSpeed / 10;
- car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
-#else
car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);
-#endif
return 0;
}
case COMMAND_SET_CAR_DRIVING_STYLE:
@@ -2311,40 +2574,42 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
return 0;
case COMMAND_PRINT_BIG:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
#ifdef MISSION_REPLAY
- if (strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "M_FAIL") == 0 && CanAllowMissionReplay())
- AllowMissionReplay = MISSION_RETRY_STAGE_WAIT_FOR_SCRIPT_TO_TERMINATE;
+ if (strcmp((char*)&CTheScripts::ScriptSpace[m_nIp - KEY_LENGTH_IN_SCRIPT], "M_FAIL") == 0) {
+ if (AllowMissionReplay == MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART)
+ AllowMissionReplay = MISSION_RETRY_STAGE_NORMAL;
+ if (CanAllowMissionReplay())
+ AllowMissionReplay = MISSION_RETRY_STAGE_WAIT_FOR_SCRIPT_TO_TERMINATE;
+ }
#endif
- m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 2);
CMessages::AddBigMessage(key, ScriptParams[0], ScriptParams[1] - 1);
return 0;
}
case COMMAND_PRINT:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessage(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
case COMMAND_PRINT_NOW:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessageJumpQ(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
+ /*
case COMMAND_PRINT_SOON:
{
- wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
+ wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);
CollectParameters(&m_nIp, 2);
CMessages::AddMessageSoon(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
+ */
case COMMAND_CLEAR_PRINTS:
CMessages::ClearMessages();
return 0;
@@ -2377,15 +2642,15 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
case COMMAND_DEBUG_OFF:
CTheScripts::DbgFlag = false;
return 0;
+ /*
case COMMAND_RETURN_TRUE:
UpdateCompareFlag(true);
return 0;
case COMMAND_RETURN_FALSE:
UpdateCompareFlag(false);
return 0;
- /* Special command only used by compiler.
- case COMMAND_VAR_INT:
*/
+ //case COMMAND_VAR_INT:
default:
script_assert(0);
break;
@@ -2438,8 +2703,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
if (!m_bIsMissionScript)
return 0;
- if (strcmp(m_abScriptName, "love3") == 0) /* A Drop in the Ocean */
- CPickups::RemoveAllFloatingPickups();
CTheScripts::MissionCleanUp.Process();
return 0;
}
@@ -2582,29 +2845,23 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(pPed->bInVehicle);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);
return 0;
}
case COMMAND_IS_PLAYER_IN_ANY_CAR:
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- UpdateCompareFlag(pPed->bInVehicle);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);
return 0;
}
case COMMAND_IS_BUTTON_PRESSED:
{
CollectParameters(&m_nIp, 2);
- bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0;
- if (CGame::playingIntro && ScriptParams[0] == 0 && ScriptParams[1] == 12) {
- if (CPad::GetPad(0)->GetLeftMouseJustDown() ||
- CPad::GetPad(0)->GetEnterJustDown() ||
- CPad::GetPad(0)->GetCharJustDown(' '))
- value = true;
- }
- UpdateCompareFlag(value);
+ UpdateCompareFlag(GetPadState(ScriptParams[0], ScriptParams[1]) != 0);
return 0;
}
+ /*
case COMMAND_GET_PAD_STATE:
{
CollectParameters(&m_nIp, 1);
@@ -2612,6 +2869,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:
case COMMAND_LOCATE_PLAYER_ON_FOOT_2D:
case COMMAND_LOCATE_PLAYER_IN_CAR_2D:
@@ -2678,6 +2936,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pObj->SetOrientation(0.0f, 0.0f, 0.0f);
pObj->GetMatrix().UpdateRW();
pObj->UpdateRwFrame();
+ CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi);
+ if (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding)
+ pObj->SetupBigBuilding();
CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
CWorld::Add(pObj);
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
@@ -2702,6 +2963,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
case COMMAND_ADD_SCORE:
CollectParameters(&m_nIp, 2);
CWorld::Players[ScriptParams[0]].m_nMoney += ScriptParams[1];
+ if (CWorld::Players[ScriptParams[0]].m_nMoney < 0)
+ CWorld::Players[ScriptParams[0]].m_nMoney = 0;
return 0;
case COMMAND_IS_SCORE_GREATER:
CollectParameters(&m_nIp, 2);
@@ -2744,12 +3007,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
case COMMAND_HAS_DEATHARREST_BEEN_EXECUTED:
UpdateCompareFlag(m_bDeatharrestExecuted);
return 0;
+ /*
case COMMAND_ADD_AMMO_TO_PLAYER:
{
CollectParameters(&m_nIp, 3);
CWorld::Players[ScriptParams[0]].m_pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
+ */
case COMMAND_ADD_AMMO_TO_CHAR:
{
CollectParameters(&m_nIp, 3);
@@ -2758,10 +3023,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
- /* Not implemented
- case COMMAND_ADD_AMMO_TO_CAR:
- case COMMAND_IS_PLAYER_STILL_ALIVE:
- */
+ //case COMMAND_ADD_AMMO_TO_CAR:
+ //case COMMAND_IS_PLAYER_STILL_ALIVE:
case COMMAND_IS_PLAYER_DEAD:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_WASTED);
@@ -2770,14 +3033,14 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(!pPed || pPed->GetPedState() == PED_DIE || pPed->GetPedState() == PED_DEAD);
+ UpdateCompareFlag(!pPed || pPed->DyingOrDead());
return 0;
}
case COMMAND_IS_CAR_DEAD:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater);
+ UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->bIsDrowning);
return 0;
}
case COMMAND_SET_CHAR_THREAT_SEARCH:
@@ -2788,9 +3051,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->m_fearFlags |= ScriptParams[1];
return 0;
}
- /* Not implemented.
- case COMMAND_SET_CHAR_THREAT_REACTION:
- */
+ //case COMMAND_SET_CHAR_THREAT_REACTION:
case COMMAND_SET_CHAR_OBJ_NO_OBJ:
{
CollectParameters(&m_nIp, 1);
@@ -2800,23 +3061,21 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->ClearObjective();
return 0;
}
- /* Not implemented.
- case COMMAND_ORDER_DRIVER_OUT_OF_CAR:
- case COMMAND_ORDER_CHAR_TO_DRIVE_CAR:
- case COMMAND_ADD_PATROL_POINT:
- case COMMAND_IS_PLAYER_IN_GANGZONE:
- */
+ //case COMMAND_ORDER_DRIVER_OUT_OF_CAR:
+ //case COMMAND_ORDER_CHAR_TO_DRIVE_CAR:
+ //case COMMAND_ADD_PATROL_POINT:
+ //case COMMAND_IS_PLAYER_IN_GANGZONE:
case COMMAND_IS_PLAYER_IN_ZONE:
{
CollectParameters(&m_nIp, 1);
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zoneToCheck != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != -1? */
CVector pos = pPlayer->GetPos();
- CZone* pZone = CTheZones::GetZone(zoneToCheck);
+ CZone* pZone = CTheZones::GetNavigationZone(zoneToCheck);
UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, pZone));
return 0;
}
@@ -2824,8 +3083,6 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->GetPedState() == PED_DRIVING &&
CPad::GetPad(ScriptParams[0])->GetHorn());
- /* Is it correct that same parameter is used both as index of Players */
- /* and as ID of pad? Pratically this parameter is always 0 anyway of course. */
return 0;
case COMMAND_HAS_CHAR_SPOTTED_PLAYER:
{
@@ -2835,10 +3092,8 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
UpdateCompareFlag(pPed->OurPedCanSeeThisOne(CWorld::Players[ScriptParams[1]].m_pPed));
return 0;
}
- /* Not implemented.
- case COMMAND_ORDER_CHAR_TO_BACKDOOR:
- case COMMAND_ADD_CHAR_TO_GANG:
- */
+ //case COMMAND_ORDER_CHAR_TO_BACKDOOR:
+ //case COMMAND_ADD_CHAR_TO_GANG:
case COMMAND_IS_CHAR_OBJECTIVE_PASSED:
{
CollectParameters(&m_nIp, 1);
@@ -2894,6 +3149,9 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPed->CharCreatedBy = MISSION_CHAR;
pPed->bRespondsToThreats = false;
pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
pPed->SetPosition(pVehicle->GetPosition());
pPed->SetOrientation(0.0f, 0.0f, 0.0f);
pPed->SetPedState(PED_DRIVING);
@@ -2909,13 +3167,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
pVehicle->bEngineOn = true;
pPed->bUsesCollision = false;
-#ifdef FIX_BUGS
- AnimationId anim = pVehicle->GetDriverAnim();
-#else
- AnimationId anim = pVehicle->bLowVehicle ? ANIM_STD_CAR_SIT_LO : ANIM_STD_CAR_SIT;
-#endif
- pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
- pPed->StopNonPartialAnims();
+ pPed->AddInCarAnims(pVehicle, true);
pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
CWorld::Add(pPed);
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
@@ -2944,18 +3196,18 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
pPlayer->m_pPed->m_pMyVehicle->RemovePassenger(pPlayer->m_pPed);
}
}
+ pPlayer->m_pPed->RemoveInCarAnims();
pPlayer->m_pPed->bInVehicle = false;
pPlayer->m_pPed->m_pMyVehicle = nil;
pPlayer->m_pPed->SetPedState(PED_IDLE);
pPlayer->m_pPed->bUsesCollision = true;
pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPlayer->m_pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPlayer->m_pPed->GetWeapon()->m_eWeaponType)->m_nModelId);
- pPlayer->m_pPed->RemoveInCarAnims();
+ pPlayer->m_pPed->ReplaceWeaponWhenExitingVehicle();
if (pPlayer->m_pPed->m_pVehicleAnim)
pPlayer->m_pPed->m_pVehicleAnim->blendDelta = -1000.0f;
pPlayer->m_pPed->m_pVehicleAnim = nil;
pPlayer->m_pPed->SetMoveState(PEDMOVE_NONE);
- CAnimManager::BlendAnimation(pPlayer->m_pPed->GetClump(), pPlayer->m_pPed->m_animGroup, ANIM_STD_IDLE, 100.0f);
+ CAnimManager::BlendAnimation(pPlayer->m_pPed->GetClump(), pPlayer->m_pPed->m_animGroup, ANIM_STD_IDLE, 1000.0f);
pPlayer->m_pPed->RestartNonPartialAnims();
AudioManager.PlayerJustLeftCar();
pos.z += pPlayer->m_pPed->GetDistanceFromCentreOfMassToBaseOfModel();
@@ -2963,9 +3215,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayer->m_pPed);
return 0;
}
- /* Not implemented.
- case COMMAND_MAKE_CHAR_DO_NOTHING:
- */
+ //case COMMAND_MAKE_CHAR_DO_NOTHING:
default:
script_assert(0);
break;
@@ -2979,21 +3229,15 @@ bool CRunningScript::CanAllowMissionReplay()
{
if (AllowMissionReplay != MISSION_RETRY_STAGE_NORMAL)
return false;
- if (CStats::LastMissionPassedName[0] == '\0')
- return false;
- for (int i = 0; i < ARRAY_SIZE(nonMissionScripts); i++) {
- if (strcmp(m_abScriptName, nonMissionScripts[i]) == 0)
- return false;
+ for (int i = 0; i < ARRAY_SIZE(MissionScripts); i++) {
+ if (!CGeneral::faststricmp(m_abScriptName, MissionScripts[i]))
+ return true;
}
- return true;
+ return false;
}
uint32 AddExtraDeathDelay()
{
- if (missionRetryScriptIndex == 63)
- return 7000;
- if (missionRetryScriptIndex == 64)
- return 4000;
return 1000;
}
diff --git a/src/control/Script.h b/src/control/Script.h
index eedf17d4..7f9a7717 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -6,6 +6,7 @@
class CEntity;
class CBuilding;
+class CPhysical;
class CVehicle;
class CPed;
class CObject;
@@ -20,18 +21,19 @@ void FlushLog();
#define PICKUP_PLACEMENT_OFFSET (0.5f)
#define PED_FIND_Z_OFFSET (5.0f)
+#define COP_PED_FIND_Z_OFFSET (10.0f)
#define UPSIDEDOWN_UP_THRESHOLD (-0.97f)
#define UPSIDEDOWN_MOVE_SPEED_THRESHOLD (0.01f)
#define UPSIDEDOWN_TURN_SPEED_THRESHOLD (0.02f)
#define UPSIDEDOWN_TIMER_THRESHOLD (1000)
-#define SPHERE_MARKER_R (0)
-#define SPHERE_MARKER_G (128)
-#define SPHERE_MARKER_B (255)
-#define SPHERE_MARKER_A (128)
-#define SPHERE_MARKER_PULSE_PERIOD (2048)
-#define SPHERE_MARKER_PULSE_FRACTION (0.1f)
+#define SPHERE_MARKER_R (252)
+#define SPHERE_MARKER_G (138)
+#define SPHERE_MARKER_B (242)
+#define SPHERE_MARKER_A (228)
+#define SPHERE_MARKER_PULSE_PERIOD 2048
+#define SPHERE_MARKER_PULSE_FRACTION 0.1f
#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
#define MILES_IN_METER (0.000621371192f)
@@ -45,9 +47,7 @@ void FlushLog();
#define KEY_LENGTH_IN_SCRIPT (8)
-#if GTA_VERSION <= GTA3_PS2_160
-#define GTA_SCRIPT_COLLECTIVE
-#endif
+//#define GTA_SCRIPT_COLLECTIVE
struct intro_script_rectangle
{
@@ -64,7 +64,7 @@ struct intro_script_rectangle
VALIDATE_SIZE(intro_script_rectangle, 0x18);
enum {
- SCRIPT_TEXT_MAX_LENGTH = 500
+ SCRIPT_TEXT_MAX_LENGTH = 100
};
struct intro_text_line
@@ -105,7 +105,7 @@ struct intro_text_line
m_sBackgroundColor = CRGBA(128, 128, 128, 128);
m_bTextProportional = true;
m_bTextBeforeFade = false;
- m_nFont = FONT_HEADING;
+ m_nFont = FONT_STANDARD;
m_fAtX = 0.0f;
m_fAtY = 0.0f;
memset(&m_Text, 0, sizeof(m_Text));
@@ -149,7 +149,7 @@ struct cleanup_entity_struct
enum {
MAX_CLEANUP = 50,
MAX_UPSIDEDOWN_CAR_CHECKS = 6,
- MAX_STUCK_CAR_CHECKS = 6
+ MAX_STUCK_CAR_CHECKS = 16
};
class CMissionCleanup
@@ -165,6 +165,7 @@ public:
void AddEntityToList(int32, uint8);
void RemoveEntityFromList(int32, uint8);
void Process();
+ void CheckIfCollisionHasLoadedForMissionObjects();
};
struct upsidedown_car_data
@@ -248,11 +249,7 @@ struct tBuildingSwap
enum {
-#if GTA_VERSION > GTA3_PS2_160
MAX_STACK_DEPTH = 6,
-#else
- MAX_STACK_DEPTH = 4,
-#endif
NUM_LOCAL_VARS = 16,
NUM_TIMERS = 2
};
@@ -287,6 +284,7 @@ public:
uint32 m_anStack[MAX_STACK_DEPTH];
uint16 m_nStackPointer;
int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];
+ bool m_bIsActive;
bool m_bCondResult;
bool m_bIsMissionScript;
bool m_bSkipWakeTime;
@@ -338,9 +336,11 @@ public:
int8 ProcessCommands800To899(int32);
int8 ProcessCommands900To999(int32);
int8 ProcessCommands1000To1099(int32);
-#if GTA_VERSION > GTA3_PS2_160
int8 ProcessCommands1100To1199(int32);
-#endif
+ int8 ProcessCommands1200To1299(int32);
+ int8 ProcessCommands1300To1399(int32);
+ int8 ProcessCommands1400To1499(int32);
+
void LocatePlayerCommand(int32, uint32*);
void LocatePlayerCharCommand(int32, uint32*);
void LocatePlayerCarCommand(int32, uint32*);
@@ -354,6 +354,8 @@ public:
void PlayerInAngledAreaCheckCommand(int32, uint32*);
void CharInAreaCheckCommand(int32, uint32*);
void CarInAreaCheckCommand(int32, uint32*);
+ void LocateObjectCommand(int32, uint32*);
+ void ObjectInAreaCheckCommand(int32, uint32*);
#ifdef GTA_SCRIPT_COLLECTIVE
void LocateCollectiveCommand(int32, uint32*);
@@ -381,26 +383,11 @@ public:
float LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; }
- bool ThisIsAValidRandomPed(uint32 pedtype) {
- switch (pedtype) {
- case PEDTYPE_CIVMALE:
- case PEDTYPE_CIVFEMALE:
- case PEDTYPE_GANG1:
- case PEDTYPE_GANG2:
- case PEDTYPE_GANG3:
- case PEDTYPE_GANG4:
- case PEDTYPE_GANG5:
- case PEDTYPE_GANG6:
- case PEDTYPE_GANG7:
- case PEDTYPE_GANG8:
- case PEDTYPE_GANG9:
- case PEDTYPE_CRIMINAL:
- case PEDTYPE_PROSTITUTE:
- return true;
- default:
- return false;
- }
- }
+ bool ThisIsAValidRandomCop(uint32 mi, int cop, int swat, int fbi, int army, int miami);
+ bool ThisIsAValidRandomPed(uint32 pedtype, int civ, int gang, int criminal);
+
+ bool CheckDamagedWeaponType(int32 actual, int32 type);
+
};
@@ -410,20 +397,22 @@ enum {
};
enum {
- SIZE_MAIN_SCRIPT = 128 * 1024,
- SIZE_MISSION_SCRIPT = 32 * 1024,
+#ifdef PS2
+ SIZE_MAIN_SCRIPT = 205512,
+#else
+ SIZE_MAIN_SCRIPT = 225512,
+#endif
+ SIZE_MISSION_SCRIPT = 35000,
SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT
};
enum {
MAX_NUM_SCRIPTS = 128,
- MAX_NUM_CONTACTS = 16,
- MAX_NUM_INTRO_TEXT_LINES = 2,
+ MAX_NUM_INTRO_TEXT_LINES = 48,
MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16,
- MAX_NUM_COLLECTIVES = 32,
- MAX_NUM_USED_OBJECTS = 200,
+ MAX_NUM_USED_OBJECTS = 220,
MAX_NUM_MISSION_SCRIPTS = 120,
MAX_NUM_BUILDING_SWAPS = 25,
MAX_NUM_INVISIBILITY_SETTINGS = 20,
@@ -435,13 +424,10 @@ class CTheScripts
public:
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
- static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS];
- static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
- static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES];
static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];
static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@@ -465,14 +451,26 @@ public:
static uint32 LargestMissionScriptSize;
static uint32 MainScriptSize;
static uint8 FailCurrentMission;
- static uint8 CountdownToMakePlayerUnsafe;
- static uint8 DelayMakingPlayerUnsafeThisTime;
static uint16 NumScriptDebugLines;
static uint16 NumberOfIntroRectanglesThisFrame;
static uint16 NumberOfIntroTextLinesThisFrame;
static uint8 UseTextCommands;
static uint16 CommandsExecuted;
static uint16 ScriptsUpdated;
+ static uint32 LastMissionPassedTime;
+ static uint16 NumberOfExclusiveMissionScripts;
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+#define CARDS_IN_SUIT (13)
+#define NUM_SUITS (4)
+#define MAX_DECKS (6)
+#define CARDS_IN_DECK (CARDS_IN_SUIT * NUM_SUITS)
+#define CARDS_IN_STACK (CARDS_IN_DECK * MAX_DECKS)
+ static int16 CardStack[CARDS_IN_STACK];
+ static int16 CardStackPosition;
+#endif
+ static bool bPlayerIsInTheStatium;
+ static uint8 RiotIntensity;
+ static bool bPlayerHasMetDebbieHarry;
static void Init();
static void Process();
@@ -495,9 +493,6 @@ public:
static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }
- static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; }
- static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; }
-
static int32 Read4BytesFromScript(uint32* pIp) {
int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 4;
@@ -559,6 +554,14 @@ public:
static int32 AddScriptSphere(int32 id, CVector pos, float radius);
static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index);
+ static void RemoveScriptTextureDictionary();
+public:
+ static void RemoveThisPed(CPed* pPed);
+
+ static uint32& GetLastMissionPassedTime() { return LastMissionPassedTime; }
+#ifdef MISSION_SWITCHER
+ static void SwitchToMission(int32 mission);
+#endif
#ifdef GTA_SCRIPT_COLLECTIVE
static void AdvanceCollectiveIndex()
@@ -579,9 +582,11 @@ public:
static void SetObjectiveForAllPedsInCollective(int, eObjective);
#endif
-#ifdef MISSION_SWITCHER
-public:
- static void SwitchToMission(int32 mission);
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ static bool MissionSupportsMissionReplay(int index)
+ {
+ return index >= 3 && index <= 35 || index >= 51 && index <= 65 || index >= 67 && index <= 74 || index >= 83 && index <= 87;
+ }
#endif
#ifdef USE_DEBUG_SCRIPT_LOADER
@@ -603,6 +608,14 @@ extern uint32 WaitForSave;
extern uint32 MissionStartTime;
extern int missionRetryScriptIndex;
extern bool doingMissionRetry;
+extern bool gbTryingPorn4Again;
+extern int IsInAmmunation;
+extern int MissionSkipLevel;
+
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+extern bool UsingMobileScript;
+extern bool AlreadySavedGame;
+#endif
uint32 AddExtraDeathDelay();
void RetryMission(int, int unk = 0);
diff --git a/src/control/Script2.cpp b/src/control/Script2.cpp
index d3ab2af7..4e7a1c3e 100644
--- a/src/control/Script2.cpp
+++ b/src/control/Script2.cpp
@@ -31,22 +31,21 @@
int8 CRunningScript::ProcessCommands300To399(int32 command)
{
switch (command) {
- /* Not implemented.
- case COMMAND_SET_CHAR_INVINCIBLE:
- case COMMAND_SET_PLAYER_INVINCIBLE:
- case COMMAND_SET_CHAR_GRAPHIC_TYPE:
- case COMMAND_SET_PLAYER_GRAPHIC_TYPE:
- */
+ //case COMMAND_SET_CHAR_INVINCIBLE:
+ //case COMMAND_SET_PLAYER_INVINCIBLE:
+ //case COMMAND_SET_CHAR_GRAPHIC_TYPE:
+ //case COMMAND_SET_PLAYER_GRAPHIC_TYPE:
+ /*
case COMMAND_HAS_PLAYER_BEEN_ARRESTED:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED);
return 0;
- /* Not implemented.
- case COMMAND_STOP_CHAR_DRIVING:
- case COMMAND_KILL_CHAR:
- case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR:
- case COMMAND_SET_CHAR_OCCUPATION:
*/
+ //case COMMAND_STOP_CHAR_DRIVING:
+ //case COMMAND_KILL_CHAR:
+ //case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR:
+ //case COMMAND_SET_CHAR_OCCUPATION:
+ /*
case COMMAND_CHANGE_CAR_LOCK:
{
CollectParameters(&m_nIp, 2);
@@ -62,6 +61,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
*(float*)&ScriptParams[2],
*(float*)&ScriptParams[3]);
return 0;
+ */
case COMMAND_IS_CAR_MODEL:
{
CollectParameters(&m_nIp, 2);
@@ -70,11 +70,10 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]);
return 0;
}
- /* Not implemented.
- case COMMAND_IS_CAR_REMAP:
- case COMMAND_HAS_CAR_JUST_SUNK:
- case COMMAND_SET_CAR_NO_COLLIDE:
- */
+ //case COMMAND_IS_CAR_REMAP:
+ //case COMMAND_HAS_CAR_JUST_SUNK:
+ //case COMMAND_SET_CAR_NO_COLLIDE:
+ /*
case COMMAND_IS_CAR_DEAD_IN_AREA_2D:
{
CollectParameters(&m_nIp, 6);
@@ -111,35 +110,39 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);
return 0;
}
- /* Not implemented.
- case COMMAND_IS_TRAILER_ATTACHED:
- case COMMAND_IS_CAR_ON_TRAILER:
- case COMMAND_HAS_CAR_GOT_WEAPON:
- case COMMAND_PARK:
- case COMMAND_HAS_PARK_FINISHED:
- case COMMAND_KILL_ALL_PASSENGERS:
- case COMMAND_SET_CAR_BULLETPROOF:
- case COMMAND_SET_CAR_FLAMEPROOF:
- case COMMAND_SET_CAR_ROCKETPROOF:
- case COMMAND_IS_CARBOMB_ACTIVE:
- case COMMAND_GIVE_CAR_ALARM:
- case COMMAND_PUT_CAR_ON_TRAILER:
*/
+ //case COMMAND_IS_TRAILER_ATTACHED:
+ //case COMMAND_IS_CAR_ON_TRAILER:
+ //case COMMAND_HAS_CAR_GOT_WEAPON:
+ //case COMMAND_PARK:
+ //case COMMAND_HAS_PARK_FINISHED:
+ //case COMMAND_KILL_ALL_PASSENGERS:
+ //case COMMAND_SET_CAR_BULLETPROOF:
+ //case COMMAND_SET_CAR_FLAMEPROOF:
+ //case COMMAND_SET_CAR_ROCKETPROOF:
+ //case COMMAND_IS_CARBOMB_ACTIVE:
+ //case COMMAND_GIVE_CAR_ALARM:
+ //case COMMAND_PUT_CAR_ON_TRAILER:
+ /*
case COMMAND_IS_CAR_CRUSHED:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0]));
return 0;
- /* Not implemented.
- case COMMAND_CREATE_GANG_CAR:
*/
+ //case COMMAND_CREATE_GANG_CAR:
case COMMAND_CREATE_CAR_GENERATOR:
+ {
CollectParameters(&m_nIp, 12);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z > MAP_Z_LOW_LIMIT)
+ pos.z += 0.015f;
ScriptParams[0] = CTheCarGenerators::CreateCarGenerator(
- *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3],
+ pos.x, pos.y, pos.z, *(float*)&ScriptParams[3],
ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7],
ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
StoreParameters(&m_nIp, 1);
return 0;
+ }
case COMMAND_SWITCH_CAR_GENERATOR:
{
CollectParameters(&m_nIp, 2);
@@ -154,6 +157,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
}
return 0;
}
+ /*
case COMMAND_ADD_PAGER_MESSAGE:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -161,11 +165,14 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]);
return 0;
}
+ */
case COMMAND_DISPLAY_ONSCREEN_TIMER:
{
script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
m_nIp++;
- CUserDisplay::OnscnTimer.AddClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp), nil);
+ uint16 offset = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 1);
+ CUserDisplay::OnscnTimer.AddClock(offset, nil, ScriptParams[0] != 0);
return 0;
}
case COMMAND_CLEAR_ONSCREEN_TIMER:
@@ -179,9 +186,9 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
{
script_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);
m_nIp++;
- uint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp);
+ int16 counter = CTheScripts::Read2BytesFromScript(&m_nIp);
CollectParameters(&m_nIp, 1);
- CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil);
+ CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil, 0);
return 0;
}
case COMMAND_CLEAR_ONSCREEN_COUNTER:
@@ -194,23 +201,30 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_SET_ZONE_CAR_INFO:
{
char label[12];
+ int16 gangDensities[NUM_GANGS] = { 0 };
+ int i;
+
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 16);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < NUM_GANGS; i++)
+ gangDensities[i] = ScriptParams[i + 2];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ for (int i = 0; i < NUM_GANGS; i++) {
+ if (gangDensities[i] != 0 && CGangs::GetGangInfo(i)->m_nVehicleMI == -1)
+ debug("SET_ZONE_CAR_INFO - Gang %d car ratio should be 0 in %s zone\n", i + 1, label);
+ }
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0,
- ScriptParams[9], ScriptParams[10], ScriptParams[11], ScriptParams[12],
- ScriptParams[13], ScriptParams[14], ScriptParams[15]);
+ while (zone >= 0) {
+ CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[11], gangDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
- /* Not implemented.
- case COMMAND_IS_CHAR_IN_GANG_ZONE:
- */
+ //case COMMAND_IS_CHAR_IN_GANG_ZONE:
case COMMAND_IS_CHAR_IN_ZONE:
{
CollectParameters(&m_nIp, 1);
@@ -218,41 +232,15 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
script_assert(pPed);
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetZone(zone)));
- return 0;
- }
- case COMMAND_SET_CAR_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += 8;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetCarDensity(zone, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
- case COMMAND_SET_PED_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetPedDensity(zone, ScriptParams[0], ScriptParams[1]);
+ UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetNavigationZone(zone)));
return 0;
}
+ //case COMMAND_SET_CAR_DENSITY:
+ //case COMMAND_SET_PED_DENSITY:
case COMMAND_POINT_CAMERA_AT_PLAYER:
{
CollectParameters(&m_nIp, 3);
@@ -264,43 +252,49 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
{
CollectParameters(&m_nIp, 3);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
- TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
+ if (pVehicle)
+ TheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
return 0;
}
case COMMAND_POINT_CAMERA_AT_CHAR:
{
CollectParameters(&m_nIp, 3);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
+ if (pPed)
+ TheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);
return 0;
}
case COMMAND_RESTORE_CAMERA:
TheCamera.Restore();
return 0;
+ /*
case COMMAND_SHAKE_PAD:
CPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]);
return 0;
+ */
case COMMAND_SET_ZONE_PED_INFO:
{
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 10);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, ScriptParams[9]);
+ while (zone >= 0) {
+ CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
+ ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
case COMMAND_SET_TIME_SCALE:
CollectParameters(&m_nIp, 1);
CTimer::SetTimeScale(*(float*)&ScriptParams[0]);
return 0;
+ /*
case COMMAND_IS_CAR_IN_AIR:
{
CollectParameters(&m_nIp, 1);
@@ -310,6 +304,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
UpdateCompareFlag(pCar->GetAllWheelsOffGround());
return 0;
}
+ */
case COMMAND_SET_FIXED_CAMERA_POSITION:
{
CollectParameters(&m_nIp, 6);
@@ -332,7 +327,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 3);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
StoreParameters(&m_nIp, 1);
@@ -343,23 +337,23 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 3);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
ScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_ADD_BLIP_FOR_OBJECT_OLD:
{
CollectParameters(&m_nIp, 3);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
ScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_REMOVE_BLIP:
CollectParameters(&m_nIp, 1);
CRadar::ClearBlip(ScriptParams[0]);
@@ -378,7 +372,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
ScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]);
StoreParameters(&m_nIp, 1);
@@ -429,6 +422,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CRestart::OverrideNextRestart(pos, angle);
return 0;
}
+ /*
case COMMAND_DRAW_SHADOW:
{
CollectParameters(&m_nIp, 10);
@@ -447,17 +441,22 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
float frontY = y;
float sideX = y;
float sideY = x;
- /* Not very nicely named intermediate variables. */
CShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY,
ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]);
return 0;
}
+ */
case COMMAND_GET_PLAYER_HEADING:
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ angle = RADTODEG(angle);
+ if (angle < 0.0f)
+ angle += 360.0f;
+ if (angle > 360.0f)
+ angle -= 360.0f;
+ *(float*)&ScriptParams[0] = angle;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -465,10 +464,9 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
{
CollectParameters(&m_nIp, 2);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- if (pPed->bInVehicle){
- // Is script_assertion required?
+ script_assert(pPed);
+ if (pPed->bInVehicle)
return 0;
- }
pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
return 0;
@@ -479,7 +477,12 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
float angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ angle = RADTODEG(angle);
+ if (angle < 0.0f)
+ angle += 360.0f;
+ if (angle > 360.0f)
+ angle -= 360.0f;
+ *(float*)&ScriptParams[0] = angle;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -488,10 +491,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- if (pPed->bInVehicle) {
- // Is script_assertion required?
+ if (pPed->bInVehicle)
return 0;
- }
pPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);
pPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));
return 0;
@@ -502,7 +503,12 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
float angle = pVehicle->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ angle = RADTODEG(angle);
+ if (angle < 0.0f)
+ angle += 360.0f;
+ if (angle > 360.0f)
+ angle -= 360.0f;
+ *(float*)&ScriptParams[0] = angle;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -520,7 +526,12 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
float angle = pObject->GetForward().Heading();
- *(float*)&ScriptParams[0] = CGeneral::LimitAngle(RADTODEG(angle));
+ angle = RADTODEG(angle);
+ if (angle < 0.0f)
+ angle += 360.0f;
+ if (angle > 360.0f)
+ angle -= 360.0f;
+ *(float*)&ScriptParams[0] = angle;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -536,6 +547,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CWorld::Add(pObject);
return 0;
}
+ /*
case COMMAND_IS_PLAYER_TOUCHING_OBJECT:
{
CollectParameters(&m_nIp, 2);
@@ -557,12 +569,14 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
UpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));
return 0;
}
+ */
case COMMAND_SET_PLAYER_AMMO:
{
CollectParameters(&m_nIp, 3);
CWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
+ /*
case COMMAND_SET_CHAR_AMMO:
{
CollectParameters(&m_nIp, 3);
@@ -570,23 +584,17 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);
return 0;
}
- /* Not implemented.
- case COMMAND_SET_CAR_AMMO:
- case COMMAND_LOAD_CAMERA_SPLINE:
- case COMMAND_MOVE_CAMERA_ALONG_SPLINE:
- case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:
*/
+ //case COMMAND_SET_CAR_AMMO:
+ //case COMMAND_LOAD_CAMERA_SPLINE:
+ //case COMMAND_MOVE_CAMERA_ALONG_SPLINE:
+ //case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:
case COMMAND_DECLARE_MISSION_FLAG:
CTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp);
return 0;
case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
- CollectParameters(&m_nIp, 1);
- CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp);
- return 0;
- case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
- CollectParameters(&m_nIp, 2);
- CTheScripts::BaseBriefIdForContact[ScriptParams[0]] = ScriptParams[1];
return 0;
+ //case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
case COMMAND_IS_PLAYER_HEALTH_GREATER:
{
CollectParameters(&m_nIp, 2);
@@ -615,7 +623,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
int handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);
CRadar::ChangeBlipScale(handle, 3);
@@ -628,7 +635,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
int handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);
CRadar::ChangeBlipScale(handle, 3);
@@ -641,7 +647,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CollectParameters(&m_nIp, 1);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
- // Useless call.
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
int handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);
CRadar::ChangeBlipScale(handle, 3);
@@ -655,7 +660,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
int handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);
CRadar::ChangeBlipScale(handle, 3);
@@ -669,7 +673,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- // Useless call
CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
int handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
CRadar::ChangeBlipScale(handle, 3);
@@ -685,12 +688,6 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
{
CollectParameters(&m_nIp, 4);
switch (ScriptParams[3]) {
- case SCRIPT_SOUND_EVIDENCE_PICKUP:
- DMAudio.PlayFrontEndSound(SOUND_EVIDENCE_PICKUP, 0);
- return 0;
- case SCRIPT_SOUND_UNLOAD_GOLD:
- DMAudio.PlayFrontEndSound(SOUND_UNLOAD_GOLD, 0);
- return 0;
case SCRIPT_SOUND_PART_MISSION_COMPLETE:
DMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0);
return 0;
@@ -706,14 +703,20 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case SCRIPT_SOUND_RACE_START_GO:
DMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0);
return 0;
+ case SCRIPT_SOUND_AMMUNATION_BUY_WEAPON:
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, 0);
+ return 0;
+ case SCRIPT_SOUND_AMMUNATION_BUY_WEAPON_DENIED:
+ DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 0);
+ return 0;
+ case SCRIPT_SOUND_IMRAN_ARM_BOMB:
+ DMAudio.PlayFrontEndSound(SOUND_AMMUNATION_IMRAN_ARM_BOMB, 0);
+ return 0;
default:
break;
}
-#ifdef FIX_BUGS
- /* BUG: if audio is not initialized, this object will not be freed. */
if (!DMAudio.IsAudioInitialised())
return 0;
-#endif
cAudioScriptObject* obj = new cAudioScriptObject();
obj->Posn = *(CVector*)&ScriptParams[0];
obj->AudioId = ScriptParams[3];
@@ -724,11 +727,15 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_ADD_CONTINUOUS_SOUND:
{
CollectParameters(&m_nIp, 4);
- cAudioScriptObject* obj = new cAudioScriptObject();
- obj->Posn = *(CVector*)&ScriptParams[0];
- obj->AudioId = ScriptParams[3];
- obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj);
- ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj);
+ if (DMAudio.IsAudioInitialised()) {
+ cAudioScriptObject* obj = new cAudioScriptObject();
+ obj->Posn = *(CVector*)&ScriptParams[0];
+ obj->AudioId = ScriptParams[3];
+ obj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj);
+ ScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj);
+ }
+ else
+ ScriptParams[0] = -1;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -773,7 +780,6 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- script_assert(pVehicle);
CTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]);
return 0;
}
@@ -807,6 +813,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos);
return 0;
}
+ /*
case COMMAND_SET_CHAR_OBJ_GUARD_AREA:
{
CollectParameters(&m_nIp, 5);
@@ -842,6 +849,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_WAIT_IN_CAR);
return 0;
}
+ */
case COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:
case COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:
case COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:
@@ -890,31 +898,21 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
pPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]));
- if (pPed->bInVehicle)
+ if (pPed->bInVehicle && pPed->m_pMyVehicle)
pPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
return 0;
}
- /* Not implemented */
//case COMMAND_GIVE_WEAPON_TO_CAR:
case COMMAND_SET_PLAYER_CONTROL:
{
CollectParameters(&m_nIp, 2);
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
if (ScriptParams[1]){
- if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){
- CTheScripts::CountdownToMakePlayerUnsafe = 50;
- if (CTheScripts::DelayMakingPlayerUnsafeThisTime)
- CTheScripts::DelayMakingPlayerUnsafeThisTime--;
- }else{
- pPlayer->MakePlayerSafe(false);
- }
+ pPlayer->MakePlayerSafe(false);
+ if (strcmp(m_abScriptName, "serg1") == 0) // Four Iron
+ pPlayer->m_pPed->ClearFollowPath();
}else{
pPlayer->MakePlayerSafe(true);
- if (strcmp(m_abScriptName, "camera") == 0){
- pPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPlayer->m_pPed->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- CAnimManager::BlendAnimation((RpClump*)pPlayer->m_pPed->m_rwObject, pPlayer->m_pPed->m_animGroup, ANIM_STD_IDLE, 1000.0f);
- }
}
return 0;
}
@@ -933,7 +931,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
{
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++){
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++){
if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
pPed->m_nSelectedWepSlot = i;
}
@@ -943,13 +941,12 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
{
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
if (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])
pPed->SetCurrentWeapon(i);
}
return 0;
}
- /* Not implemented */
//case COMMAND_SET_CURRENT_CAR_WEAPON:
case COMMAND_GET_OBJECT_COORDINATES:
{
@@ -1139,10 +1136,13 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->CharCreatedBy = MISSION_CHAR;
pPed->bRespondsToThreats = false;
pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
pPed->SetPosition(pVehicle->GetPosition());
pPed->SetOrientation(0.0f, 0.0f, 0.0f);
- pPed->SetPedState(PED_DRIVING);
CPopulation::ms_nTotalMissionPeds++;
+ CWorld::Add(pPed);
if (ScriptParams[3] >= 0)
pVehicle->AddPassenger(pPed, ScriptParams[3]);
else
@@ -1151,17 +1151,9 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
pPed->bInVehicle = true;
pPed->SetPedState(PED_DRIVING);
- pVehicle->SetStatus(STATUS_PHYSICS);
pPed->bUsesCollision = false;
-#ifdef FIX_BUGS
- AnimationId anim = pVehicle->GetDriverAnim();
-#else
- AnimationId anim = pVehicle->bLowVehicle ? ANIM_STD_CAR_SIT_LO : ANIM_STD_CAR_SIT;
-#endif
- pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f);
- pPed->StopNonPartialAnims();
+ pPed->AddInCarAnims(pVehicle, false);
pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());
- CWorld::Add(pPed);
ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
StoreParameters(&m_nIp, 1);
if (m_bIsMissionScript)
@@ -1208,6 +1200,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);
return 0;
}
+ /*
case COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:
{
CollectParameters(&m_nIp, 2);
@@ -1218,6 +1211,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);
return 0;
}
+ */
case COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:
{
CollectParameters(&m_nIp, 2);
@@ -1298,11 +1292,18 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);
return 0;
}
- /* Not implemented.
- case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR:
- case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
+ //case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR:
+ //case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:
case COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT:
- */
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_DESTROY_OBJECT, pObject);
+ return 0;
+ }
case COMMAND_SET_CHAR_OBJ_DESTROY_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -1313,6 +1314,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle);
return 0;
}
+ /*
case COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT:
{
CollectParameters(&m_nIp, 5);
@@ -1339,11 +1341,10 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius);
return 0;
}
- /* Not implemented.
- case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR:
- case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
- case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK:
*/
+ //case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR:
+ //case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ //case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK:
case COMMAND_SET_CHAR_AS_LEADER:
{
CollectParameters(&m_nIp, 2);
@@ -1406,9 +1407,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);
return 0;
}
- /* Not implemented.
- case COMMAND_PRINT_WITH_NUMBER_SOON:
- */
+ //case COMMAND_PRINT_WITH_NUMBER_SOON:
case COMMAND_SWITCH_ROADS_ON:
{
CollectParameters(&m_nIp, 6);
@@ -1486,7 +1485,16 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- pVehicle->bIsHeavy = (ScriptParams[1] != 0);
+ if (ScriptParams[1] != 0) {
+ pVehicle->bIsHeavy = true;
+ pVehicle->m_fMass = 3.0f * pVehicle->pHandling->fMass;
+ pVehicle->m_fTurnMass = 5.0f * pVehicle->pHandling->fTurnMass;
+ }
+ else {
+ pVehicle->bIsHeavy = false;
+ pVehicle->m_fMass = pVehicle->pHandling->fMass;
+ pVehicle->m_fTurnMass = pVehicle->pHandling->fTurnMass;
+ }
return 0;
}
case COMMAND_CLEAR_CHAR_THREAT_SEARCH:
@@ -1497,6 +1505,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
pPed->m_fearFlags = 0;
return 0;
}
+ /*
case COMMAND_ACTIVATE_CRANE:
{
CollectParameters(&m_nIp, 10);
@@ -1524,28 +1533,21 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
return 0;
}
+ */
case COMMAND_SET_MAX_WANTED_LEVEL:
{
CollectParameters(&m_nIp, 1);
CWanted::SetMaximumWantedLevel(ScriptParams[0]);
return 0;
}
- /* Debug commands?
- case COMMAND_SAVE_VAR_INT:
- case COMMAND_SAVE_VAR_FLOAT:
- */
+ //case COMMAND_SAVE_VAR_INT:
+ //case COMMAND_SAVE_VAR_FLOAT:
case COMMAND_IS_CAR_IN_AIR_PROPER:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
-#ifdef FIX_BUGS
- // don't wanna get stuck in unique stunt jump cam forever
- bool usj_with_dodo = strcmp(m_abScriptName, "usj") == 0 && pVehicle->GetModelIndex() == MI_DODO;
- UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0 && !usj_with_dodo);
-#else
UpdateCompareFlag(pVehicle->m_nCollisionRecords == 0);
-#endif
return 0;
}
default:
diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp
index ac88347b..f831645e 100644
--- a/src/control/Script3.cpp
+++ b/src/control/Script3.cpp
@@ -32,6 +32,8 @@
#include "WaterLevel.h"
#include "Weather.h"
#include "Zones.h"
+#include "GameLogic.h"
+#include "Bike.h"
#include "Wanted.h"
int8 CRunningScript::ProcessCommands500To599(int32 command)
@@ -71,6 +73,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
}
return 0;
}
+ /*
case COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -79,6 +82,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
ScriptParams[1], ScriptParams[2], ScriptParams[3]);
return 0;
}
+ */
case COMMAND_START_KILL_FRENZY:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -145,7 +149,12 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
}
case COMMAND_ADD_EXPLOSION:
CollectParameters(&m_nIp, 4);
- CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0);
+#ifdef SIMPLER_MISSIONS
+ if (!CGeneral::faststricmp(m_abScriptName, "hait2"))
+ CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true, 11.25f);
+ else
+#endif
+ CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true);
return 0;
case COMMAND_IS_CAR_UPRIGHT:
@@ -223,7 +232,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target);
return 0;
}
- /* Not implemented*/
//case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR:
case COMMAND_CREATE_PICKUP:
{
@@ -263,6 +271,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_NUMBER_BIG_Q:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -271,56 +280,39 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
ScriptParams[0], -1, -1, -1, -1, -1);
return 0;
}
+ */
case COMMAND_SET_GARAGE:
{
- CollectParameters(&m_nIp, 7);
+ CollectParameters(&m_nIp, 9);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), ScriptParams[6], 0);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, ScriptParams[8], 0);
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_SET_GARAGE_WITH_CAR_MODEL:
{
- CollectParameters(&m_nIp, 8);
+ CollectParameters(&m_nIp, 10);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(CVector(infX, infY, infZ), CVector(supX, supY, supZ), ScriptParams[6], ScriptParams[7]);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, ScriptParams[8], ScriptParams[9]);
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE:
{
CollectParameters(&m_nIp, 2);
@@ -339,11 +331,11 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CGarages::HasCarBeenDroppedOffYet(ScriptParams[0]));
return 0;
+/*
case COMMAND_SET_FREE_BOMBS:
CollectParameters(&m_nIp, 1);
CGarages::SetFreeBombs(ScriptParams[0] != 0);
return 0;
-#if GTA_VERSION <= GTA3_PS2_160
case COMMAND_SET_POWERPOINT:
{
CollectParameters(&m_nIp, 7);
@@ -377,7 +369,6 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
return 0;
}
-#endif // GTA_VERSION <= GTA3_PS2_160
case COMMAND_SET_ALL_TAXI_LIGHTS:
CollectParameters(&m_nIp, 1);
CAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);
@@ -391,6 +382,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
UpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum
return 0;
}
+ */
case COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR:
CollectParameters(&m_nIp, 2);
CPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0);
@@ -400,7 +392,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- pPed->m_fHealth = ScriptParams[1];
+ pPed->m_fHealth = Min(ScriptParams[1], CWorld::Players[ScriptParams[0]].m_nMaxHealth);
return 0;
}
case COMMAND_SET_CHAR_HEALTH:
@@ -417,7 +409,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->FlagToDestroyWhenNextProcessed();
}
else {
- pPed->SetDie(ANIM_STD_KO_FRONT, 4.0f, 0.0f);
+ pPed->SetDie();
}
return 0;
}
@@ -434,7 +426,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
+ ScriptParams[0] = pPed->m_fHealth;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -443,7 +435,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- ScriptParams[0] = pPed->m_fHealth; // correct cast float to int
+ ScriptParams[0] = pPed->m_fHealth;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -452,19 +444,21 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- ScriptParams[0] = pVehicle->m_fHealth; // correct cast float to int
+ ScriptParams[0] = pVehicle->m_fHealth;
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_IS_CAR_ARMED_WITH_BOMB:
{
CollectParameters(&m_nIp, 2);
CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pCar);
script_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);
- UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]); //TODO: enum
+ UpdateCompareFlag(pCar->m_bombType == ScriptParams[1]);
return 0;
}
+ */
case COMMAND_CHANGE_CAR_COLOUR:
{
CollectParameters(&m_nIp, 3);
@@ -578,15 +572,19 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pSourcePed->RestorePreviousState();
return 0;
}
+ /*
case COMMAND_SWITCH_HELICOPTER:
CollectParameters(&m_nIp, 1);
CHeli::ActivateHeli(ScriptParams[0] != 0);
return 0;
-
- //case COMMAND_SET_GANG_ATTITUDE:
- //case COMMAND_SET_GANG_GANG_ATTITUDE:
- //case COMMAND_SET_GANG_PLAYER_ATTITUDE:
- //case COMMAND_SET_GANG_PED_MODELS:
+ */
+ //case COMMAND_SET_GANG_ATTITUDE:
+ //case COMMAND_SET_GANG_GANG_ATTITUDE:
+ //case COMMAND_SET_GANG_PLAYER_ATTITUDE:
+ case COMMAND_SET_GANG_PED_MODELS:
+ CollectParameters(&m_nIp, 3);
+ CGangs::SetGangPedModels(ScriptParams[0], ScriptParams[1], ScriptParams[2]);
+ return 0;
case COMMAND_SET_GANG_CAR_MODEL:
CollectParameters(&m_nIp, 2);
CGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]);
@@ -595,6 +593,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CollectParameters(&m_nIp, 3);
CGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]);
return 0;
+ /*
case COMMAND_SET_CHAR_OBJ_RUN_TO_AREA:
{
CollectParameters(&m_nIp, 5);
@@ -621,6 +620,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius);
return 0;
}
+ */
case COMMAND_SET_CHAR_OBJ_RUN_TO_COORD:
{
CollectParameters(&m_nIp, 3);
@@ -634,6 +634,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos);
return 0;
}
+ /*
case COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT:
{
CollectParameters(&m_nIp, 2);
@@ -662,6 +663,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
UpdateCompareFlag(isTouching);
return 0;
}
+ */
case COMMAND_LOAD_SPECIAL_CHARACTER:
{
CollectParameters(&m_nIp, 1);
@@ -679,6 +681,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
UpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1));
return 0;
}
+ /*
case COMMAND_FLASH_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -703,10 +706,12 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pObject->bHasBlip = (ScriptParams[1] != 0);
return 0;
}
+ */
case COMMAND_IS_PLAYER_IN_REMOTE_MODE:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode());
return 0;
+ /*
case COMMAND_ARM_CAR_WITH_BOMB:
{
CollectParameters(&m_nIp, 2);
@@ -717,6 +722,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed();
return 0;
}
+ */
case COMMAND_SET_CHAR_PERSONALITY:
{
CollectParameters(&m_nIp, 2);
@@ -737,6 +743,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
return 0;
}
+ /*
case COMMAND_SET_ANIM_GROUP_FOR_PLAYER:
{
CollectParameters(&m_nIp, 2);
@@ -745,6 +752,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
pPed->m_animGroup = (AssocGroupId)ScriptParams[1];
return 0;
}
+ */
case COMMAND_REQUEST_MODEL:
{
CollectParameters(&m_nIp, 1);
@@ -779,6 +787,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_SET_REPEATED_PHONE_MESSAGE:
{
CollectParameters(&m_nIp, 1);
@@ -799,6 +808,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0]));
return 0;
}
+ */
case COMMAND_TURN_PHONE_OFF:
{
CollectParameters(&m_nIp, 1);
@@ -812,7 +822,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8],
- 255, pos, *(float*)&ScriptParams[3], 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);
+ 255, pos, *(float*)&ScriptParams[3], 450.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);
return 0;
}
case COMMAND_DRAW_LIGHT:
@@ -824,18 +834,15 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
ScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true);
return 0;
}
- case COMMAND_STORE_WEATHER:
- CWeather::StoreWeatherState();
- return 0;
- case COMMAND_RESTORE_WEATHER:
- CWeather::RestoreWeatherState();
- return 0;
+ //case COMMAND_STORE_WEATHER:
+ //case COMMAND_RESTORE_WEATHER:
case COMMAND_STORE_CLOCK:
CClock::StoreClock();
return 0;
case COMMAND_RESTORE_CLOCK:
CClock::RestoreClock();
return 0;
+ /*
case COMMAND_RESTART_CRITICAL_MISSION:
{
CollectParameters(&m_nIp, 4);
@@ -848,6 +855,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission();
return 0;
}
+ */
case COMMAND_IS_PLAYER_PLAYING:
{
CollectParameters(&m_nIp, 1);
@@ -1206,19 +1214,25 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);
+ //assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ // they DO call this for bikes, we don't really want to destroy the structure...
+#ifdef FIX_BUGS
+ if (pVehicle->m_vehType == VEHICLE_TYPE_CAR)
+#endif
+ ((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);
+
return 0;
}
+ /*
case COMMAND_IS_TAXI:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- int mi = pVehicle->GetModelIndex();
- UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
+ UpdateCompareFlag(pVehicle->IsTaxi());
return 0;
}
+ */
case COMMAND_UNLOAD_SPECIAL_CHARACTER:
CollectParameters(&m_nIp, 1);
CStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1);
@@ -1231,6 +1245,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
ScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]);
StoreParameters(&m_nIp, 1);
return 0;
+ /*
case COMMAND_ACTIVATE_GARAGE:
CollectParameters(&m_nIp, 1);
CGarages::ActivateGarage(ScriptParams[0]);
@@ -1246,12 +1261,13 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
}
return 0;
}
+ */
case COMMAND_CREATE_OBJECT_NO_OFFSET:
{
CollectParameters(&m_nIp, 4);
int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;
CObject* pObj = new CObject(mi, false);
- pObj->ObjectCreatedBy = MISSION_OBJECT;
+; pObj->ObjectCreatedBy = MISSION_OBJECT;
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -1259,6 +1275,9 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
pObj->SetOrientation(0.0f, 0.0f, 0.0f);
pObj->GetMatrix().UpdateRW();
pObj->UpdateRwFrame();
+ CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi);
+ if (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding)
+ pObj->SetupBigBuilding();
CTheScripts::ClearSpaceForMissionEntity(pos, pObj);
CWorld::Add(pObj);
ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);
@@ -1267,6 +1286,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);
return 0;
}
+ /*
case COMMAND_IS_BOAT:
{
CollectParameters(&m_nIp, 1);
@@ -1301,6 +1321,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);
return 0;
}
+ */
#ifdef GTA_SCRIPT_COLLECTIVE
case COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS:
{
@@ -1332,7 +1353,9 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
UpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer));
return 0;
+
}
+ /*
case COMMAND_IS_CHAR_STOPPED:
{
CollectParameters(&m_nIp, 1);
@@ -1355,6 +1378,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);
return 0;
}
+ */
case COMMAND_SWITCH_WIDESCREEN:
CollectParameters(&m_nIp, 1);
if (ScriptParams[0] != 0)
@@ -1362,6 +1386,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
else
TheCamera.SetWideScreenOff();
return 0;
+ /*
case COMMAND_ADD_SPRITE_BLIP_FOR_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -1398,6 +1423,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT:
{
CollectParameters(&m_nIp, 4);
@@ -1478,6 +1504,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
case COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:
PlayerInAngledAreaCheckCommand(command, &m_nIp);
return 0;
+ /*
case COMMAND_DEACTIVATE_GARAGE:
CollectParameters(&m_nIp, 1);
CGarages::DeActivateGarage(ScriptParams[0]);
@@ -1491,6 +1518,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CollectParameters(&m_nIp, 2);
UpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1));
return 0;
+ */
default:
script_assert(0);
}
@@ -1500,6 +1528,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
int8 CRunningScript::ProcessCommands700To799(int32 command)
{
switch (command){
+ /*
case COMMAND_SET_SWAT_REQUIRED:
CollectParameters(&m_nIp, 1);
FindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0);
@@ -1512,6 +1541,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 1);
FindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0);
return 0;
+ */
case COMMAND_IS_CAR_IN_WATER:
{
CollectParameters(&m_nIp, 1);
@@ -1525,7 +1555,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)];
+ CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f, true)];
*(CVector*)&ScriptParams[0] = pNode->GetPosition();
StoreParameters(&m_nIp, 3);
return 0;
@@ -1536,8 +1566,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)];
- *(CVector*)&ScriptParams[0] = pNode->GetPosition();
+ *(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true));
StoreParameters(&m_nIp, 3);
return 0;
}
@@ -1556,10 +1585,11 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE;
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->bEngineOn = true;
- pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
+ pVehicle->AutoPilot.m_nCruiseSpeed = Max(1, pVehicle->AutoPilot.m_nCruiseSpeed);
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
return 0;
}
+ /*
case COMMAND_START_PACMAN_RACE:
CollectParameters(&m_nIp, 1);
CPacManPickups::StartPacManRace(ScriptParams[0]);
@@ -1590,6 +1620,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:
CPacManPickups::ResetPowerPillsCarriedByPlayer();
return 0;
+ */
case COMMAND_IS_CAR_ON_SCREEN:
{
CollectParameters(&m_nIp, 1);
@@ -1614,6 +1645,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
UpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius()));
return 0;
}
+ /*
case COMMAND_GOSUB_FILE:
{
CollectParameters(&m_nIp, 2);
@@ -1623,6 +1655,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
// ScriptParams[1] == filename
return 0;
}
+ */
case COMMAND_GET_GROUND_Z_FOR_3D_COORD:
{
CollectParameters(&m_nIp, 3);
@@ -1650,6 +1683,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 1);
gFireManager.RemoveScriptFire(ScriptParams[0]);
return 0;
+ /*
case COMMAND_SET_COMEDY_CONTROLS:
{
CollectParameters(&m_nIp, 2);
@@ -1658,6 +1692,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pVehicle->bComedyControls = (ScriptParams[1] != 0);
return 0;
}
+ */
case COMMAND_BOAT_GOTO_COORDS:
{
CollectParameters(&m_nIp, 4);
@@ -1672,7 +1707,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pBoat->AutoPilot.m_vecDestinationCoors = pos;
pBoat->SetStatus(STATUS_PHYSICS);
pBoat->bEngineOn = true;
- pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed);
+ pBoat->AutoPilot.m_nCruiseSpeed = Max(1, pBoat->AutoPilot.m_nCruiseSpeed);
pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
return 0;
}
@@ -1726,7 +1761,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 2);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+ UpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType);
return 0;
}
case COMMAND_IS_CURRENT_CHAR_WEAPON:
@@ -1734,9 +1769,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- UpdateCompareFlag(ScriptParams[1] == pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType);
+ UpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType);
return 0;
}
+ /*
case COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:
CPacManPickups::ResetPowerPillsEatenInRace();
return 0;
@@ -1749,6 +1785,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CPacManPickups::GenerateOnePMPickUp(pos);
return 0;
}
+ */
case COMMAND_SET_BOAT_CRUISE_SPEED:
{
CollectParameters(&m_nIp, 2);
@@ -1759,6 +1796,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];
return 0;
}
+ /*
case COMMAND_GET_RANDOM_CHAR_IN_AREA:
{
CollectParameters(&m_nIp, 4);
@@ -1783,8 +1821,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
- continue;
+// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+// continue;
if (!ThisIsAValidRandomPed(pPed->m_nPedType))
continue;
if (pPed->bIsLeader || pPed->m_leader)
@@ -1807,14 +1845,16 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_GET_RANDOM_CHAR_IN_ZONE:
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
+ CollectParameters(&m_nIp, 3);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -1832,9 +1872,9 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+ if (pPed->m_nWaitState != WAITSTATE_FALSE)
continue;
- if (!ThisIsAValidRandomPed(pPed->m_nPedType))
+ if (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[0], ScriptParams[1], ScriptParams[2]))
continue;
if (pPed->bIsLeader || pPed->m_leader)
continue;
@@ -1844,6 +1884,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
continue;
+ bool found;
+ CWorld::FindRoofZFor3DCoord(pos.x, pos.y, pos.z, &found);
+ if (found)
+ continue;
ped_handle = CPools::GetPedPool()->GetIndex(pPed);
CTheScripts::LastRandomPedId = ped_handle;
pPed->CharCreatedBy = MISSION_CHAR;
@@ -1964,6 +2008,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 1);
CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0];
return 0;
+ /*
case COMMAND_IS_PROJECTILE_IN_AREA:
{
CollectParameters(&m_nIp, 6);
@@ -2034,6 +2079,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);
return 0;
}
+ */
case COMMAND_IS_CHAR_MODEL:
{
CollectParameters(&m_nIp, 2);
@@ -2053,29 +2099,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
m_nIp += KEY_LENGTH_IN_SCRIPT;
return 0;
}
- case COMMAND_CREATE_CUTSCENE_HEAD:
- {
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pObject);
- CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
- StoreParameters(&m_nIp, 1);
- return 0;
- }
- case COMMAND_SET_CUTSCENE_HEAD_ANIM:
- {
- CollectParameters(&m_nIp, 1);
- CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- script_assert(pCutHead);
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CTimer::Stop();
- CCutsceneMgr::SetHeadAnim(name, pCutHead);
- CTimer::Update();
- return 0;
- }
+ //case COMMAND_CREATE_CUTSCENE_HEAD:
+ //case COMMAND_SET_CUTSCENE_HEAD_ANIM:
case COMMAND_SIN:
CollectParameters(&m_nIp, 1);
*(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0]));
@@ -2108,6 +2133,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CollectParameters(&m_nIp, 2);
CGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1], 0);
return 0;
+ /*
case COMMAND_ACTIVATE_CRUSHER_CRANE:
{
CollectParameters(&m_nIp, 10);
@@ -2136,6 +2162,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
return 0;
}
+ */
case COMMAND_PRINT_WITH_2_NUMBERS_NOW:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2143,6 +2170,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_2_NUMBERS_SOON:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2150,6 +2178,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
return 0;
}
+ */
case COMMAND_PRINT_WITH_3_NUMBERS:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2157,6 +2186,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_3_NUMBERS_NOW:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2171,6 +2201,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);
return 0;
}
+ */
case COMMAND_PRINT_WITH_4_NUMBERS:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2178,6 +2209,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_4_NUMBERS_NOW:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2213,6 +2245,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);
return 0;
}
+ */
case COMMAND_PRINT_WITH_6_NUMBERS:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2220,6 +2253,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_6_NUMBERS_NOW:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -2245,6 +2279,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pPed->SetFormation((eFormation)ScriptParams[2]);
return 0;
}
+ */
case COMMAND_PLAYER_MADE_PROGRESS:
CollectParameters(&m_nIp, 1);
CStats::ProgressMade += ScriptParams[0];
@@ -2252,6 +2287,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
case COMMAND_SET_PROGRESS_TOTAL:
CollectParameters(&m_nIp, 1);
CStats::TotalProgressInGame = ScriptParams[0];
+ if (CGame::germanGame)
+ CStats::TotalProgressInGame -= 2;
return 0;
case COMMAND_REGISTER_JUMP_DISTANCE:
CollectParameters(&m_nIp, 1);
@@ -2298,6 +2335,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
strncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT);
++CStats::MissionsPassed;
CStats::CheckPointReachedSuccessfully();
+ CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();
+ CGameLogic::RemoveShortCutDropOffPointForMission();
return 0;
}
case COMMAND_SET_CHAR_RUNNING:
@@ -2311,6 +2350,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
case COMMAND_REMOVE_ALL_SCRIPT_FIRES:
gFireManager.RemoveAllScriptFires();
return 0;
+ /*
case COMMAND_IS_FIRST_CAR_COLOUR:
{
CollectParameters(&m_nIp, 2);
@@ -2327,22 +2367,37 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
UpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]);
return 0;
}
+ */
case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:
{
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ bool result = false;
if (!pPed)
printf("HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\n");
- UpdateCompareFlag(pPed && pPed->m_lastWepDam == ScriptParams[1]);
+ else {
+ if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON)
+ result = CheckDamagedWeaponType(pPed->m_lastWepDam, ScriptParams[1]);
+ else
+ result = ScriptParams[1] == pPed->m_lastWepDam;
+ }
+ UpdateCompareFlag(result);
return 0;
}
case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ bool result = false;
if (!pVehicle)
printf("HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\n");
- UpdateCompareFlag(pVehicle && pVehicle->m_nLastWeaponDamage == ScriptParams[1]);
+ else {
+ if (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON)
+ result = CheckDamagedWeaponType(pVehicle->m_nLastWeaponDamage, ScriptParams[1]);
+ else
+ result = ScriptParams[1] == pVehicle->m_nLastWeaponDamage;
+ }
+ UpdateCompareFlag(result);
return 0;
}
case COMMAND_IS_CHAR_IN_CHARS_GROUP:
@@ -2352,7 +2407,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
CPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]);
script_assert(pPed);
script_assert(pLeader);
- UpdateCompareFlag(pPed->m_leader == pLeader);
+ UpdateCompareFlag(pPed->m_leader == pLeader && !pPed->bWaitForLeaderToComeCloser);
return 0;
}
default:
diff --git a/src/control/Script4.cpp b/src/control/Script4.cpp
index 4e798be3..ac632b15 100644
--- a/src/control/Script4.cpp
+++ b/src/control/Script4.cpp
@@ -38,8 +38,26 @@
#include "WaterLevel.h"
#include "World.h"
#include "Zones.h"
+#include "Bike.h"
#include "Wanted.h"
+#ifdef FIX_BUGS
+static bool IsSlideObjectUsedWrongByScript(const CVector& posTarget, const CVector& slideBy)
+{
+ if (posTarget == CVector(-559.476f, 784.807f, 23.279f) && slideBy == CVector(0.0f, 10.0f, 0.0f))
+ return true; // G-Spotlight bottom elevator, east side
+ if (posTarget == CVector(-559.476f, 779.64f, 23.279f) && slideBy == CVector(0.0f, 10.0f, 0.0f))
+ return true; // G-Spotlight bottom elevator, west side
+ if (posTarget == CVector(-553.563f, 790.595f, 97.917f) && slideBy == CVector(0.0f, 10.0f, 0.0f))
+ return true; // G-Spotlight top elevator, east side
+ if (posTarget == CVector(-553.563f, 785.427f, 97.917f) && slideBy == CVector(0.0f, 10.0f, 0.0f))
+ return true; // G-Spotlight top elevator, west side
+ if (posTarget == CVector(-866.689f, -572.095f, 15.573f) && slideBy == CVector(0.0f, 0.0f, 4.5f))
+ return true; // Cherry Popper garage door
+ return false;
+}
+#endif
+
int8 CRunningScript::ProcessCommands800To899(int32 command)
{
CMatrix tmp_matrix;
@@ -51,7 +69,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed;
script_assert(pPed);
script_assert(pLeader);
- UpdateCompareFlag(pPed->m_leader == pLeader);
+ UpdateCompareFlag(pPed->m_leader == pLeader && !pPed->bWaitForLeaderToComeCloser);
return 0;
}
case COMMAND_EXPLODE_CHAR_HEAD:
@@ -59,17 +77,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- if (pPed->m_nPedState == PED_DRIVING) {
- pPed->SetDead();
- if (!pPed->IsPlayer())
- pPed->FlagToDestroyWhenNextProcessed();
- }
- else if (CGame::nastyGame && pPed->IsPedInControl()) {
- pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
- }
- else {
- pPed->SetDie(ANIM_STD_KO_FRONT, 4.0f, 0.0f);
- }
+ pPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0);
return 0;
}
case COMMAND_EXPLODE_PLAYER_HEAD:
@@ -77,12 +85,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- if (CGame::nastyGame) {
- pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true);
- }
- else {
- pPed->SetDie(ANIM_STD_KO_FRONT, 4.0f, 0.0f);
- }
+ pPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0);
return 0;
}
case COMMAND_ANCHOR_BOAT:
@@ -99,12 +102,15 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 2);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_INFO);
if (zone_id < 0) {
printf("Couldn't find zone - %s\n", zone);
return 0;
}
- CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);
+ while (zone_id >= 0) {
+ CTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);
+ zone_id = CTheZones::FindNextZoneByLabelAndReturnIndex(zone, ZONE_INFO);
+ }
return 0;
}
case COMMAND_START_CAR_FIRE:
@@ -138,6 +144,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
+ if (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE)
+ continue;
+ if (!pVehicle->bUsesCollision)
+ continue;
if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)
continue;
if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
@@ -155,14 +165,15 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:
{
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
CollectParameters(&m_nIp, 1);
int handle = -1;
uint32 i = CPools::GetVehiclePool()->GetSize();
@@ -187,6 +198,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_HAS_RESPRAY_HAPPENED:
{
CollectParameters(&m_nIp, 1);
@@ -226,6 +238,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CCarAI::TellCarToRamOtherCar(pVehicle, pTarget);
return 0;
}
+ /*
case COMMAND_SET_CAR_BLOCK_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -245,6 +258,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->SetObjective(OBJECTIVE_CATCH_TRAIN);
return 0;
}
+ */
#ifdef GTA_SCRIPT_COLLECTIVE
case COMMAND_SET_COLL_OBJ_CATCH_TRAIN:
CollectParameters(&m_nIp, 1);
@@ -273,6 +287,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->bPedIsBleeding = (ScriptParams[1] != 0);
return 0;
}
+ /*
case COMMAND_SET_CAR_FUNNY_SUSPENSION:
{
CollectParameters(&m_nIp, 2);
@@ -291,6 +306,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pCar->bBigWheels = (ScriptParams[1] != 0);
return 0;
}
+ */
case COMMAND_SET_FREE_RESPRAYS:
CollectParameters(&m_nIp, 1);
CGarages::SetFreeResprays(ScriptParams[0] != 0);
@@ -311,6 +327,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->bIsVisible = (ScriptParams[1] != 0);
return 0;
}
+ /*
case COMMAND_SET_CAR_VISIBLE:
{
CollectParameters(&m_nIp, 2);
@@ -319,6 +336,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pVehicle->bIsVisible = (ScriptParams[1] != 0);
return 0;
}
+ */
case COMMAND_IS_AREA_OCCUPIED:
{
CollectParameters(&m_nIp, 11);
@@ -346,6 +364,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
UpdateCompareFlag(total > 0);
return 0;
}
+ /*
case COMMAND_START_DRUG_RUN:
CPlane::CreateIncomingCesna();
return 0;
@@ -359,6 +378,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
gFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f);
return 0;
+ */
case COMMAND_DISPLAY_TEXT:
{
CollectParameters(&m_nIp, 2);
@@ -405,18 +425,21 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0];
return 0;
}
+ /*
case COMMAND_SET_TEXT_CENTRE_SIZE:
{
CollectParameters(&m_nIp, 1);
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0];
return 0;
}
+ */
case COMMAND_SET_TEXT_BACKGROUND:
{
CollectParameters(&m_nIp, 1);
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0);
return 0;
}
+ /*
case COMMAND_SET_TEXT_BACKGROUND_COLOUR:
{
CollectParameters(&m_nIp, 4);
@@ -430,12 +453,14 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0);
return 0;
}
+ */
case COMMAND_SET_TEXT_PROPORTIONAL:
{
CollectParameters(&m_nIp, 1);
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0);
return 0;
}
+ /*
case COMMAND_SET_TEXT_FONT:
{
CollectParameters(&m_nIp, 1);
@@ -453,6 +478,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
case COMMAND_SUBURBAN_PASSED:
CStats::SuburbanPassed = true;
return 0;
+ */
case COMMAND_ROTATE_OBJECT:
{
CollectParameters(&m_nIp, 4);
@@ -514,10 +540,14 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
script_assert(pObject);
CVector pos = pObject->GetPosition();
CVector posTarget = *(CVector*)&ScriptParams[1];
-#ifdef FIX_BUGS
- CVector slideBy = *(CVector*)&ScriptParams[4] * CTimer::GetTimeStepFix();
-#else
CVector slideBy = *(CVector*)&ScriptParams[4];
+#ifdef FIX_BUGS
+ // the check is a hack for original script, where some objects are moved
+ // via SLIDE_OBJECT instead of SET_OBJECT_POSITION
+ // assuming the slide will take exactly one frame, which is true
+ // only without accounting time step (which is a bug)
+ if (!IsSlideObjectUsedWrongByScript(posTarget, slideBy))
+ slideBy *= CTimer::GetTimeStepFix();
#endif
if (posTarget == pos) { // using direct comparasion here is fine
UpdateCompareFlag(true);
@@ -570,28 +600,16 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
if (pPed && pPed->CharCreatedBy == MISSION_CHAR){
CWorld::RemoveReferencesToDeletedObject(pPed);
- if (pPed->bInVehicle){
- if (pPed->m_pMyVehicle){
- if (pPed == pPed->m_pMyVehicle->pDriver){
- pPed->m_pMyVehicle->RemoveDriver();
- pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())
- pPed->m_pMyVehicle->ChangeLawEnforcerState(0);
- }else{
- pPed->m_pMyVehicle->RemovePassenger(pPed);
- }
- }
- delete pPed;
- --CPopulation::ms_nTotalMissionPeds;
- }else{
+ if (pPed->bInVehicle && pPed->m_pMyVehicle)
+ CTheScripts::RemoveThisPed(pPed);
+ else{
pPed->CharCreatedBy = RANDOM_CHAR;
pPed->bRespondsToThreats = true;
pPed->bScriptObjectiveCompleted = false;
pPed->ClearLeader();
--CPopulation::ms_nTotalMissionPeds;
pPed->bFadeOut = true;
+ CWorld::RemoveReferencesToDeletedObject(pPed);
}
}
if (m_bIsMissionScript)
@@ -606,9 +624,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->bKindaStayInSamePlace = (ScriptParams[1] != 0);
return 0;
}
+ /*
case COMMAND_IS_NASTY_GAME:
UpdateCompareFlag(CGame::nastyGame);
return 0;
+ */
case COMMAND_UNDRESS_CHAR:
{
CollectParameters(&m_nIp, 1);
@@ -618,13 +638,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, name);
for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
name[i] = tolower(name[i]);
- int mi = pPed->GetModelIndex();
- pPed->DeleteRwObject();
- if (pPed->IsPlayer())
- mi = 0;
- CStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CWorld::Remove(pPed);
+ pPed->Undress(name);
return 0;
}
case COMMAND_DRESS_CHAR:
@@ -632,12 +647,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- int mi = pPed->GetModelIndex();
- pPed->m_modelIndex = -1;
- pPed->SetModelIndex(mi);
- CWorld::Add(pPed);
+ pPed->Dress();
return 0;
}
+ /*
case COMMAND_START_CHASE_SCENE:
CollectParameters(&m_nIp, 1);
CTimer::Suspend();
@@ -678,10 +691,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
return 0;
@@ -709,6 +722,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:
{
CollectParameters(&m_nIp, 5);
@@ -735,7 +749,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPlayerPed);
- pPlayerPed->m_fArmour = Clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);
+ pPlayerPed->m_fArmour = Clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, CWorld::Players[ScriptParams[0]].m_nMaxArmour);
return 0;
}
case COMMAND_ADD_ARMOUR_TO_CHAR:
@@ -761,7 +775,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
{
CollectParameters(&m_nIp, 4);
- CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
CVector pos = *(CVector*)&ScriptParams[1];
if (pos.z <= MAP_Z_LOW_LIMIT)
@@ -774,26 +788,58 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
pPed->m_pMyVehicle->bEngineOn = false;
pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);
+ pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);
}else{
pPed->m_pMyVehicle->RemovePassenger(pPed);
}
- pPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);
- pPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);
+ if (pPed->m_vehDoor) {
+ if (pPed->GetPedState() == PED_EXIT_CAR || pPed->GetPedState() == PED_DRAG_FROM_CAR) {
+ uint8 flags = 0;
+ if (pPed->m_pMyVehicle->IsBike()) {
+ if (pPed->m_vehDoor == CAR_DOOR_LF ||
+ pPed->m_vehDoor == CAR_DOOR_RF ||
+ pPed->m_vehDoor == CAR_WINDSCREEN)
+ flags = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;
+ else if (pPed->m_vehDoor == CAR_DOOR_LR ||
+ pPed->m_vehDoor == CAR_DOOR_RR)
+ flags = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;
+ }
+ else {
+ switch (pPed->m_vehDoor) {
+ case CAR_DOOR_LF:
+ flags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_LF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;
+ break;
+ case CAR_DOOR_LR:
+ flags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_RF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;
+ break;
+ case CAR_DOOR_RF:
+ flags = CAR_DOOR_FLAG_RF;
+ break;
+ case CAR_DOOR_RR:
+ flags = CAR_DOOR_FLAG_RR;
+ break;
+ }
+ }
+ pPed->m_pMyVehicle->m_nGettingOutFlags &= ~flags;
+ pPed->m_pMyVehicle->ProcessOpenDoor(pPed->m_vehDoor, ANIM_STD_NUM, 0.0f);
+ }
+ }
}
+ pPed->RemoveInCarAnims();
pPed->bInVehicle = false;
pPed->m_pMyVehicle = nil;
pPed->SetPedState(PED_IDLE);
pPed->m_nLastPedState = PED_NONE;
pPed->bUsesCollision = true;
pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pPed->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);
- pPed->RemoveInCarAnims();
+ pPed->ReplaceWeaponWhenExitingVehicle();
if (pPed->m_pVehicleAnim)
pPed->m_pVehicleAnim->blendDelta = -1000.0f;
pPed->m_pVehicleAnim = nil;
pPed->RestartNonPartialAnims();
pPed->SetMoveState(PEDMOVE_NONE);
- CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_STD_IDLE, 100.0f);
+ CAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_STD_IDLE, 1000.0f);
pos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel();
pPed->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, pPed);
@@ -813,7 +859,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, range, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * range;
for (int i = 0; i < total; i++) {
@@ -829,6 +875,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
}
return 0;
}
+ /*
case COMMAND_HAS_CHAR_SPOTTED_CHAR:
{
CollectParameters(&m_nIp, 2);
@@ -839,6 +886,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
UpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget));
return 0;
}
+ */
case COMMAND_SET_CHAR_OBJ_HAIL_TAXI:
{
CollectParameters(&m_nIp, 1);
@@ -856,6 +904,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
UpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible);
return 0;
}
+ /*
case COMMAND_START_KILL_FRENZY_HEADSHOT:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -886,6 +935,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);
return 0;
}
+ */
case COMMAND_WARP_PLAYER_INTO_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -917,6 +967,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);
return 0;
}
+ /*
case COMMAND_PRINT_WITH_3_NUMBERS_BIG:
{
wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
@@ -945,6 +996,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);
return 0;
}
+ */
case COMMAND_SET_CHAR_WAIT_STATE:
{
CollectParameters(&m_nIp, 3);
@@ -956,6 +1008,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
case COMMAND_SET_CAMERA_BEHIND_PLAYER:
TheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();
return 0;
+ /*
case COMMAND_SET_MOTION_BLUR:
CollectParameters(&m_nIp, 1);
TheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]);
@@ -968,6 +1021,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string);
return 0;
}
+ */
case COMMAND_CREATE_RANDOM_CHAR:
{
CollectParameters(&m_nIp, 3);
@@ -990,6 +1044,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ped->CharCreatedBy = MISSION_CHAR;
ped->bRespondsToThreats = false;
ped->bAllowMedicsToReviveMe = false;
+ ped->bIsPlayerFriend = false;
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
@@ -997,6 +1052,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -1015,6 +1072,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
pPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR);
return 0;
}
+ /*
case COMMAND_SET_2_REPEATED_PHONE_MESSAGES:
{
CollectParameters(&m_nIp, 1);
@@ -1069,6 +1127,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil);
return 0;
}
+ */
case COMMAND_IS_SNIPER_BULLET_IN_AREA:
{
CollectParameters(&m_nIp, 6);
@@ -1093,9 +1152,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
UpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ));
return 0;
}
+ /*
case COMMAND_GIVE_PLAYER_DETONATOR:
CGarages::GivePlayerDetonator();
return 0;
+ */
#ifdef GTA_SCRIPT_COLLECTIVE
case COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:
CollectParameters(&m_nIp, 1);
@@ -1150,6 +1211,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
return 0;
}
//case COMMAND_PRINT_STRING_IN_STRING_SOON:
+ /*
case COMMAND_SET_5_REPEATED_PHONE_MESSAGES:
{
CollectParameters(&m_nIp, 1);
@@ -1196,6 +1258,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
gPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6);
return 0;
}
+ */
case COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY:
{
CollectParameters(&m_nIp, 6);
@@ -1226,16 +1289,24 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
return 0;
}
case COMMAND_LOAD_ALL_MODELS_NOW:
+#ifdef FIX_BUGS
+ CTimer::Suspend();
+#else
CTimer::Stop();
+#endif
CStreaming::LoadAllRequestedModels(false);
+#ifdef FIX_BUGS
+ CTimer::Resume();
+#else
CTimer::Update();
+#endif
return 0;
case COMMAND_ADD_TO_OBJECT_VELOCITY:
{
CollectParameters(&m_nIp, 4);
CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
script_assert(pObject);
- pObject->SetMoveSpeed(pObject->GetMoveSpeed() + METERS_PER_SECOND_TO_GAME_SPEED * *(CVector*)&ScriptParams[1]);
+ pObject->AddToMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);
return 0;
}
case COMMAND_DRAW_SPRITE:
@@ -1289,9 +1360,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
}
case COMMAND_REMOVE_TEXTURE_DICTIONARY:
{
- for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)
- CTheScripts::ScriptSprites[i].Delete();
- CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script"));
+ CTheScripts::RemoveScriptTextureDictionary();
return 0;
}
case COMMAND_SET_OBJECT_DYNAMIC:
@@ -1313,6 +1382,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
}
return 0;
}
+ /*
case COMMAND_SET_CHAR_ANIM_SPEED:
{
CollectParameters(&m_nIp, 2);
@@ -1323,6 +1393,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
pAssoc->speed = *(float*)&ScriptParams[1];
return 0;
}
+ */
case COMMAND_PLAY_MISSION_PASSED_TUNE:
{
CollectParameters(&m_nIp, 1);
@@ -1351,6 +1422,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
pVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0;
return 0;
}
+ /*
case COMMAND_SWITCH_PED_ROADS_ON_ANGLED:
{
CollectParameters(&m_nIp, 7);
@@ -1373,14 +1445,20 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
ThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],
*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0);
return 0;
+ */
case COMMAND_SET_CAR_WATERTIGHT:
{
CollectParameters(&m_nIp, 2);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- script_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
- CAutomobile* pCar = (CAutomobile*)pVehicle;
- pCar->bWaterTight = ScriptParams[1] != 0;
+ if (pVehicle->IsBike()) {
+ CBike* pBike = (CBike*)pVehicle;
+ pBike->bWaterTight = ScriptParams[1] != 0;
+ }
+ else if (pVehicle->IsCar()) {
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ pCar->bWaterTight = ScriptParams[1] != 0;
+ }
return 0;
}
case COMMAND_ADD_MOVING_PARTICLE_EFFECT:
@@ -1424,6 +1502,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
pVehicle->SetHeading(heading);
return 0;
}
+ /*
case COMMAND_IS_CRANE_LIFTING_CAR:
{
CollectParameters(&m_nIp, 3);
@@ -1431,6 +1510,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
UpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle));
return 0;
}
+ */
case COMMAND_DRAW_SPHERE:
{
CollectParameters(&m_nIp, 4);
@@ -1467,6 +1547,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
strncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT);
return 0;
}
+ /*
case COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL:
{
CollectParameters(&m_nIp, 3);
@@ -1477,6 +1558,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
*(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates();
StoreParameters(&m_nIp, 3);
return 0;
+ */
case COMMAND_SAVE_INT_TO_DEBUG_FILE:
// TODO: implement something here
CollectParameters(&m_nIp, 1);
@@ -1504,7 +1586,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
return 0;
case COMMAND_SWITCH_RUBBISH:
CollectParameters(&m_nIp, 1);
- CRubbish::SetVisibility(ScriptParams[0] != 0);;
+ CRubbish::SetVisibility(ScriptParams[0] != 0);
return 0;
case COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA:
{
@@ -1543,6 +1625,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0]));
return 0;
+ /*
case COMMAND_START_CATALINA_HELI:
CHeli::StartCatalinaFlyBy();
return 0;
@@ -1555,6 +1638,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN:
UpdateCompareFlag(CHeli::HasCatalinaBeenShotDown());
return 0;
+ */
case COMMAND_SWAP_NEAREST_BUILDING_MODEL:
{
CollectParameters(&m_nIp, 6);
@@ -1570,7 +1654,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, radius, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * radius;
for (int i = 0; i < total; i++) {
@@ -1601,6 +1685,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
pPed->ClearWeapons();
return 0;
}
+ /*
case COMMAND_GRAB_CATALINA_HELI:
{
CHeli* pHeli = CHeli::FindPointerToCatalinasHeli();
@@ -1608,6 +1693,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_CLEAR_AREA_OF_CARS:
{
CollectParameters(&m_nIp, 6);
@@ -1652,9 +1738,11 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
CollectParameters(&m_nIp, 1);
CTheScripts::RemoveScriptSphere(ScriptParams[0]);
return 0;
+ /*
case COMMAND_CATALINA_HELI_FLY_AWAY:
CHeli::MakeCatalinaHeliFlyAway();
return 0;
+ */
case COMMAND_SET_EVERYONE_IGNORE_PLAYER:
{
CollectParameters(&m_nIp, 2);
@@ -1689,18 +1777,21 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_IS_PHONE_DISPLAYING_MESSAGE:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0]));
return 0;
+ */
case COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:
{
script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 1);
wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CUserDisplay::OnscnTimer.AddClock(var, onscreen_str);
+ CUserDisplay::OnscnTimer.AddClock(var, onscreen_str, ScriptParams[0] != 0);
return 0;
}
case COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:
@@ -1711,7 +1802,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str);
+ CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, 0);
return 0;
}
case COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK:
@@ -1721,30 +1812,28 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
return 0;
int attempts;
int model = -1;
- int index = CGeneral::GetRandomNumberInRange(0, 50);
- for (attempts = 0; attempts < 50; attempts++) {
+ int index = CGeneral::GetRandomNumberInRange(0, MAXVEHICLESLOADED);
+ for (attempts = 0; attempts < MAXVEHICLESLOADED; attempts++) {
if (model != -1)
break;
model = CStreaming::ms_vehiclesLoaded[index];
if (model == -1)
continue;
- // desperatly want to believe this was inlined :|
- CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model);
- script_assert(pInfo->GetModelType() == MITYPE_VEHICLE);
- CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo;
- if (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR) {
+ if (CModelInfo::IsCarModel(model) || CModelInfo::IsBikeModel(model)) {
switch (model) {
case MI_LANDSTAL:
case MI_LINERUN:
+ case MI_RIO:
case MI_FIRETRUCK:
case MI_TRASH:
case MI_STRETCH:
+ case MI_VOODOO:
case MI_MULE:
case MI_AMBULAN:
case MI_FBICAR:
case MI_MRWHOOP:
case MI_BFINJECT:
- case MI_CORPSE:
+ case MI_HUNTER:
case MI_POLICE:
case MI_ENFORCER:
case MI_SECURICA:
@@ -1752,56 +1841,95 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_BUS:
case MI_RHINO:
case MI_BARRACKS:
- case MI_TRAIN:
+ case MI_CUBAN:
case MI_CHOPPER:
- case MI_DODO:
+ case MI_ANGEL:
case MI_COACH:
case MI_RCBANDIT:
- case MI_BELLYUP:
- case MI_MRWONGS:
- case MI_MAFIA:
- case MI_YARDIE:
- case MI_YAKUZA:
- case MI_DIABLOS:
- case MI_COLUMB:
- case MI_HOODS:
+ case MI_ROMERO:
+ case MI_PACKER:
+ case MI_SENTXS:
+ case MI_SQUALO:
+ case MI_SEASPAR:
+ case MI_PIZZABOY:
+ case MI_GANGBUR:
case MI_AIRTRAIN:
case MI_DEADDODO:
case MI_SPEEDER:
case MI_REEFER:
- case MI_PANLANT:
+ case MI_TROPIC:
case MI_FLATBED:
case MI_YANKEE:
- case MI_ESCAPE:
- case MI_BORGNINE:
- case MI_TOYZ:
- case MI_GHOST:
- case MI_MIAMI_RCBARON:
- case MI_MIAMI_RCRAIDER:
+ case MI_CADDY:
+ case MI_ZEBRA:
+ case MI_TOPFUN:
+ case MI_SKIMMER:
+ case MI_RCBARON:
+ case MI_RCRAIDER:
+ case MI_SPARROW:
+ case MI_PATRIOT:
+ case MI_LOVEFIST:
+ case MI_COASTG:
+ case MI_DINGHY:
+ case MI_HERMES:
+ case MI_SABRETUR:
+ case MI_PHEONIX:
+ case MI_WALTON:
+ case MI_COMET:
+ case MI_DELUXO:
+ case MI_BURRITO:
+ case MI_SPAND:
+ case MI_MARQUIS:
+ case MI_BAGGAGE:
+ case MI_KAUFMAN:
+ case MI_MAVERICK:
+ case MI_VCNMAV:
+ case MI_RANCHER:
+ case MI_FBIRANCH:
+ case MI_JETMAX:
+ case MI_HOTRING:
+ case MI_SANDKING:
+ case MI_BLISTAC:
+ case MI_POLMAV:
+ case MI_BOXVILLE:
+ case MI_BENSON:
+ case MI_MESA:
+ case MI_RCGOBLIN:
+ case MI_HOTRINA:
+ case MI_HOTRINB:
+ case MI_BLOODRA:
+ case MI_BLOODRB:
+ case MI_VICECHEE:
model = -1;
break;
case MI_IDAHO:
case MI_STINGER:
case MI_PEREN:
case MI_SENTINEL:
- case MI_PATRIOT:
case MI_MANANA:
case MI_INFERNUS:
- case MI_BLISTA:
case MI_PONY:
case MI_CHEETAH:
case MI_MOONBEAM:
case MI_ESPERANT:
case MI_TAXI:
- case MI_KURUMA:
+ case MI_WASHING:
case MI_BOBCAT:
case MI_BANSHEE:
case MI_CABBIE:
case MI_STALLION:
case MI_RUMPO:
- case 151:
- case 152:
- case 153:
+ case MI_ADMIRAL:
+ case MI_PCJ600:
+ case MI_FAGGIO:
+ case MI_FREEWAY:
+ case MI_GLENDALE:
+ case MI_OCEANIC:
+ case MI_SANCHEZ:
+ case MI_SABRE:
+ case MI_REGINA:
+ case MI_VIRGO:
+ case MI_GREENWOO:
break;
default:
printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]);
@@ -1817,7 +1945,11 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (model == -1)
return 0;
CVehicle* car;
- if (!CModelInfo::IsBikeModel(model))
+ if (CModelInfo::IsBikeModel(model)) {
+ car = new CBike(model, RANDOM_VEHICLE);
+ ((CBike*)(car))->bIsStanding = true;
+ }
+ else
car = new CAutomobile(model, RANDOM_VEHICLE);
CVector pos = *(CVector*)&ScriptParams[0];
pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();
@@ -1838,10 +1970,12 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
CWorld::Add(car);
return 0;
}
+ /*
case COMMAND_IS_COLLISION_IN_MEMORY:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]);
return 0;
+ */
case COMMAND_SET_WANTED_MULTIPLIER:
CollectParameters(&m_nIp, 1);
FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0];
@@ -1849,6 +1983,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER:
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
return 0;
+ /*
case COMMAND_IS_CAR_VISIBLY_DAMAGED:
{
CollectParameters(&m_nIp, 1);
@@ -1857,6 +1992,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
UpdateCompareFlag(pVehicle->bIsDamaged);
return 0;
}
+ */
case COMMAND_DOES_OBJECT_EXIST:
CollectParameters(&m_nIp, 1);
UpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0]));
@@ -1865,9 +2001,17 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
{
CollectParameters(&m_nIp, 3);
CVector pos = *(CVector*)&ScriptParams[0];
+#ifdef FIX_BUGS
+ CTimer::Suspend();
+#else
CTimer::Stop();
+#endif
CStreaming::LoadScene(pos);
+#ifdef FIX_BUGS
+ CTimer::Suspend();
+#else
CTimer::Update();
+#endif
return 0;
}
case COMMAND_ADD_STUCK_CAR_CHECK:
@@ -1889,21 +2033,31 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
UpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0]));
return 0;
case COMMAND_LOAD_MISSION_AUDIO:
+ {
+ CollectParameters(&m_nIp, 1);
strncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
str[i] = tolower(str[i]);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- DMAudio.PreloadMissionAudio(str);
+ DMAudio.PreloadMissionAudio(ScriptParams[0] - 1, str);
return 0;
+ }
case COMMAND_HAS_MISSION_AUDIO_LOADED:
- UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus() == 1);
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus(ScriptParams[0] - 1) == 1);
return 0;
+ }
case COMMAND_PLAY_MISSION_AUDIO:
- DMAudio.PlayLoadedMissionAudio();
+ CollectParameters(&m_nIp, 1);
+ DMAudio.PlayLoadedMissionAudio(ScriptParams[0] - 1);
return 0;
case COMMAND_HAS_MISSION_AUDIO_FINISHED:
- UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished());
+ {
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished(ScriptParams[0] - 1));
return 0;
+ }
case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:
{
CollectParameters(&m_nIp, 3);
@@ -1911,7 +2065,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
- *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition();
+ *(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(node);
*(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node);
StoreParameters(&m_nIp, 4);
return 0;
@@ -1936,21 +2090,27 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
}
case COMMAND_SET_MISSION_AUDIO_POSITION:
{
- CollectParameters(&m_nIp, 3);
- CVector pos = *(CVector*)&ScriptParams[0];
- DMAudio.SetMissionAudioLocation(pos.x, pos.y, pos.z);
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[1];
+ DMAudio.SetMissionAudioLocation(ScriptParams[0] - 1, pos.x, pos.y, pos.z);
return 0;
}
case COMMAND_ACTIVATE_SAVE_MENU:
- FrontEndMenuManager.m_bSaveMenuActive = true;
+ {
+ CStats::SafeHouseVisits++;
+ FrontEndMenuManager.m_bActivateSaveMenu = true;
+ FindPlayerPed()->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ FindPlayerPed()->SetTurnSpeed(0.0f, 0.0f, 0.0f);
return 0;
+ }
case COMMAND_HAS_SAVE_GAME_FINISHED:
- UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive);
+ UpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive && !FrontEndMenuManager.m_bActivateSaveMenu);
return 0;
case COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE:
CollectParameters(&m_nIp, 1);
CGarages::SetLeaveCameraForThisGarage(ScriptParams[0]);
return 0;
+ /*
case COMMAND_ADD_BLIP_FOR_PICKUP_OLD:
{
CollectParameters(&m_nIp, 3);
@@ -1960,6 +2120,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_ADD_BLIP_FOR_PICKUP:
{
CollectParameters(&m_nIp, 1);
@@ -1971,6 +2132,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP:
{
CollectParameters(&m_nIp, 2);
@@ -1982,6 +2144,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_SET_PED_DENSITY_MULTIPLIER:
CollectParameters(&m_nIp, 1);
CPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0];
@@ -1990,18 +2153,25 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
CollectParameters(&m_nIp, 1);
CPopulation::m_AllRandomPedsThisType = ScriptParams[0];
return 0;
+ /*
case COMMAND_SET_TEXT_DRAW_BEFORE_FADE:
CollectParameters(&m_nIp, 1);
CTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0;
return 0;
+ */
case COMMAND_GET_COLLECTABLE1S_COLLECTED:
ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;
StoreParameters(&m_nIp, 1);
return 0;
- case COMMAND_REGISTER_EL_BURRO_TIME:
+ case COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR:
+ {
CollectParameters(&m_nIp, 1);
- CStats::RegisterElBurroTime(ScriptParams[0]);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle);
return 0;
+ }
case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
CollectParameters(&m_nIp, 1);
CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;
@@ -2015,8 +2185,8 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (CCamera::m_bUseMouse3rdPerson && (
strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "HELP15") == 0 ||
strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2A") == 0 ||
- strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_3A") == 0 ||
- strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_4A") == 0)) {
+ strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2C") == 0 ||
+ strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "GUN_2D") == 0)) {
m_nIp += KEY_LENGTH_IN_SCRIPT;
return 0;
}
diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp
index 76aa2442..e9f0967e 100644
--- a/src/control/Script5.cpp
+++ b/src/control/Script5.cpp
@@ -17,6 +17,7 @@
#include "SpecialFX.h"
#include "World.h"
#include "main.h"
+#include "SaveBuf.h"
void CRunningScript::UpdateCompareFlag(bool flag)
{
@@ -331,7 +332,7 @@ void CRunningScript::LocateCharCommand(int32 command, uint32* pIp)
CollectParameters(pIp, b3D ? 8 : 6);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ CVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
switch (command) {
case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:
case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:
@@ -732,6 +733,64 @@ void CRunningScript::LocateCarCommand(int32 command, uint32* pIp)
}
}
+void CRunningScript::LocateObjectCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float X, Y, Z, dX, dY, dZ;
+ switch (command) {
+ case COMMAND_LOCATE_OBJECT_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVector pos = pObject->GetPosition();
+ X = *(float*)&ScriptParams[1];
+ Y = *(float*)&ScriptParams[2];
+ if (b3D) {
+ Z = *(float*)&ScriptParams[3];
+ dX = *(float*)&ScriptParams[4];
+ dY = *(float*)&ScriptParams[5];
+ dZ = *(float*)&ScriptParams[6];
+ debug = ScriptParams[7];
+ }
+ else {
+ dX = *(float*)&ScriptParams[3];
+ dY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y &&
+ Z - dZ <= pos.z &&
+ Z + dZ >= pos.z;
+ }
+ else {
+ in_area = X - dX <= pos.x &&
+ X + dX >= pos.x &&
+ Y - dY <= pos.y &&
+ Y + dY >= pos.y;
+ }
+ result = in_area;
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);
+ else
+ CTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);
+ }
+}
+
void CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp)
{
bool b3D, result, debug;
@@ -1033,7 +1092,7 @@ void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp)
CollectParameters(pIp, b3D ? 8 : 6);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
+ CVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
switch (command) {
case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:
case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:
@@ -1229,6 +1288,88 @@ void CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp)
}
}
+void CRunningScript::ObjectInAreaCheckCommand(int32 command, uint32* pIp)
+{
+ bool b3D, result, debug;
+ float infX, infY, infZ, supX, supY, supZ;
+ switch (command) {
+ case COMMAND_IS_OBJECT_IN_AREA_3D:
+ b3D = true;
+ break;
+ default:
+ b3D = false;
+ break;
+ }
+ CollectParameters(pIp, b3D ? 8 : 6);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVector pos = pObject->GetPosition();
+ infX = *(float*)&ScriptParams[1];
+ infY = *(float*)&ScriptParams[2];
+ if (b3D) {
+ infZ = *(float*)&ScriptParams[3];
+ supX = *(float*)&ScriptParams[4];
+ supY = *(float*)&ScriptParams[5];
+ supZ = *(float*)&ScriptParams[6];
+ if (infZ > supZ) {
+ infZ = *(float*)&ScriptParams[6];
+ supZ = *(float*)&ScriptParams[3];
+ }
+ debug = ScriptParams[7];
+ }
+ else {
+ supX = *(float*)&ScriptParams[3];
+ supY = *(float*)&ScriptParams[4];
+ debug = ScriptParams[5];
+ }
+ if (infX > supX) {
+ float tmp = infX;
+ infX = supX;
+ supX = tmp;
+ }
+ if (infY > supY) {
+ float tmp = infY;
+ infY = supY;
+ supY = tmp;
+ }
+ result = false;
+ bool in_area;
+ if (b3D) {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y &&
+ infZ <= pos.z &&
+ supZ >= pos.z;
+ }
+ else {
+ in_area = infX <= pos.x &&
+ supX >= pos.x &&
+ infY <= pos.y &&
+ supY >= pos.y;
+ }
+ if (in_area) {
+ switch (command) {
+ case COMMAND_IS_OBJECT_IN_AREA_2D:
+ case COMMAND_IS_OBJECT_IN_AREA_3D:
+ result = true;
+ break;
+ default:
+ script_assert(false);
+ break;
+ }
+ }
+ UpdateCompareFlag(result);
+ if (debug)
+ CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);
+ if (CTheScripts::DbgFlag) {
+ if (b3D)
+ CTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);
+ else
+ CTheScripts::DrawDebugSquare(infX, infY, supX, supY);
+ }
+}
+
void CRunningScript::DoDeatharrestCheck()
{
if (!m_bDeatharrestEnabled)
@@ -1236,11 +1377,13 @@ void CRunningScript::DoDeatharrestCheck()
if (!CTheScripts::IsPlayerOnAMission())
return;
CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
- if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown())
+ if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest())
return;
#ifdef MISSION_REPLAY
- if (AllowMissionReplay != MISSION_RETRY_STAGE_NORMAL)
+ if (AllowMissionReplay != MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART && AllowMissionReplay != MISSION_RETRY_STAGE_NORMAL)
return;
+ if (AllowMissionReplay == MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART)
+ AllowMissionReplay = MISSION_RETRY_STAGE_NORMAL;
if (CanAllowMissionReplay())
AllowMissionReplay = MISSION_RETRY_STAGE_WAIT_FOR_SCRIPT_TO_TERMINATE;
#endif
@@ -1248,29 +1391,7 @@ void CRunningScript::DoDeatharrestCheck()
while (m_nStackPointer > 1)
--m_nStackPointer;
m_nIp = m_anStack[--m_nStackPointer];
- int16 messageId;
- if (pPlayer->IsRestartingAfterDeath())
- messageId = 0;
- else if (pPlayer->IsRestartingAfterArrest())
- messageId = 5;
- else
- messageId = 10;
- messageId += CGeneral::GetRandomNumberInRange(0, 5);
- bool found = false;
- for (int16 contact = 0; !found && contact < MAX_NUM_CONTACTS; contact++) {
- int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
- if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
- messageId += CTheScripts::BaseBriefIdForContact[contact];
- found = true;
- }
- }
- if (!found)
- messageId = 8001;
- char tmp[16];
- sprintf(tmp, "%d", messageId);
CMessages::ClearSmallMessagesOnly();
- wchar* text = TheText.Get(tmp);
- // ...and do nothing about it
*(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;
m_bDeatharrestExecuted = true;
m_nWakeTime = 0;
@@ -1787,6 +1908,76 @@ void CRunningScript::CollectiveInAreaCheckCommand(int32 command, uint32* pIp)
}
#endif
+bool CRunningScript::CheckDamagedWeaponType(int32 actual, int32 type)
+{
+ if (actual == -1)
+ return false;
+
+ if (type == WEAPONTYPE_ANYMELEE) {
+ if (actual <= WEAPONTYPE_CHAINSAW)
+ return true;
+ if (actual >= WEAPONTYPE_GRENADE && actual <= WEAPONTYPE_UNIDENTIFIED)
+ return false;
+ return false;
+ }
+
+ if (type != WEAPONTYPE_ANYWEAPON)
+ return false;
+
+ switch (actual) {
+ case WEAPONTYPE_UNARMED:
+ case WEAPONTYPE_BRASSKNUCKLE:
+ case WEAPONTYPE_SCREWDRIVER:
+ case WEAPONTYPE_GOLFCLUB:
+ case WEAPONTYPE_NIGHTSTICK:
+ case WEAPONTYPE_KNIFE:
+ case WEAPONTYPE_BASEBALLBAT:
+ case WEAPONTYPE_HAMMER:
+ case WEAPONTYPE_CLEAVER:
+ case WEAPONTYPE_MACHETE:
+ case WEAPONTYPE_KATANA:
+ case WEAPONTYPE_CHAINSAW:
+ case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
+ case WEAPONTYPE_TEARGAS:
+ case WEAPONTYPE_MOLOTOV:
+ case WEAPONTYPE_ROCKET:
+ case WEAPONTYPE_COLT45:
+ case WEAPONTYPE_PYTHON:
+ case WEAPONTYPE_SHOTGUN:
+ case WEAPONTYPE_SPAS12_SHOTGUN:
+ case WEAPONTYPE_STUBBY_SHOTGUN:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
+ case WEAPONTYPE_M4:
+ case WEAPONTYPE_RUGER:
+ case WEAPONTYPE_SNIPERRIFLE:
+ case WEAPONTYPE_LASERSCOPE:
+ case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_FLAMETHROWER:
+ case WEAPONTYPE_M60:
+ case WEAPONTYPE_MINIGUN:
+ case WEAPONTYPE_DETONATOR:
+ case WEAPONTYPE_HELICANNON:
+ case WEAPONTYPE_CAMERA:
+ case WEAPONTYPE_EXPLOSION:
+ case WEAPONTYPE_UZI_DRIVEBY:
+ return true;
+ case WEAPONTYPE_HEALTH:
+ case WEAPONTYPE_ARMOUR:
+ case WEAPONTYPE_RAMMEDBYCAR:
+ case WEAPONTYPE_RUNOVERBYCAR:
+ case WEAPONTYPE_DROWNING:
+ case WEAPONTYPE_FALL:
+ case WEAPONTYPE_UNIDENTIFIED:
+ return false;
+ }
+
+ return false;
+}
+
void CTheScripts::PrintListSizes()
{
int active = 0;
@@ -1909,8 +2100,8 @@ void CTheScripts::RenderTheScriptDebugLines()
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0);
}
-#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\
- sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)
+#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) +\
+ 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)
void CTheScripts::SaveAllScripts(uint8* buf, uint32* size)
{
@@ -1930,13 +2121,7 @@ INITSAVEBUF
uint32 script_data_size = SCRIPT_DATA_SIZE;
WriteSaveBuf(buf, script_data_size);
WriteSaveBuf(buf, OnAMissionFlag);
- for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) {
- WriteSaveBuf(buf, OnAMissionForContactFlag[i]);
- WriteSaveBuf(buf, BaseBriefIdForContact[i]);
- }
- for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++)
- WriteSaveBuf(buf, CollectiveArray[i]);
- WriteSaveBuf(buf, NextFreeCollectiveIndex);
+ WriteSaveBuf(buf, LastMissionPassedTime);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding;
uint32 type, handle;
@@ -1986,12 +2171,12 @@ INITSAVEBUF
WriteSaveBuf(buf, handle);
}
WriteSaveBuf(buf, bUsingAMultiScriptFile);
- WriteSaveBuf(buf, (uint8)0);
+ WriteSaveBuf(buf, bPlayerHasMetDebbieHarry);
WriteSaveBuf(buf, (uint16)0);
WriteSaveBuf(buf, MainScriptSize);
WriteSaveBuf(buf, LargestMissionScriptSize);
WriteSaveBuf(buf, NumberOfMissionScripts);
- WriteSaveBuf(buf, (uint16)0);
+ WriteSaveBuf(buf, NumberOfExclusiveMissionScripts);
WriteSaveBuf(buf, runningScripts);
for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())
pScript->Save(buf);
@@ -2012,13 +2197,7 @@ INITSAVEBUF
ReadSaveBuf(&tmp, buf);
script_assert(tmp == SCRIPT_DATA_SIZE);
ReadSaveBuf(&OnAMissionFlag, buf);
- for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) {
- ReadSaveBuf(&OnAMissionForContactFlag[i], buf);
- ReadSaveBuf(&BaseBriefIdForContact[i], buf);
- }
- for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++)
- ReadSaveBuf(&CollectiveArray[i], buf);
- ReadSaveBuf(&NextFreeCollectiveIndex, buf);
+ ReadSaveBuf(&LastMissionPassedTime, buf);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
ReadSaveBuf(&type, buf);
ReadSaveBuf(&handle, buf);
@@ -2068,7 +2247,8 @@ INITSAVEBUF
bool tmpBool;
ReadSaveBuf(&tmpBool, buf);
script_assert(tmpBool == bUsingAMultiScriptFile);
- SkipSaveBuf(buf, 3);
+ ReadSaveBuf(&bPlayerHasMetDebbieHarry, buf);
+ SkipSaveBuf(buf, 2);
ReadSaveBuf(&tmp, buf);
script_assert(tmp == MainScriptSize);
ReadSaveBuf(&tmp, buf);
@@ -2076,7 +2256,8 @@ INITSAVEBUF
uint16 tmp16;
ReadSaveBuf(&tmp16, buf);
script_assert(tmp16 == NumberOfMissionScripts);
- SkipSaveBuf(buf, 2);
+ ReadSaveBuf(&tmp16, buf);
+ script_assert(tmp16 == NumberOfExclusiveMissionScripts);
uint32 runningScripts;
ReadSaveBuf(&runningScripts, buf);
for (uint32 i = 0; i < runningScripts; i++)
@@ -2105,10 +2286,10 @@ void CRunningScript::Save(uint8*& buf)
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
WriteSaveBuf(buf, m_anLocalVariables[i]);
+ WriteSaveBuf(buf, m_bIsActive);
WriteSaveBuf(buf, m_bCondResult);
WriteSaveBuf(buf, m_bIsMissionScript);
WriteSaveBuf(buf, m_bSkipWakeTime);
- ZeroSaveBuf(buf, 1);
WriteSaveBuf(buf, m_nWakeTime);
WriteSaveBuf(buf, m_nAndOrState);
WriteSaveBuf(buf, m_bNotFlag);
@@ -2140,10 +2321,10 @@ void CRunningScript::Load(uint8*& buf)
#endif
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
ReadSaveBuf(&m_anLocalVariables[i], buf);
+ ReadSaveBuf(&m_bIsActive, buf);
ReadSaveBuf(&m_bCondResult, buf);
ReadSaveBuf(&m_bIsMissionScript, buf);
ReadSaveBuf(&m_bSkipWakeTime, buf);
- SkipSaveBuf(buf, 1);
ReadSaveBuf(&m_nWakeTime, buf);
ReadSaveBuf(&m_nAndOrState, buf);
ReadSaveBuf(&m_bNotFlag, buf);
@@ -2451,22 +2632,24 @@ void CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective ob
bool CTheScripts::IsPedStopped(CPed* pPed)
{
- if (pPed->bInVehicle)
+ if (pPed->InVehicle())
return IsVehicleStopped(pPed->m_pMyVehicle);
- return pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL;
+ return (pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL) &&
+ !pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f;
}
bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer)
{
CPed* pPed = pPlayer->m_pPed;
- if (pPed->bInVehicle)
+ if (pPed->InVehicle())
return IsVehicleStopped(pPed->m_pMyVehicle);
if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_RUNSTOP1) ||
RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_RUNSTOP2) ||
RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_JUMP_LAUNCH) ||
RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_JUMP_GLIDE))
return false;
- return pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL;
+ return (pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL) &&
+ !pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f;
}
bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
@@ -2474,6 +2657,30 @@ bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)
return 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;
}
+void CTheScripts::RemoveThisPed(CPed* pPed)
+{
+ if (pPed) {
+ bool bWasMissionPed = pPed->CharCreatedBy == MISSION_CHAR;
+ if (pPed->InVehicle() && pPed->m_pMyVehicle) {
+ if (pPed->m_pMyVehicle->pDriver == pPed) {
+ pPed->m_pMyVehicle->RemoveDriver();
+ pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())
+ pPed->m_pMyVehicle->ChangeLawEnforcerState(0);
+ }
+ else {
+ pPed->m_pMyVehicle->RemovePassenger(pPed);
+ }
+ }
+ CWorld::RemoveReferencesToDeletedObject(pPed);
+ delete pPed;
+ if (bWasMissionPed)
+ --CPopulation::ms_nTotalMissionPeds;
+ }
+}
+
void CTheScripts::CleanUpThisPed(CPed* pPed)
{
if (!pPed)
@@ -2483,7 +2690,7 @@ void CTheScripts::CleanUpThisPed(CPed* pPed)
pPed->CharCreatedBy = RANDOM_CHAR;
if (pPed->m_nPedType == PEDTYPE_PROSTITUTE)
pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000;
- if (pPed->bInVehicle) {
+ if (pPed->InVehicle()) {
if (pPed->m_pMyVehicle->pDriver == pPed) {
if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle);
@@ -2508,6 +2715,7 @@ void CTheScripts::CleanUpThisPed(CPed* pPed)
pPed->ClearObjective();
pPed->bRespondsToThreats = true;
pPed->bScriptObjectiveCompleted = false;
+ pPed->bKindaStayInSamePlace = false;
pPed->ClearLeader();
if (pPed->IsPedInControl())
pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7);
@@ -2538,7 +2746,7 @@ void CTheScripts::CleanUpThisObject(CObject* pObject)
if (pObject->ObjectCreatedBy != MISSION_OBJECT)
return;
pObject->ObjectCreatedBy = TEMP_OBJECT;
- pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;
+ pObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000000;
pObject->m_nRefModelIndex = -1;
pObject->bUseVehicleColours = false;
++CObject::nNoTempObjects;
@@ -2595,7 +2803,7 @@ void CTheScripts::ReadMultiScriptFileOffsetsFromScript()
MainScriptSize = Read4BytesFromScript(&ip);
LargestMissionScriptSize = Read4BytesFromScript(&ip);
NumberOfMissionScripts = Read2BytesFromScript(&ip);
- ip += 2;
+ NumberOfExclusiveMissionScripts = Read2BytesFromScript(&ip);
for (int i = 0; i < NumberOfMissionScripts; i++) {
MultiScriptArray[i] = Read4BytesFromScript(&ip);
}
diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp
index 0a2248f8..8af32f57 100644
--- a/src/control/Script6.cpp
+++ b/src/control/Script6.cpp
@@ -32,17 +32,58 @@
#include "Weather.h"
#include "Zones.h"
#include "main.h"
+#include "GameLogic.h"
+#include "Sprite.h"
+#include "CarAI.h"
+#include "Pickups.h"
+#include "Fluff.h"
-// NB: on PS2 this file did not exist; ProcessCommands1000To1099 was in Script5.cpp and ProcessCommands1100To1199 was only added on PC
-// however to avoid redundant copies of code, Script6.cpp is used with PS2 defines
+#ifdef USE_DEBUG_SCRIPT_LOADER
+extern const char* scriptfile;
+#endif
+
+bool CRunningScript::ThisIsAValidRandomCop(uint32 mi, int cop, int swat, int fbi, int army, int miami)
+{
+ switch (mi)
+ {
+ case MI_COP: if (cop) return true; break;
+ case MI_SWAT: if (swat) return true; break;
+ case MI_FBI: if (fbi) return true; break;
+ case MI_ARMY: if (army) return true; break;
+ default: if (mi >= MI_VICE1 && mi <= MI_VICE8 && miami) return true; break;
+ }
+ return false;
+}
+
+bool CRunningScript::ThisIsAValidRandomPed(uint32 pedtype, int civ, int gang, int criminal)
+{
+ switch (pedtype) {
+ case PEDTYPE_CIVMALE:
+ case PEDTYPE_CIVFEMALE:
+ return civ;
+ case PEDTYPE_GANG1:
+ case PEDTYPE_GANG2:
+ case PEDTYPE_GANG3:
+ case PEDTYPE_GANG4:
+ case PEDTYPE_GANG5:
+ case PEDTYPE_GANG6:
+ case PEDTYPE_GANG7:
+ case PEDTYPE_GANG8:
+ case PEDTYPE_GANG9:
+ return gang;
+ case PEDTYPE_CRIMINAL:
+ case PEDTYPE_PROSTITUTE:
+ return criminal;
+ default:
+ return false;
+ }
+}
int8 CRunningScript::ProcessCommands1000To1099(int32 command)
{
-#if GTA_VERSION <= GTA3_PS2_160
- char tmp[48];
-#endif
switch (command) {
//case COMMAND_FLASH_RADAR_BLIP:
+ /*
case COMMAND_IS_CHAR_IN_CONTROL:
{
CollectParameters(&m_nIp, 1);
@@ -50,6 +91,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(pPed->IsPedInControl());
return 0;
}
+ */
case COMMAND_SET_GENERATE_CARS_AROUND_CAMERA:
CollectParameters(&m_nIp, 1);
CCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0);
@@ -57,9 +99,11 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
case COMMAND_CLEAR_SMALL_PRINTS:
CMessages::ClearSmallMessagesOnly();
return 0;
+ /*
case COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS:
UpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane());
return 0;
+ */
case COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED:
{
CollectParameters(&m_nIp, 2);
@@ -81,10 +125,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE:
{
CollectParameters(&m_nIp, 1);
-#ifdef MISSION_REPLAY
- AllowMissionReplay = MISSION_RETRY_STAGE_NORMAL;
- SaveGameForPause(SAVE_TYPE_QUICKSAVE_FOR_MISSION_REPLAY);
-#endif
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);
pPlayerInfo->MakePlayerSafe(true);
@@ -129,6 +169,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
return 0;
}
//case COMMAND_MAKE_PLAYER_UNSAFE:
+ /*
case COMMAND_LOAD_COLLISION:
{
CollectParameters(&m_nIp, 1);
@@ -149,9 +190,10 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
return 0;
}
case COMMAND_GET_BODY_CAST_HEALTH:
- ScriptParams[0] = CObject::nBodyCastHealth;
- StoreParameters(&m_nIp, 1);
+ // ScriptParams[0] = CObject::nBodyCastHealth;
+ // StoreParameters(&m_nIp, 1);
return 0;
+ */
case COMMAND_SET_CHARS_CHATTING:
{
CollectParameters(&m_nIp, 3);
@@ -163,6 +205,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
return 0;
}
//case COMMAND_MAKE_PLAYER_SAFE:
+ /*
case COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL:
{
CollectParameters(&m_nIp, 2);
@@ -185,22 +228,34 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_nZoneLevel = LEVEL_GENERIC;
return 0;
}
- case COMMAND_REGISTER_4X4_ONE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4OneTime(ScriptParams[0]);
- return 0;
- case COMMAND_REGISTER_4X4_TWO_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4TwoTime(ScriptParams[0]);
+ */
+ case COMMAND_SET_DRUNK_INPUT_DELAY:
+ {
+ CollectParameters(&m_nIp, 2);
+ assert(ScriptParams[1] < CPad::DRUNK_STEERING_BUFFER_SIZE);
+ CPad::GetPad(ScriptParams[0])->SetDrunkInputDelay(ScriptParams[1]);
return 0;
- case COMMAND_REGISTER_4X4_THREE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4ThreeTime(ScriptParams[0]);
+ }
+ case COMMAND_SET_CHAR_MONEY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_nPedMoney = ScriptParams[1];
+ pPed->bMoneyHasBeenGivenByScript = true;
return 0;
- case COMMAND_REGISTER_4X4_MAYHEM_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4MayhemTime(ScriptParams[0]);
+ }
+ //case COMMAND_INCREASE_CHAR_MONEY:
+ case COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ CVector result = Multiply3x3(pObject->GetMatrix(), *(CVector*)&ScriptParams[1]) + pObject->GetPosition();
+ *(CVector*)&ScriptParams[0] = result;
+ StoreParameters(&m_nIp, 3);
return 0;
+ }
case COMMAND_REGISTER_LIFE_SAVED:
CStats::AnotherLifeSavedWithAmbulance();
return 0;
@@ -218,25 +273,35 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
gPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9;
return 0;
+ /*
case COMMAND_REGISTER_LONGEST_DODO_FLIGHT:
CollectParameters(&m_nIp, 1);
CStats::RegisterLongestFlightInDodo(ScriptParams[0]);
return 0;
- case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]);
+ */
+ case COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVector result = Multiply3x3(pVehicle->GetMatrix(), *(CVector*)&ScriptParams[1]) + pVehicle->GetPosition();
+ *(CVector*)&ScriptParams[0] = result;
+ StoreParameters(&m_nIp, 3);
return 0;
+ }
case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
CollectParameters(&m_nIp, 1);
CStats::SetTotalNumberKillFrenzies(ScriptParams[0]);
return 0;
case COMMAND_BLOW_UP_RC_BUGGY:
- CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy();
+ CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(true);
return 0;
+ /*
case COMMAND_REMOVE_CAR_FROM_CHASE:
CollectParameters(&m_nIp, 1);
CRecordDataForChase::RemoveCarFromChase(ScriptParams[0]);
return 0;
+ */
case COMMAND_IS_FRENCH_GAME:
UpdateCompareFlag(CGame::frenchGame);
return 0;
@@ -244,8 +309,10 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(CGame::germanGame);
return 0;
case COMMAND_CLEAR_MISSION_AUDIO:
- DMAudio.ClearMissionAudio();
+ CollectParameters(&m_nIp, 1);
+ DMAudio.ClearMissionAudio(ScriptParams[0] - 1);
return 0;
+ /*
case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST:
CollectParameters(&m_nIp, 1);
CRestart::bFadeInAfterNextArrest = !!ScriptParams[0];
@@ -258,6 +325,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 2);
CGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]);
return 0;
+ */
case COMMAND_SET_CHAR_USE_PEDNODE_SEEK:
{
CollectParameters(&m_nIp, 2);
@@ -268,6 +336,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->bUsePedNodeSeek = !!ScriptParams[1];
return 0;
}
+ /*
case COMMAND_SWITCH_VEHICLE_WEAPONS:
{
CollectParameters(&m_nIp, 2);
@@ -280,10 +349,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 2);
CWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1];
return 0;
+ */
case COMMAND_SET_FREE_HEALTH_CARE:
CollectParameters(&m_nIp, 2);
CWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1];
return 0;
+ /*
case COMMAND_IS_CAR_DOOR_CLOSED:
{
CollectParameters(&m_nIp, 2);
@@ -292,15 +363,33 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1]));
return 0;
}
+ */
case COMMAND_LOAD_AND_LAUNCH_MISSION:
return 0;
case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:
{
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ uint32 oldIp = m_nIp;
+#endif
CollectParameters(&m_nIp, 1);
+
+ if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2)
+ return 0;
#ifdef MISSION_REPLAY
missionRetryScriptIndex = ScriptParams[0];
- if (missionRetryScriptIndex == 19)
- CStats::LastMissionPassedName[0] = '\0';
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ if (!UsingMobileScript && CTheScripts::MissionSupportsMissionReplay(missionRetryScriptIndex)){
+ if (!AlreadySavedGame) {
+ m_nIp = oldIp - 2;
+ SaveGameForPause(SAVE_TYPE_QUICKSAVE_FOR_SCRIPT);
+ AlreadySavedGame = true;
+ return 0;
+ }
+ else {
+ AlreadySavedGame = false;
+ }
+ }
+#endif
#endif
CTimer::Suspend();
int offset = CTheScripts::MultiScriptArray[ScriptParams[0]];
@@ -318,6 +407,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pMissionScript->m_bIsMissionScript = true;
pMissionScript->m_bMissionFlag = true;
CTheScripts::bAlreadyRunningAMissionScript = true;
+ CGameLogic::ClearShortCut();
return 0;
}
case COMMAND_SET_OBJECT_DRAW_LAST:
@@ -333,14 +423,15 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 2);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- CWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];
- if (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])
- ScriptParams[0] = pWeaponSlot->m_nAmmoTotal;
- else
- ScriptParams[0] = 0;
+ ScriptParams[0] = 0;
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+ if (pPed->GetWeapon(i).m_eWeaponType == (eWeaponType)ScriptParams[1])
+ ScriptParams[0] = pPed->GetWeapon(i).m_nAmmoTotal;
+ }
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_GET_AMMO_IN_CHAR_WEAPON:
{
CollectParameters(&m_nIp, 2);
@@ -385,6 +476,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
}
return 0;
}
+ */
case COMMAND_SET_NEAR_CLIP:
CollectParameters(&m_nIp, 1);
TheCamera.SetNearClipScript(*(float*)&ScriptParams[0]);
@@ -393,6 +485,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 2);
DMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]);
return 0;
+ /*
case COMMAND_OVERRIDE_HOSPITAL_LEVEL:
CollectParameters(&m_nIp, 1);
CRestart::OverrideHospitalLevel = ScriptParams[0];
@@ -413,6 +506,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle));
return 0;
}
+ */
case COMMAND_SET_CAR_TRACTION:
{
CollectParameters(&m_nIp, 2);
@@ -422,7 +516,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
if (pVehicle->m_vehType == VEHICLE_TYPE_CAR)
((CAutomobile*)pVehicle)->m_fTraction = fTraction;
else
- // this is certainly not a boat, trane, heli or plane field
((CBike*)pVehicle)->m_fTraction = fTraction;
return 0;
}
@@ -442,6 +535,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_MARK_ROADS_BETWEEN_LEVELS:
{
CollectParameters(&m_nIp, 6);
@@ -490,6 +584,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
ThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);
return 0;
}
+ */
case COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS:
{
CollectParameters(&m_nIp, 2);
@@ -498,6 +593,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1];
return 0;
}
+ /*
case COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS:
{
CollectParameters(&m_nIp, 2);
@@ -510,6 +606,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 2);
UpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1]));
return 0;
+ */
case COMMAND_CLEAR_AREA_OF_CHARS:
{
CollectParameters(&m_nIp, 6);
@@ -536,7 +633,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
}
case COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS:
CollectParameters(&m_nIp, 1);
- CStats::SetTotalNumberMissions(ScriptParams[0]);
+ CStats::SetTotalNumberMissions(CGame::germanGame ? ScriptParams[0] - 2 : ScriptParams[0]);
return 0;
case COMMAND_CONVERT_METRES_TO_FEET_INT:
CollectParameters(&m_nIp, 1);
@@ -560,6 +657,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(ScriptParams[1] < pVehicle->m_nNumMaxPassengers && pVehicle->pPassengers[ScriptParams[1]] == nil);
return 0;
}
+ /*
case COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT:
{
CollectParameters(&m_nIp, 2);
@@ -571,6 +669,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL:
{
CollectParameters(&m_nIp, 2);
@@ -593,6 +692,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1],
*(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0);
return 0;
+ /*
case COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS:
{
CollectParameters(&m_nIp, 2);
@@ -625,10 +725,12 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix());
return 0;
}
+ */
case COMMAND_SET_MUSIC_DOES_FADE:
CollectParameters(&m_nIp, 1);
TheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0);
return 0;
+ /*
case COMMAND_SET_INTRO_IS_PLAYING:
CollectParameters(&m_nIp, 1);
if (ScriptParams[0]) {
@@ -643,6 +745,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CStreaming::LoadAllRequestedModels(false);
}
return 0;
+ */
case COMMAND_SET_PLAYER_HOOKER:
{
CollectParameters(&m_nIp, 2);
@@ -655,6 +758,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]);
script_assert(pHooker);
pPlayerInfo->m_pHooker = (CCivilianPed*)pHooker;
+ pPlayerInfo->m_nSexFrequency = 1000;
pPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
pPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
}
@@ -682,8 +786,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
- script_assert(pVehicle);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR && pPed->m_pMyVehicle == pVehicle);
return 0;
}
case COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR:
@@ -691,24 +794,27 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR);
return 0;
}
+ /*
case COMMAND_SET_SCRIPT_FIRE_AUDIO:
CollectParameters(&m_nIp, 2);
gFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]);
return 0;
+ */
case COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED:
- UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3);
+ UpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3 || CVehicle::bHoverCheat || CVehicle::bCheat8 || CVehicle::bCheat9);
return 0;
case COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS:
{
CollectParameters(&m_nIp, 2);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- pPed->bNoCriticalHits = (ScriptParams[0] == 0);
+ pPed->bNoCriticalHits = (ScriptParams[1] == 0);
return 0;
}
+ /*
case COMMAND_IS_PLAYER_LIFTING_A_PHONE:
{
CollectParameters(&m_nIp, 1);
@@ -717,6 +823,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
UpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL);
return 0;
}
+ */
case COMMAND_IS_CHAR_SITTING_IN_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -724,7 +831,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
script_assert(pPed);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
script_assert(pVehicle);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_pMyVehicle == pVehicle);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR && pPed->m_pMyVehicle == pVehicle);
return 0;
}
case COMMAND_IS_CHAR_SITTING_IN_ANY_CAR:
@@ -732,7 +839,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING);
+ UpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR);
return 0;
}
case COMMAND_IS_PLAYER_ON_FOOT:
@@ -753,7 +860,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
return 0;
}
-#if GTA_VERSION > GTA3_PS2_160
default:
script_assert(0);
}
@@ -764,7 +870,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
char tmp[48];
switch (command) {
-#endif
+ /*
case COMMAND_LOAD_COLLISION_WITH_SCREEN:
CollectParameters(&m_nIp, 1);
CTimer::Stop();
@@ -800,6 +906,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
CTimer::Update();
return 0;
+ */
case COMMAND_LOAD_SPLASH_SCREEN:
CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
@@ -807,6 +914,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
m_nIp += 8;
LoadSplash(tmp);
return 0;
+ /*
case COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:
{
CollectParameters(&m_nIp, 2);
@@ -828,6 +936,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pCar->bMoreResistantToDamage = ScriptParams[1];
return 0;
}
+ */
case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
{
CollectParameters(&m_nIp, 1);
@@ -839,14 +948,14 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_LOAD_END_OF_GAME_TUNE:
DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
printf("Start preload end of game audio\n");
- DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
+ DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_CUTSCENE_FINALE);
printf("End preload end of game audio\n");
return 0;
+ /*
case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA);
return 0;
-#if GTA_VERSION > GTA3_PS2_160
- // These are "beta" VC commands (with bugs)
+ */
case COMMAND_SET_OBJECT_ROTATION:
{
CollectParameters(&m_nIp, 4);
@@ -866,6 +975,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source;
StoreParameters(&m_nIp, 3);
return 0;
+ /*
case COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:
*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front;
StoreParameters(&m_nIp, 3);
@@ -879,6 +989,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
UpdateCompareFlag(pTarget && pTarget->IsPed());
return 0;
}
+ */
case COMMAND_IS_PLAYER_TARGETTING_CHAR:
{
CollectParameters(&m_nIp, 2);
@@ -887,9 +998,38 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
script_assert(pTestedPed);
CEntity* pTarget = pPed->m_pPointGunAt;
- UpdateCompareFlag(pTarget && pTarget->IsPed() && pTarget == pTestedPed);
+ bool bTargetting = pTarget && pTarget->IsPed() && pTarget == pTestedPed;
+ // PC shit
+ static int nCounter = 0;
+ nCounter = Max(0, nCounter - 1);
+ if (!pPed->GetWeapon()->IsTypeMelee() && !bTargetting) {
+ if ((pTestedPed->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) {
+ CVector vTestedPos(pTestedPed->GetPosition().x, pTestedPed->GetPosition().y, pTestedPed->GetPosition().z + 0.4);
+ CVector vScreenPos;
+ float w, h;
+ if (CSprite::CalcScreenCoors(vTestedPos, &vScreenPos, &w, &h, false)) {
+ CVector2D vCrosshairPosition(CCamera::m_f3rdPersonCHairMultX * RsGlobal.maximumWidth, CCamera::m_f3rdPersonCHairMultY * RsGlobal.maximumHeight);
+ float fScreenDistance = ((CVector2D)vScreenPos - vCrosshairPosition).Magnitude();
+ if (SCREEN_STRETCH_X(0.45f) > fScreenDistance / w) {
+ CColPoint point;
+ CEntity* entity;
+ if (!CWorld::ProcessLineOfSight(TheCamera.GetPosition() + 2.0f * TheCamera.GetForward(),
+ vTestedPos, point, entity, true, true, true, true, true, false) ||
+ entity == pTestedPed) {
+ nCounter += 2;
+ if (nCounter > 20) {
+ bTargetting = true;
+ nCounter = 20;
+ }
+ }
+ }
+ }
+ }
+ }
+ UpdateCompareFlag(bTargetting);
return 0;
}
+ /*
case COMMAND_IS_PLAYER_TARGETTING_OBJECT:
{
CollectParameters(&m_nIp, 2);
@@ -901,6 +1041,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
UpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject);
return 0;
}
+ */
case COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:
{
CTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);
@@ -942,9 +1083,14 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
case COMMAND_FAIL_CURRENT_MISSION:
CTheScripts::FailCurrentMission = 2;
+#ifdef MISSION_REPLAY
+ MissionSkipLevel = 0;
+#endif
return 0;
case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:
{
+ return 0;
+/*
CollectParameters(&m_nIp, 5);
CVector pos = *(CVector*)&ScriptParams[0];
if (pos.z <= MAP_Z_LOW_LIMIT)
@@ -988,7 +1134,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
StoreParameters(&m_nIp, 1);
return 0;
+*/
}
+ /*
case COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:
{
CollectParameters(&m_nIp, 5);
@@ -1000,28 +1148,20 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset);
return 0;
}
+ */
case COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- if (pVehicle->pDriver) {
- pVehicle->pDriver->bScriptObjectiveCompleted = false;
- pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
- }
- for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++)
- {
- if (pVehicle->pPassengers[i]) {
- pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false;
- pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
- }
- }
+ CCarAI::TellOccupantsToLeaveCar(pVehicle);
return 0;
}
case COMMAND_SET_INTERPOLATION_PARAMETERS:
CollectParameters(&m_nIp, 2);
- TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 50.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
+ TheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 100.0f - *(float*)&ScriptParams[0], ScriptParams[1]);
return 0;
+ /*
case COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:
{
CollectParameters(&m_nIp, 5);
@@ -1052,16 +1192,27 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 4);
return 0;
}
+ */
case COMMAND_GET_DEBUG_CAMERA_POINT_AT:
*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front;
StoreParameters(&m_nIp, 3);
return 0;
case COMMAND_ATTACH_CHAR_TO_CAR:
- // empty implementation
+ {
+ CollectParameters(&m_nIp, 8);
+ CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ pPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(*(float*)&ScriptParams[6]), (eWeaponType)ScriptParams[7]);
return 0;
+ }
case COMMAND_DETACH_CHAR_FROM_CAR:
- // empty implementation
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ if (pPed && pPed->m_attachedTo)
+ pPed->DettachPedFromEntity();
return 0;
+ }
case COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA
{
CollectParameters(&m_nIp, 2);
@@ -1074,20 +1225,25 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
- script_assert(pPed);
- pPed->m_lastWepDam = -1;
+ if (pPed)
+ pPed->m_lastWepDam = -1;
+ else
+ debug("CLEAR_CHAR_LAST_WEAPON_DAMAGE - Character doesn't exist\n");
return 0;
}
case COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:
{
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
- pVehicle->m_nLastWeaponDamage = -1;
+ if (pVehicle)
+ pVehicle->m_nLastWeaponDamage = -1;
+ else
+ debug("CLEAR_CAR_LAST_WEAPON_DAMAGE - Vehicle doesn't exist\n");
return 0;
}
case COMMAND_GET_RANDOM_COP_IN_AREA:
{
- CollectParameters(&m_nIp, 4);
+ CollectParameters(&m_nIp, 9);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
float x1 = *(float*)&ScriptParams[0];
@@ -1103,9 +1259,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
continue;
if (pPed->m_nPedType != PEDTYPE_COP)
continue;
+ if (!ThisIsAValidRandomCop(pPed->GetModelIndex(), ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]))
+ continue;
if (pPed->CharCreatedBy != RANDOM_CHAR)
continue;
- if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)
+ if (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING && pPed->GetPedState() != PED_ABSEIL)
continue;
if (pPed->bRemoveFromWorld)
continue;
@@ -1115,9 +1273,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
continue;
if (!pPed->IsWithinArea(x1, y1, x2, y2))
continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ if (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z)
continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ if (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z)
continue;
ped_handle = CPools::GetPedPool()->GetIndex(pPed);
CTheScripts::LastRandomPedId = ped_handle;
@@ -1131,14 +1289,15 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ /*
case COMMAND_GET_RANDOM_COP_IN_ZONE:
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -1162,9 +1321,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
continue;
if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))
continue;
- if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ if (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z)
continue;
- if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ if (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z)
continue;
ped_handle = CPools::GetPedPool()->GetIndex(pPed);
CTheScripts::LastRandomPedId = ped_handle;
@@ -1178,6 +1337,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
StoreParameters(&m_nIp, 1);
return 0;
}
+ */
case COMMAND_SET_CHAR_OBJ_FLEE_CAR:
{
CollectParameters(&m_nIp, 2);
@@ -1234,7 +1394,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -1243,7 +1403,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- ScriptParams[0] = pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType;
+ ScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -1255,15 +1415,16 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
LocateCharObjectCommand(command, &m_nIp);
return 0;
- case COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT: // this will be changed in final VC version to a more general SET_TEMP_ACTION
+ case COMMAND_SET_CAR_TEMP_ACTION:
{
- CollectParameters(&m_nIp, 2);
+ CollectParameters(&m_nIp, 3);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
script_assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ pVehicle->AutoPilot.m_nTempAction = (uint8)ScriptParams[1];
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2];
return 0;
}
+ /*
case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
{
CollectParameters(&m_nIp, 2);
@@ -1282,18 +1443,21 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
return 0;
}
+ */
case COMMAND_IS_CHAR_ON_ANY_BIKE:
{
CollectParameters(&m_nIp, 1);
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ UpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);
return 0;
}
+ /*
case COMMAND_LOCATE_SNIPER_BULLET_2D:
case COMMAND_LOCATE_SNIPER_BULLET_3D:
LocateSniperBulletCommand(command, &m_nIp);
return 0;
+ */
case COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:
CollectParameters(&m_nIp, 1);
ScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1;
@@ -1304,9 +1468,10 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
CollectParameters(&m_nIp, 1);
CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
script_assert(pPed);
- UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);
return 0;
}
+ /*
case COMMAND_IS_CHAR_LYING_DOWN:
{
CollectParameters(&m_nIp, 1);
@@ -1315,6 +1480,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
UpdateCompareFlag(pPed->bFallenDown);
return 0;
}
+ */
case COMMAND_CAN_CHAR_SEE_DEAD_CHAR:
{
CollectParameters(&m_nIp, 2);
@@ -1332,23 +1498,315 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nEnterCarRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
-#if GTA_VERSION < GTA3_PC_11
case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nThreatReactionRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
+ case COMMAND_SET_CHAR_CEASE_ATTACK_TIMER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->m_ceaseAttackTimer = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_REMOTE_CONTROLLED_CAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CWorld::Players[ScriptParams[0]].m_pRemoteVehicle;
+ if (pVehicle)
+ ScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ else
+ ScriptParams[0] = -1;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_PC_VERSION:
+ UpdateCompareFlag(true);
+ return 0;
+ //case COMMAND_REPLAY:
+ //case COMMAND_IS_REPLAY_PLAYING:
+ case COMMAND_IS_MODEL_AVAILABLE:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil);
+ return 0;
+ case COMMAND_SHUT_CHAR_UP:
+ CollectParameters(&m_nIp, 2);
+ DMAudio.SetPedTalkingStatus(CPools::GetPedPool()->GetAt(ScriptParams[0]), ScriptParams[1] == 0);
+ return 0;
+ case COMMAND_SET_ENABLE_RC_DETONATE:
+ CollectParameters(&m_nIp, 1);
+ CVehicle::bDisableRemoteDetonation = !ScriptParams[0];
+ return 0;
+ case COMMAND_SET_CAR_RANDOM_ROUTE_SEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->m_nRouteSeed = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_IS_ANY_PICKUP_AT_COORDS:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ CRunningScript::UpdateCompareFlag(CPickups::TestForPickupsInBubble(pos, 0.5f));
+ return 0;
+ }
+ case COMMAND_GET_FIRST_PICKUP_COORDS:
+ case COMMAND_GET_NEXT_PICKUP_COORDS:
+ case COMMAND_REMOVE_ALL_CHAR_WEAPONS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->ClearWeapons();
+ return 0;
+ }
+ case COMMAND_HAS_PLAYER_GOT_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ bool bFound = false;
+ for (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {
+ if (pPed->GetWeapon(i).m_eWeaponType == ScriptParams[1]) {
+ bFound = true;
+ break;
+ }
+ }
+ UpdateCompareFlag(bFound);
+ return 0;
+ }
+ //case COMMAND_HAS_CHAR_GOT_WEAPON:
+ //case COMMAND_IS_PLAYER_FACING_CHAR:
+ case COMMAND_SET_TANK_DETONATE_CARS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle && pVehicle->m_vehType == VEHICLE_TYPE_CAR);
+ ((CAutomobile*)pVehicle)->bTankDetonateCars = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_GET_POSITION_OF_ANALOGUE_STICKS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPad* pPad = CPad::GetPad(ScriptParams[0]);
+ ScriptParams[0] = pPad->NewState.LeftStickX;
+ ScriptParams[1] = pPad->NewState.LeftStickY;
+ ScriptParams[2] = pPad->NewState.RightStickX;
+ ScriptParams[3] = pPad->NewState.RightStickY;
+ StoreParameters(&m_nIp, 4);
+ return 0;
+ }
+ case COMMAND_IS_CAR_ON_FIRE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ bool bOnFire = false;
+ if (pVehicle->m_pCarFire)
+ bOnFire = true;
+ if (pVehicle->m_vehType == VEHICLE_TYPE_CAR && ((CAutomobile*)pVehicle)->Damage.GetEngineStatus() >= ENGINE_STATUS_ON_FIRE)
+ bOnFire = true;
+ if (pVehicle->m_fHealth < 250.0f)
+ bOnFire = true;
+ UpdateCompareFlag(bOnFire);
+ return 0;
+ }
+ case COMMAND_IS_CAR_TYRE_BURST:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ bool bIsBurst = false;
+ CBike* pBike = (CBike*)pVehicle;
+ if (pVehicle->IsBike()) {
+ if (ScriptParams[1] == 4) {
+ for (int i = 0; i < 2; i++) {
+ if (pBike->m_wheelStatus[i] == WHEEL_STATUS_BURST)
+ bIsBurst = true;
+ }
+ }
+ else {
+ if (ScriptParams[1] == 2)
+ ScriptParams[1] = 0;
+ if (ScriptParams[1] == 3)
+ ScriptParams[1] = 1;
+ bIsBurst = pBike->m_wheelStatus[ScriptParams[1]] == WHEEL_STATUS_BURST;
+ }
+ }
+ else {
+ CAutomobile* pCar = (CAutomobile*)pVehicle;
+ if (ScriptParams[1] == 4) {
+ for (int i = 0; i < 4; i++) {
+ if (pCar->Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST)
+ bIsBurst = true;
+ }
+ }
+ else
+ bIsBurst = pCar->Damage.GetWheelStatus(ScriptParams[1] == WHEEL_STATUS_BURST);
+ }
+ UpdateCompareFlag(bIsBurst);
+ return 0;
+ }
+ //case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD:
+ //case COMMAND_SET_CAR_WAIT:
+ //case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE:
+ //case COMMAND_IS_PLAYER_FOOT_DOWN:
+ //case COMMAND_IS_CHAR_FOOT_DOWN:
+ case COMMAND_INITIALISE_OBJECT_PATH: {
+ CollectParameters(&m_nIp, 2);
+ int32 counter = 0;
+ while (counter < 3 && CScriptPaths::aArray[counter].m_state != SCRIPT_PATH_DISABLED) {
+ counter++;
+ }
+ CScriptPaths::aArray[counter].InitialiseOne(ScriptParams[0], *(float*)&ScriptParams[1]);
+ ScriptParams[0] = counter;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_START_OBJECT_ON_PATH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject *pObj = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ assert(pObj);
+ CScriptPaths::aArray[ScriptParams[1]].SetObjectToControl(pObj);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_PATH_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CScriptPaths::aArray[ScriptParams[0]].m_fSpeed = *(float*)&ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_PATH_POSITION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CScriptPaths::aArray[ScriptParams[0]].m_fPosition = *(float*)&ScriptParams[1];
+ return 0;
+ }
+ //case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH:
+ case COMMAND_CLEAR_OBJECT_PATH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CScriptPaths::aArray[ScriptParams[0]].Clear();
+ return 0;
+ }
+ case COMMAND_HELI_GOTO_COORDS:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ ((CAutomobile*)pVehicle)->TellHeliToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]);
+ return 0;
+ }
+ case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr == ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr == ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CVector pos;
+ pTarget->CreateDeadPedPickupCoors(&pos.x, &pos.y, &pos.z);
+ *(CVector*)&ScriptParams[0] = pos;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_CREATE_PROTECTION_PICKUP:
+ {
+ CollectParameters(&m_nIp, 5);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_REVENUE, PICKUP_ASSET_REVENUE, ScriptParams[3], ScriptParams[4]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_BOAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_BOAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_HELI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_HELI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_PLANE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_IN_ANY_PLANE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pPed && pPed->bIsInWater);
+ return 0;
+ }
+ case COMMAND_SET_VAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_LVAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
default:
script_assert(0);
}
diff --git a/src/control/Script7.cpp b/src/control/Script7.cpp
new file mode 100644
index 00000000..71099cc4
--- /dev/null
+++ b/src/control/Script7.cpp
@@ -0,0 +1,1404 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "CarCtrl.h"
+#include "ColStore.h"
+#include "Coronas.h"
+#include "CutsceneMgr.h"
+#include "DMAudio.h"
+#include "Explosion.h"
+#include "GameLogic.h"
+#include "General.h"
+#include "Glass.h"
+#include "Fluff.h"
+#include "Hud.h"
+#include "MBlur.h"
+#include "Pad.h"
+#include "Pickups.h"
+#include "Pools.h"
+#include "Population.h"
+#include "Radar.h"
+#include "RoadBlocks.h"
+#include "Ropes.h"
+#include "SetPieces.h"
+#include "SpecialFX.h"
+#include "Stats.h"
+#include "Streaming.h"
+#include "Timecycle.h"
+#include "User.h"
+#include "World.h"
+#include "Zones.h"
+
+int8 CRunningScript::ProcessCommands1200To1299(int32 command)
+{
+ switch (command) {
+ case COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr > ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr > ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ UpdateCompareFlag(ScriptParams[0] > *ptr);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ UpdateCompareFlag(ScriptParams[0] > *ptr);
+ return 0;
+ }
+ case COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr >= ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(*ptr >= ScriptParams[0]);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ UpdateCompareFlag(ScriptParams[0] >= *ptr);
+ return 0;
+ }
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR:
+ {
+ CollectParameters(&m_nIp, 1);
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ UpdateCompareFlag(ScriptParams[0] >= *ptr);
+ return 0;
+ }
+ case COMMAND_GET_CHAR_WEAPON_IN_SLOT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ ScriptParams[0] = pPed->GetWeapon(ScriptParams[1] - 1).m_eWeaponType;
+ ScriptParams[1] = pPed->GetWeapon(ScriptParams[1] - 1).m_nAmmoTotal;
+ ScriptParams[2] = CPickups::ModelForWeapon((eWeaponType)ScriptParams[0]);
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_GET_CLOSEST_STRAIGHT_ROAD:
+ {
+ CollectParameters(&m_nIp, 5);
+ int node1, node2;
+ float angle;
+ ThePaths.FindNodePairClosestToCoors(*(CVector*)&ScriptParams[0], PATH_CAR, &node1, &node2, &angle,
+ *(float*)&ScriptParams[3], *(float*)&ScriptParams[4], true, true);
+ if (node1 == -1) {
+ for (int i = 0; i < 7; i++)
+ ScriptParams[i] = 0;
+ }
+ else {
+ *(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(node1);
+ *(CVector*)&ScriptParams[3] = ThePaths.FindNodeCoorsForScript(node2);
+ *(float*)&ScriptParams[6] = angle;
+ }
+ StoreParameters(&m_nIp, 7);
+ return 0;
+ }
+ case COMMAND_SET_CAR_FORWARD_SPEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ float speed = *(float*)&ScriptParams[1] / GAME_SPEED_TO_CARAI_SPEED;
+ pVehicle->SetMoveSpeed(pVehicle->GetForward() * speed);
+ if (pVehicle->IsRealHeli() && pVehicle->IsCar())
+ ((CAutomobile*)pVehicle)->m_aWheelSpeed[1] = 0.22f;
+ return 0;
+ }
+ case COMMAND_SET_AREA_VISIBLE:
+ CollectParameters(&m_nIp, 1);
+ CGame::currArea = ScriptParams[0];
+ CStreaming::RemoveBuildingsNotInArea(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_CUTSCENE_ANIM_TO_LOOP:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CCutsceneMgr::SetCutsceneAnimToLoop(key);
+ return 0;
+ }
+ case COMMAND_MARK_CAR_AS_CONVOY_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bPartOfConvoy = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CWorld::Players[ScriptParams[0]].m_nHavocLevel = 0;
+ return 0;
+ }
+ case COMMAND_GET_HAVOC_CAUSED_BY_PLAYER:
+ {
+ CollectParameters(&m_nIp, 1);
+ ScriptParams[0] = CWorld::Players[ScriptParams[0]].m_nHavocLevel;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CREATE_SCRIPT_ROADBLOCK:
+ {
+ CollectParameters(&m_nIp, 6);
+ CRoadBlocks::RegisterScriptRoadBlock(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS:
+ {
+ CRoadBlocks::ClearScriptRoadBlocks();
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTargetPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING, pTargetPed);
+ return 0;
+ }
+ //case COMMAND_IS_PICKUP_IN_ZONE:
+ case COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector result = Multiply3x3(pPed->GetMatrix(), *(CVector*)&ScriptParams[1]) + pPed->GetPosition();
+ *(CVector*)&ScriptParams[0] = result;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ bool result = false;
+ if (pPed->bHasBeenPhotographed) {
+ result = true;
+ pPed->bHasBeenPhotographed = false;
+ }
+ UpdateCompareFlag(result);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ script_assert(pTargetPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_AIM_GUN_AT, pTargetPed);
+ return 0;
+ }
+ case COMMAND_SWITCH_SECURITY_CAMERA:
+ {
+ CollectParameters(&m_nIp, 1);
+ CSpecialFX::bVideoCam = ScriptParams[0] != 0;
+ return 0;
+ }
+ //case COMMAND_IS_CHAR_IN_FLYING_VEHICLE:
+ case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && (pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE));
+ return 0;
+ }
+ //case COMMAND_HAS_SONY_CD_BEEN_READ:
+ //case COMMAND_GET_NUMBER_OF_SONY_CDS_READ:
+ //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD:
+ //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD:
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_MONEY_SPENT_ON_CLOTHES:
+ CollectParameters(&m_nIp, 1);
+ CStats::MoneySpentOnFashion(ScriptParams[0]);
+ return 0;
+
+ case COMMAND_SET_HELI_ORIENTATION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());
+ float fAngle = DEGTORAD(*(float*)&ScriptParams[1] - 90.0f);
+ while (fAngle < 0.0f)
+ fAngle += TWOPI;
+ while (fAngle > TWOPI)
+ fAngle -= TWOPI;
+ pHeli->SetHeliOrientation(fAngle);
+ return 0;
+ }
+ case COMMAND_CLEAR_HELI_ORIENTATION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());
+ pHeli->ClearHeliOrientation();
+ return 0;
+ }
+ case COMMAND_PLANE_GOTO_COORDS:
+ {
+ CollectParameters(&m_nIp, 5);
+ CAutomobile* pPlane = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pPlane && pPlane->IsCar() && pPlane->IsRealPlane());
+ pPlane->TellPlaneToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]);
+ return 0;
+ }
+ case COMMAND_GET_NTH_CLOSEST_CAR_NODE:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ *(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(ThePaths.FindNthNodeClosestToCoors(pos, 0, 999999.9f, true, true, ScriptParams[3] - 1));
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ //case COMMAND_GET_NTH_CLOSEST_CHAR_NODE:
+ case COMMAND_DRAW_WEAPONSHOP_CORONA:
+ {
+ CollectParameters(&m_nIp, 9);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], 255, pos, *(float*)&ScriptParams[3],
+ 150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f, false, 0.2f);
+ return 0;
+ }
+ case COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle::bDisableRemoteDetonationOnContact = (ScriptParams[0] == 0);
+ return 0;
+ }
+ case COMMAND_FREEZE_CHAR_POSITION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bIsFrozen = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CHAR_DROWNS_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bDrownsInWater = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_RECORDS_COLLISIONS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->bUseCollisionRecords = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ UpdateCompareFlag(pObject->m_nCollisionRecords != 0);
+ return 0;
+ }
+ case COMMAND_REMOVE_RC_BUGGY:
+ {
+ CWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(false);
+ return 0;
+ }
+ //case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN:
+ case COMMAND_GET_CHAR_ARMOUR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ ScriptParams[0] = pPed->m_fArmour;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ //case COMMAND_SET_CHAR_ARMOUR:
+ case COMMAND_SET_HELI_STABILISER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bHeliMinimumTilt = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->AutoPilot.m_nSwitchDistance = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_POP_CAR_BOOT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pCar&& pCar->IsCar());
+ pCar->PopBoot();
+ return 0;
+ }
+ case COMMAND_SHUT_PLAYER_UP:
+ {
+ CollectParameters(&m_nIp, 2);
+ DMAudio.ShutUpPlayerTalking(!!ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_MOOD:
+ {
+ CollectParameters(&m_nIp, 3);
+ DMAudio.SetPlayersMood(ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_REQUEST_COLLISION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVector2D pos;
+ pos.x = *(float*)&ScriptParams[0];
+ pos.y = *(float*)&ScriptParams[1];
+ CColStore::RequestCollision(pos);
+ return 0;
+ }
+ case COMMAND_LOCATE_OBJECT_2D:
+ case COMMAND_LOCATE_OBJECT_3D:
+ LocateObjectCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_IS_OBJECT_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ UpdateCompareFlag(pObject->bIsInWater);
+ return 0;
+ }
+ //case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR:
+ case COMMAND_IS_OBJECT_IN_AREA_2D:
+ case COMMAND_IS_OBJECT_IN_AREA_3D:
+ ObjectInAreaCheckCommand(command, &m_nIp);
+ return 0;
+ case COMMAND_SET_CHAR_CROUCH:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->bCrouchWhenShooting = true;
+ pPed->SetDuck(ScriptParams[2], true);
+ }
+ else {
+ pPed->ClearDuck(true);
+ pPed->bCrouchWhenShooting = false;
+ }
+ return 0;
+ }
+ case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:
+ {
+ char label[12];
+ int16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };
+ int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };
+ int i;
+
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < CCarCtrl::NUM_CAR_CLASSES; i++)
+ carDensities[i] = ScriptParams[i + 1];
+ for (i = 0; i < CCarCtrl::NUM_BOAT_CLASSES; i++)
+ boatDensities[i] = ScriptParams[i + 1 + CCarCtrl::NUM_CAR_CLASSES];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ if (zone < 0) {
+ debug("Couldn't find zone - %s\n", label);
+ return 0;
+ }
+ while (zone >= 0) {
+ CTheZones::SetZoneCivilianCarInfo(zone, ScriptParams[0], carDensities, boatDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
+ return 0;
+ }
+ case COMMAND_REQUEST_ANIMATION:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CStreaming::RequestAnim(CAnimManager::GetAnimationBlockIndex(key), STREAMFLAGS_SCRIPTOWNED);
+ return 0;
+ }
+ case COMMAND_HAS_ANIMATION_LOADED:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ UpdateCompareFlag(CAnimManager::GetAnimationBlock(key)->isLoaded);
+ return 0;
+ }
+ case COMMAND_REMOVE_ANIMATION:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CStreaming::RemoveAnim(CAnimManager::GetAnimationBlockIndex(key));
+ return 0;
+ }
+ case COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bIsStaticWaitingForCollision);
+ return 0;
+ }
+ case COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ UpdateCompareFlag(pVehicle->bIsStaticWaitingForCollision);
+ return 0;
+ }
+ case COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ UpdateCompareFlag(pObject->bIsStaticWaitingForCollision);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ pPed->PedShuffle();
+ return 0;
+ }
+ case COMMAND_ATTACH_CHAR_TO_OBJECT:
+ {
+ CollectParameters(&m_nIp, 8);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+ pPed->AttachPedToEntity(pObject, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(ScriptParams[6]), (eWeaponType)ScriptParams[7]);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_AS_PLAYER_FRIEND:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bIsPlayerFriend = ScriptParams[2];
+ return 0;
+ }
+ //case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER:
+ case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING:
+ {
+ char onscreen_str[12];
+ script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
+ uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 2);
+ wchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???
+ strncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, ScriptParams[1] - 1);
+ return 0;
+ }
+ case COMMAND_ADD_SET_PIECE:
+ {
+ CollectParameters(&m_nIp, 13);
+ CSetPieces::AddOne(ScriptParams[0],
+ *(CVector2D*)&ScriptParams[1], *(CVector2D*)&ScriptParams[3],
+ *(CVector2D*)&ScriptParams[5], *(CVector2D*)&ScriptParams[7],
+ *(CVector2D*)&ScriptParams[9], *(CVector2D*)&ScriptParams[11]);
+ return 0;
+ }
+ case COMMAND_SET_EXTRA_COLOURS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CTimeCycle::StartExtraColour(ScriptParams[0]-1, ScriptParams[1] != 0);
+ return 0;
+ }
+ case COMMAND_CLEAR_EXTRA_COLOURS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTimeCycle::StopExtraColour(ScriptParams[0]);
+ return 0;
+ }
+ //case COMMAND_CLOSE_CAR_BOOT:
+ case COMMAND_GET_WHEELIE_STATS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ ScriptParams[0] = pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels;
+ *(float*)&ScriptParams[1] = pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;
+ ScriptParams[2] = pPlayerInfo->m_nLastTimeSpentOnWheelie;
+ *(float*)&ScriptParams[3] = pPlayerInfo->m_nLastDistanceTravelledOnWheelie;
+ ScriptParams[4] = pPlayerInfo->m_nLastTimeSpentOnStoppie;
+ *(float*)&ScriptParams[5] = pPlayerInfo->m_nLastDistanceTravelledOnStoppie;
+ StoreParameters(&m_nIp, 6);
+ pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels = 0;
+ pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels = 0.0f;
+ pPlayerInfo->m_nLastTimeSpentOnWheelie = 0;
+ pPlayerInfo->m_nLastDistanceTravelledOnWheelie = 0.0f;
+ pPlayerInfo->m_nLastTimeSpentOnStoppie = 0;
+ pPlayerInfo->m_nLastDistanceTravelledOnStoppie = 0.0f;
+ return 0;
+ }
+ //case COMMAND_DISARM_CHAR:
+ case COMMAND_BURST_CAR_TYRE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ if (pVehicle->IsBike()) {
+ if (ScriptParams[1] == 2)
+ ScriptParams[1] = 0;
+ else if (ScriptParams[1] == 3)
+ ScriptParams[1] = 1;
+ pVehicle->BurstTyre(ScriptParams[1], true);
+ }
+ else {
+ pVehicle->BurstTyre(ScriptParams[1], true);
+ }
+ return 0;
+ }
+ case COMMAND_IS_CHAR_OBJ_NO_OBJ:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->m_prevObjective == OBJECTIVE_NONE && pPed->m_objective == OBJECTIVE_NONE);
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_WEARING:
+ {
+ CollectParameters(&m_nIp, 1);
+ char key[12];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ for (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)
+ key[i] = tolower(key[i]);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(strcmp(key, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetModelName()) == 0);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_bDriveByAllowed = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVector pos;
+ pos.x = *(float*)&ScriptParams[1];
+ pos.y = *(float*)&ScriptParams[2];
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_SPRINT_TO_AREA, pos);
+ return 0;
+ }
+ case COMMAND_CREATE_SWAT_ROPE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CRopes::CreateRopeWithSwatComingDown(*(CVector*)&ScriptParams[0]);
+ return 0;
+ }
+ //case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA:
+ //case COMMAND_GET_NEAREST_TYRE_TO_POINT:
+ case COMMAND_SET_CAR_MODEL_COMPONENTS:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVehicleModelInfo::SetComponentsToUse(ScriptParams[1], ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_SWITCH_LIFT_CAMERA:
+ {
+ CollectParameters(&m_nIp, 1);
+ CSpecialFX::bLiftCam = ScriptParams[0] != 0;
+ return 0;
+ }
+ case COMMAND_CLOSE_ALL_CAR_DOORS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pCar&& pCar->IsCar());
+ pCar->CloseAllDoors();
+ return 0;
+ }
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D:
+ {
+ CollectParameters(&m_nIp, 4);
+ *(float*)&ScriptParams[0] = (*(CVector2D*)&ScriptParams[0] - *(CVector2D*)&ScriptParams[2]).Magnitude();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D:
+ {
+ CollectParameters(&m_nIp, 6);
+ *(float*)&ScriptParams[0] = (*(CVector*)&ScriptParams[0] - *(CVector*)&ScriptParams[3]).Magnitude();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_POP_CAR_BOOT_USING_PHYSICS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pCar && pCar->IsCar());
+ pCar->PopBootUsingPhysics();
+ return 0;
+ }
+ //case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA:
+ case COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE);
+ return 0;
+ }
+ case COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->m_pCollidingEntity = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ return 0;
+ }
+ //case COMMAND_GET_MAX_WANTED_LEVEL:
+ case COMMAND_IS_CHAR_WANDER_PATH_CLEAR:
+ {
+ CollectParameters(&m_nIp, 5);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(CWorld::IsWanderPathClear(pPed->GetPosition(), *(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3], 4));
+ return 0;
+ }
+ //case COMMAND_PRINT_HELP_WITH_NUMBER:
+ case COMMAND_PRINT_HELP_FOREVER:
+ {
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ CHud::SetHelpMessage(text, false, true);
+ return 0;
+ }
+ //case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER:
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1300To1399(int32 command)
+{
+ switch (command) {
+ case COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG:
+ {
+ CollectParameters(&m_nIp, 3);
+ CPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pTarget);
+ uint8 flag = 1 << (uint8)ScriptParams[1];
+ if (ScriptParams[2])
+ pTarget->m_gangFlags |= flag;
+ else
+ pTarget->m_gangFlags &= ~flag;
+
+ return 0;
+ }
+ case COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE:
+ return 0;
+ //case COMMAND_IS_MISSION_AUDIO_PLAYING:
+ case COMMAND_CREATE_LOCKED_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ // TheText.Get(key);
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY, PICKUP_PROPERTY_LOCKED, 0, 0, false, key);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CREATE_FORSALE_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ // TheText.Get(key);
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY_FORSALE, PICKUP_PROPERTY_FORSALE, ScriptParams[3], 0, false, key);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_FREEZE_CAR_POSITION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bIsFrozen = ScriptParams[1];
+ pVehicle->bInfiniteMass = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ CPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
+ bool result = false;
+ if (pPed) {
+ if (pPed->m_lastDamEntity) {
+ if (pPed->m_lastDamEntity == pTestedPed)
+ result = true;
+ if (pTestedPed->bInVehicle && pPed->m_lastDamEntity == pTestedPed->m_pMyVehicle)
+ result = true;
+ }
+ }else
+ debug("HAS_CHAR_BEEN_DAMAGED_BY_CHAR - First character doesn't exist\n");
+ UpdateCompareFlag(result);
+ return 0;
+ }
+ //case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR:
+ //case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR:
+ //case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR:
+ //case COMMAND_GET_RADIO_CHANNEL:
+ //case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS:
+ //case COMMAND_IS_CAR_DROWNING_IN_WATER:
+ case COMMAND_IS_CHAR_DROWNING_IN_WATER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pPed && pPed->bIsDrowning);
+ return 0;
+ }
+ case COMMAND_DISABLE_CUTSCENE_SHADOWS:
+ {
+ CCutsceneMgr::DisableCutsceneShadows();
+ return 0;
+ }
+ case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY:
+ {
+ CollectParameters(&m_nIp, 3);
+
+ bool shattered = false;
+ if ( CGlass::HasGlassBeenShatteredAtCoors(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]) )
+ shattered = true;
+
+ UpdateCompareFlag(shattered);
+ return 0;
+ }
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE:
+ {
+ CollectParameters(&m_nIp, 3);
+ CCutsceneMgr::AttachObjectToBone(CPools::GetObjectPool()->GetAt(ScriptParams[0]), CPools::GetObjectPool()->GetAt(ScriptParams[1]), ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject *obj1 = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ CObject *obj2 = CPools::GetObjectPool()->GetAt(ScriptParams[1]);
+
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+
+ CCutsceneMgr::AttachObjectToFrame(obj1, obj2, key);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bStayInCarOnJack = ScriptParams[1];
+ return 0;
+ }
+ //case COMMAND_IS_MISSION_AUDIO_LOADING:
+ case COMMAND_ADD_MONEY_SPENT_ON_WEAPONS:
+ CollectParameters(&m_nIp, 1);
+ CStats::MoneySpentOnWeapons(ScriptParams[0]);
+ return 0;
+ case COMMAND_ADD_MONEY_SPENT_ON_PROPERTY:
+ CollectParameters(&m_nIp, 1);
+ CStats::MoneySpentOnProperty(ScriptParams[0]);
+ return 0;
+ //case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING:
+ case COMMAND_SET_CHAR_ANSWERING_MOBILE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ if (ScriptParams[1])
+ pPed->SetAnswerMobile();
+ else
+ pPed->ClearAnswerMobile();
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_DRUNKENNESS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_pPed->m_nDrunkenness = ScriptParams[1];
+ pPlayerInfo->m_pPed->m_nFadeDrunkenness = 0;
+ if (pPlayerInfo->m_pPed->m_nDrunkenness == 0)
+ CMBlur::ClearDrunkBlur();
+ return 0;
+ }
+ //case COMMAND_GET_PLAYER_DRUNKENNESS:
+ //case COMMAND_SET_PLAYER_DRUG_LEVEL:
+ //case COMMAND_GET_PLAYER_DRUG_LEVEL:
+ //case COMMAND_ADD_LOAN_SHARK_VISITS:
+ case COMMAND_ADD_STORES_KNOCKED_OFF:
+ CollectParameters(&m_nIp, 1);
+ CStats::NumOfStoresKnockedOff(ScriptParams[0]);
+ return 0;
+ //case COMMAND_ADD_MOVIE_STUNTS:
+ case COMMAND_ADD_NUMBER_OF_ASSASSINATIONS:
+ CollectParameters(&m_nIp, 1);
+ CStats::NumOfAssassinations(ScriptParams[0]);
+ return 0;
+ case COMMAND_ADD_PIZZAS_DELIVERED:
+ CollectParameters(&m_nIp, 1);
+ CStats::NumOfPizzasDelivered(ScriptParams[0]);
+ return 0;
+ //case COMMAND_ADD_GARBAGE_PICKUPS:
+ case COMMAND_ADD_ICE_CREAMS_SOLD:
+ CollectParameters(&m_nIp, 1);
+ CStats::NumOfIceCreamSold(ScriptParams[0]);
+ return 0;
+ //case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE:
+ //case COMMAND_ADD_SHOOTING_RANGE_RANK:
+ //case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING:
+ //case COMMAND_ADD_MONEY_WON_ON_GAMBLING:
+ //case COMMAND_SET_LARGEST_GAMBLING_WIN:
+ case COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bDontFight = !ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_WAIT_STATE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->ClearWaitState();
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE:
+ {
+ CollectParameters(&m_nIp, 5);
+ int handle = -1;
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ float infX = *(float*)&ScriptParams[0];
+ float infY = *(float*)&ScriptParams[1];
+ float supX = *(float*)&ScriptParams[2];
+ float supY = *(float*)&ScriptParams[3];
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE)
+ continue;
+ if (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)
+ continue;
+ if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)
+ continue;
+ if (!pVehicle->IsWithinArea(infX, infY, supX, supY))
+ continue;
+ handle = CPools::GetVehiclePool()->GetIndex(pVehicle);
+ }
+ ScriptParams[0] = handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CAN_BURST_CAR_TYRES:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ pVehicle->bTyresDontBurst = !ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_AUTO_AIM:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ pPed->bDoomAim = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_FIRE_HUNTER_GUN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nGunFiringTime + 150) {
+ CWeapon gun(WEAPONTYPE_HELICANNON, 5000);
+ CVector worldGunPos = (pVehicle->GetMatrix() * vecHunterGunPos) + (CTimer::GetTimeStep() * pVehicle->m_vecMoveSpeed);
+ gun.FireInstantHit(pVehicle, &worldGunPos);
+ gun.AddGunshell(pVehicle, worldGunPos, CVector2D(0.f, 0.1f), 0.025f);
+ DMAudio.PlayOneShot(pVehicle->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.f);
+ pVehicle->m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
+ }
+ return 0;
+ }
+ case COMMAND_SET_PROPERTY_AS_OWNED:
+ CollectParameters(&m_nIp, 1);
+ CStats::AddPropertyAsOwned(ScriptParams[0]);
+ return 0;
+ case COMMAND_ADD_BLOOD_RING_KILLS:
+ CollectParameters(&m_nIp, 1);
+ CStats::AddNumBloodRingKills(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING:
+ CollectParameters(&m_nIp, 1);
+ CStats::LongestTimeInBloodRing(ScriptParams[0]);
+ return 0;
+ case COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE:
+ {
+ CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver();
+ return 0;
+ }
+ case COMMAND_IS_PLAYER_TOUCHING_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ CPhysical* pTestedEntity = pPed;
+ if (pPed->bInVehicle && pPed->m_pMyVehicle)
+ pTestedEntity = pPed->m_pMyVehicle;
+ UpdateCompareFlag(pTestedEntity->GetHasCollidedWith(pVehicle));
+ return 0;
+ }
+ //case COMMAND_IS_CHAR_TOUCHING_VEHICLE:
+ case COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER:
+ {
+ CollectParameters(&m_nIp, 6);
+ CVector d1 = CWorld::Players[ScriptParams[0]].GetPos() - *(CVector*)&ScriptParams[1];
+ CVector d2 = CWorld::Players[ScriptParams[0]].GetPos() + *(CVector*)&ScriptParams[1];
+ int i = CPools::GetPedPool()->GetSize();
+ bool result = false;
+ while (i--) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (ScriptParams[4] != pPed->GetModelIndex() && ScriptParams[5] != pPed->GetModelIndex())
+ continue;
+ if (pPed->IsWithinArea(d1.x, d1.y, d1.z, d2.x, d2.y, d2.z))
+ result = true;
+ }
+ UpdateCompareFlag(result);
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_FOLLOW_PATH:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (pPed->GetPedState() == PED_FOLLOW_PATH) {
+ pPed->RestorePreviousState();
+ pPed->ClearFollowPath();
+ }
+ return 0;
+ }
+ case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bCanBeShotInVehicle = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CCutsceneMgr::AttachObjectToParent(CPools::GetObjectPool()->GetAt(ScriptParams[0]), CPools::GetVehiclePool()->GetAt(ScriptParams[1]));
+ return 0;
+ }
+ case COMMAND_LOAD_MISSION_TEXT:
+ {
+ char key[8];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ TheText.LoadMissionText(key);
+ return 0;
+ }
+ case COMMAND_SET_TONIGHTS_EVENT:
+ {
+ CollectParameters(&m_nIp, 1);
+ CScrollBar::TonightsEvent = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ if (pPed)
+ pPed->m_lastDamEntity = nil;
+ else
+ debug("CLEAR_CHAR_LAST_DAMAGE_ENTITY - Character doesn't exist\n");
+ return 0;
+ }
+ //case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY:
+ case COMMAND_FREEZE_OBJECT_POSITION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->bIsFrozen = ScriptParams[1];
+ pObject->bInfiniteMass = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::bPlayerHasMetDebbieHarry = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_RIOT_INTENSITY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::RiotIntensity = ScriptParams[0];
+ return 0;
+ }
+ //case COMMAND_IS_CAR_IN_ANGLED_AREA_2D:
+ //case COMMAND_IS_CAR_IN_ANGLED_AREA_3D:
+ //case COMMAND_REMOVE_WEAPON_FROM_CHAR:
+ case COMMAND_SET_UP_TAXI_SHORTCUT:
+ {
+ CollectParameters(&m_nIp, 8);
+ CGameLogic::SetUpShortCut(
+ *(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3],
+ *(CVector*)&ScriptParams[4], *(float*)&ScriptParams[7]);
+ return 0;
+ }
+ case COMMAND_CLEAR_TAXI_SHORTCUT:
+ CGameLogic::ClearShortCut();
+ return 0;
+ //case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT:
+ //case COMMAND_GET_CLOSEST_WATER_NODE:
+ case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH:
+ CollectParameters(&m_nIp, 1);
+ CStats::PamphletMissionPassed = ScriptParams[0];
+ return 0;
+ case COMMAND_CREATE_CLOTHES_PICKUP:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_CLOTHES, PICKUP_ON_STREET, ScriptParams[3]);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ //case COMMAND_CHANGE_BLIP_THRESHOLD:
+ case COMMAND_MAKE_PLAYER_FIRE_PROOF:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_bFireproof = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_INCREASE_PLAYER_MAX_HEALTH:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_nMaxHealth += ScriptParams[1];
+ pPlayerInfo->m_pPed->m_fHealth = pPlayerInfo->m_nMaxHealth;
+ return 0;
+ }
+ case COMMAND_INCREASE_PLAYER_MAX_ARMOUR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ pPlayerInfo->m_nMaxArmour += ScriptParams[1];
+ pPlayerInfo->m_pPed->m_fArmour = pPlayerInfo->m_nMaxArmour;
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ CPed* pPed = CPopulation::AddPedInCar(pVehicle, true);
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
+ pPed->SetPosition(pVehicle->GetPosition());
+ pPed->SetOrientation(0.0f, 0.0f, 0.0f);
+ pPed->SetPedState(PED_DRIVING);
+ pPed->m_pMyVehicle = pVehicle;
+ pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
+ pVehicle->pDriver = pPed;
+ pVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver);
+ pPed->bInVehicle = true;
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ if (pVehicle->m_vehType == VEHICLE_TYPE_BOAT)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->bEngineOn = true;
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ CPopulation::ms_nTotalMissionPeds++;
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ CPed* pPed = CPopulation::AddPedInCar(pVehicle, false);
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ pPed->bAllowMedicsToReviveMe = false;
+ pPed->bIsPlayerFriend = false;
+ if (pVehicle->bIsBus)
+ pPed->bRenderPedInCar = false;
+ pPed->SetPosition(pVehicle->GetPosition());
+ pPed->SetOrientation(0.0f, 0.0f, 0.0f);
+ CPopulation::ms_nTotalMissionPeds++;
+ pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());
+ if (ScriptParams[1] >= 0)
+ pVehicle->AddPassenger(pPed, ScriptParams[1]);
+ else
+ pVehicle->AddPassenger(pPed);
+
+ pPed->m_pMyVehicle = pVehicle;
+ pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);
+ pPed->bInVehicle = true;
+ pPed->SetPedState(PED_DRIVING);
+ ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);
+ StoreParameters(&m_nIp, 1);
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bIgnoreThreatsBehindObjects = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ if (pPed->bInVehicle) {
+ if (pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType) {
+ if (pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_nAmmoTotal < ScriptParams[1])
+ pPed->SetAmmo(pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType, ScriptParams[1]);
+ }
+ else {
+ pPed->GiveWeapon(WEAPONTYPE_UZI, ScriptParams[1], true);
+ if (pPed->m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
+ pPed->m_storedWeapon = pPed->GetWeapon()->m_eWeaponType;
+ pPed->SetCurrentWeapon(WEAPONTYPE_UZI);
+ }
+ }
+ return 0;
+ }
+ case COMMAND_MAKE_HELI_COME_CRASHING_DOWN:
+ {
+ CollectParameters(&m_nIp, 1);
+ CAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());
+ pHeli->bHeliDestroyed = true;
+ return 0;
+ }
+ case COMMAND_ADD_EXPLOSION_NO_SOUND:
+ {
+ CollectParameters(&m_nIp, 4);
+ CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, false);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_AREA_VISIBLE:
+ {
+ CollectParameters(&m_nIp, 2);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ script_assert(pObject);
+ pObject->m_area = ScriptParams[1];
+ return 0;
+ }
+ //case COMMAND_WAS_VEHICLE_EVER_POLICE:
+ case COMMAND_SET_CHAR_NEVER_TARGETTED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bNeverEverTargetThisPed = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_LOAD_UNCOMPRESSED_ANIM:
+ {
+ char key[KEY_LENGTH_IN_SCRIPT];
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CCutsceneMgr::LoadAnimationUncompressed(key);
+ return 0;
+ }
+ case COMMAND_WAS_CUTSCENE_SKIPPED:
+ {
+ UpdateCompareFlag(CCutsceneMgr::WasCutsceneSkipped());
+ return 0;
+ }
+ case COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bCrouchWhenScared = true;
+ return 0;
+ }
+ case COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle &&
+ pPed->m_pMyVehicle->IsLawEnforcementVehicle() &&
+ pPed->m_pMyVehicle->GetModelIndex() != MI_PREDATOR);
+ return 0;
+ }
+ case COMMAND_DOES_CHAR_EXIST:
+ CollectParameters(&m_nIp, 1);
+ UpdateCompareFlag(CPools::GetPedPool()->GetAt(ScriptParams[0]) != 0);
+ return 0;
+ //case COMMAND_DOES_VEHICLE_EXIST:
+ //case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT:
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 2, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_STUCK:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->m_nWaitState == WAITSTATE_STUCK);
+ return 0;
+ }
+ case COMMAND_SET_ALL_TAXIS_HAVE_NITRO:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle::bAllTaxisHaveNitro = ScriptParams[0] != 0;
+ return 0;
+ }
+ case COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->bKindaStayInSamePlace = true;
+ pPed->bStopAndShoot = true;
+ }
+ else {
+ pPed->bKindaStayInSamePlace = false;
+ pPed->bStopAndShoot = false;
+ }
+ pPed->m_nLastPedState = PED_NONE;
+ return 0;
+ }
+ case COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ if (ScriptParams[1]) {
+ pVehicle->bIsFrozen = true;
+ pVehicle->bInfiniteMass = true;
+ if (m_bIsMissionScript) {
+ CWorld::Remove(pVehicle);
+ pVehicle->bIsStaticWaitingForCollision = true;
+ CWorld::Add(pVehicle);
+ }
+ }
+ else {
+ pVehicle->bIsFrozen = false;
+ pVehicle->bInfiniteMass = false;
+ }
+ return 0;
+ }
+ //case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION:
+ //case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION:
+ //case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION:
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/Script8.cpp b/src/control/Script8.cpp
new file mode 100644
index 00000000..98f69737
--- /dev/null
+++ b/src/control/Script8.cpp
@@ -0,0 +1,618 @@
+#include "common.h"
+
+#include "Script.h"
+#include "ScriptCommands.h"
+
+#include "DMAudio.h"
+#if ((defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT) && defined MORE_LANGUAGES)
+#include "Frontend.h"
+#endif
+#include "GameLogic.h"
+#include "Garages.h"
+#ifdef MISSION_REPLAY
+#include "GenericGameStorage.h"
+#endif
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+#include "General.h"
+#include "maths.h"
+#endif
+#include "Hud.h"
+#include "Pad.h"
+#include "PedAttractor.h"
+#include "Population.h"
+#include "Pools.h"
+#include "RpAnimBlend.h"
+#include "Stats.h"
+#include "VisibilityPlugins.h"
+#include "Wanted.h"
+#include "WaterLevel.h"
+#include "World.h"
+#include "Zones.h"
+
+int8 CRunningScript::ProcessCommands1400To1499(int32 command)
+{
+ switch (command) {
+ case COMMAND_REGISTER_VIGILANTE_LEVEL:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterLevelVigilanteMission(ScriptParams[0]);
+ return 0;
+ case COMMAND_CLEAR_ALL_CHAR_ANIMS:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (!pPed->bInVehicle) {
+ pPed->m_pVehicleAnim = nil;
+ pPed->RestartNonPartialAnims();
+ RpAnimBlendClumpRemoveAllAssociations(pPed->GetClump());
+ pPed->SetPedState(PED_IDLE);
+ pPed->SetMoveState(PEDMOVE_STILL);
+ pPed->m_nLastPedState = PED_NONE;
+ pPed->ClearAimFlag();
+ pPed->ClearLookFlag();
+ pPed->bIsPointingGunAt = false;
+ if (pPed->IsPlayer())
+ ((CPlayerPed*)pPed)->m_fMoveSpeed = 0.0f;
+ else
+ pPed->m_nStoredMoveState = PEDMOVE_STILL;
+ CAnimManager::AddAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_STD_IDLE);
+ pPed->bIsPedDieAnimPlaying = false;
+ }
+ return 0;
+ }
+ case COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE:
+ CollectParameters(&m_nIp, 2);
+ CGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_WANTED_STARS_ARE_FLASHING:
+ {
+ CWanted* pWanted = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted;
+ UpdateCompareFlag(pWanted->m_nMinWantedLevel - pWanted->GetWantedLevel() > 0);
+ return 0;
+ }
+ case COMMAND_SET_ALLOW_HURRICANES:
+ CollectParameters(&m_nIp, 1);
+ CStats::NoMoreHurricanes = ScriptParams[0];
+ return 0;
+ case COMMAND_PLAY_ANNOUNCEMENT:
+ {
+ CollectParameters(&m_nIp, 1);
+ DMAudio.PlayRadioAnnouncement(ScriptParams[0] + STREAMED_SOUND_ANNOUNCE_BRIDGE_CLOSED);
+ return 0;
+ }
+ case COMMAND_SET_PLAYER_IS_IN_STADIUM:
+ {
+ CollectParameters(&m_nIp, 1);
+ CTheScripts::bPlayerIsInTheStatium = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ ScriptParams[0] = pPlayerInfo->m_pPed->m_nLastBusFareCollected;
+ pPlayerInfo->m_pPed->m_nLastBusFareCollected = 0;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);
+ script_assert(pVehicle);
+ ScriptParams[0] = 0;
+ if (pPed->m_objective == OBJECTIVE_NONE && !pPed->bHasAlreadyUsedAttractor) {
+ C2dEffect* pEffect = (C2dEffect*)GetPedAttractorManager()->GetEffectForIceCreamVan(pVehicle, pPed->GetPosition()); // has to be casted, because inner methods are const
+ if (pEffect) {
+ CVector pos;
+ CPedAttractorManager::ComputeEffectPos(pEffect, pVehicle->GetMatrix(), pos);
+ if ((pPed->GetPosition() - pos).MagnitudeSqr() < SQR(20.0f)) {
+ if (GetPedAttractorManager()->HasEmptySlot(pEffect) && GetPedAttractorManager()->IsApproachable(pEffect, pVehicle->GetMatrix(), 0, pPed)) {
+ if (GetPedAttractorManager()->RegisterPedWithAttractor(pPed, pEffect, pVehicle->GetMatrix()))
+ ScriptParams[0] = 1;
+ }
+ }
+ }
+ }
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_DISPLAY_RADAR:
+ CollectParameters(&m_nIp, 1);
+ CHud::m_HideRadar = ScriptParams[0] == 0;
+ return 0;
+ case COMMAND_REGISTER_BEST_POSITION:
+ CollectParameters(&m_nIp, 2);
+ CStats::RegisterBestPosition(ScriptParams[0], ScriptParams[1]);
+ return 0;
+ case COMMAND_IS_PLAYER_IN_INFO_ZONE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
+ char key[KEY_LENGTH_IN_SCRIPT];
+ memset(key, 0, KEY_LENGTH_IN_SCRIPT);
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CVector pos = pPlayerInfo->GetPos();
+ CZone* infoZone = CTheZones::FindInformationZoneForPosition(&pos);
+ UpdateCompareFlag(strncmp(key, infoZone->name, 8) == 0); // original code doesn't seem to be using strncmp in here and compare 2 ints instead
+ return 0;
+ }
+ case COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (pPed->m_attractor)
+ GetPedAttractorManager()->DeRegisterPed(pPed, pPed->m_attractor);
+ return 0;
+ }
+ case COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED:
+ UpdateCompareFlag(CPad::GetPad(0)->GetCarGunFired());
+ return 0;
+ case COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bHasAlreadyUsedAttractor);
+ return 0;
+ }
+ case COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ if (ScriptParams[1]) {
+ pVehicle->bDontLoadCollision = false;
+ if (m_bMissionFlag) {
+ CWorld::Remove(pVehicle);
+ pVehicle->bIsStaticWaitingForCollision = true;
+ CWorld::Add(pVehicle);
+ }
+ }
+ else {
+ pVehicle->bDontLoadCollision = true;
+ if (pVehicle->bIsStaticWaitingForCollision) {
+ pVehicle->bIsStaticWaitingForCollision = false;
+ if (!pVehicle->GetIsStatic())
+ pVehicle->AddToMovingList();
+ }
+ }
+ return 0;
+ }
+ case COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ if (ScriptParams[1]) {
+ pPed->bDontLoadCollision = false;
+ if (m_bMissionFlag) {
+ CWorld::Remove(pPed);
+ pPed->bIsStaticWaitingForCollision = true;
+ CWorld::Add(pPed);
+ }
+ }
+ else {
+ pPed->bDontLoadCollision = true;
+ if (pPed->bIsStaticWaitingForCollision) {
+ pPed->bIsStaticWaitingForCollision = false;
+ if (!pPed->GetIsStatic())
+ pPed->AddToMovingList();
+ }
+ }
+ return 0;
+ }
+ //case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG:
+ case COMMAND_ADD_BIG_GUN_FLASH:
+ {
+ CollectParameters(&m_nIp, 6);
+ CWeapon::AddGunFlashBigGuns(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bBoughtIceCream);
+ return 0;
+ }
+ case COMMAND_GET_PROGRESS_PERCENTAGE:
+ *(float*)&ScriptParams[0] = CStats::GetPercentageProgress();
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SET_SHORTCUT_PICKUP_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CGameLogic::AddShortCutPointAfterDeath(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION:
+ {
+ CollectParameters(&m_nIp, 4);
+ CGameLogic::AddShortCutDropOffPointForMission(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);
+ return 0;
+ }
+ case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 7);
+ int ped_handle = -1;
+ CVector pos = FindPlayerCoors();
+ float x1 = *(float*)&ScriptParams[0];
+ float y1 = *(float*)&ScriptParams[1];
+ float x2 = *(float*)&ScriptParams[2];
+ float y2 = *(float*)&ScriptParams[3];
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i && ped_handle == -1) {
+ CPed* pPed = CPools::GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))
+ continue;
+ if (pPed->CharCreatedBy != RANDOM_CHAR)
+ continue;
+ if (!pPed->IsPedInControl())
+ continue;
+ if (pPed->bRemoveFromWorld)
+ continue;
+ if (pPed->bFadeOut)
+ continue;
+ if (pPed->m_nWaitState != WAITSTATE_FALSE)
+ continue;
+ if (pPed->bHasAlreadyUsedAttractor)
+ continue;
+ if (pPed->m_attractor)
+ continue;
+ if (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[4], ScriptParams[5], ScriptParams[6]))
+ continue;
+ if (pPed->bIsLeader || pPed->m_leader)
+ continue;
+ if (!pPed->IsWithinArea(x1, y1, x2, y2))
+ continue;
+ if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)
+ continue;
+ if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)
+ continue;
+ ped_handle = CPools::GetPedPool()->GetIndex(pPed);
+ CTheScripts::LastRandomPedId = ped_handle;
+ pPed->CharCreatedBy = MISSION_CHAR;
+ pPed->bRespondsToThreats = false;
+ ++CPopulation::ms_nTotalMissionPeds;
+ if (m_bIsMissionScript)
+ CTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);
+ }
+ ScriptParams[0] = ped_handle;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ //case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE:
+ case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA:
+ {
+ CollectParameters(&m_nIp, 4);
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ float infX = *(float*)&ScriptParams[0];
+ float infY = *(float*)&ScriptParams[1];
+ float supX = *(float*)&ScriptParams[2];
+ float supY = *(float*)&ScriptParams[3];
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (pVehicle->IsWithinArea(infX, infY, supX, supY))
+ pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ }
+ return 0;
+ }
+ case COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS:
+ CollectParameters(&m_nIp, 2);
+ CGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]);
+ return 0;
+ case COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ pPed->bHeldHostageInCar = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_SET_VEHICLE_TO_FADE_IN:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ script_assert(pVehicle);
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), ScriptParams[1]);
+ return 0;
+ }
+ case COMMAND_REGISTER_ODDJOB_MISSION_PASSED:
+ ++CStats::MissionsPassed;
+ CStats::CheckPointReachedSuccessfully();
+ CTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();
+ CGameLogic::RemoveShortCutDropOffPointForMission();
+ return 0;
+ case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;
+ script_assert(pPed);
+ UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle && pPed->m_pMyVehicle == CGameLogic::pShortCutTaxi);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_DUCKING:
+ {
+ CollectParameters(&m_nIp, 1);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ script_assert(pPed);
+ UpdateCompareFlag(RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_DUCK_DOWN) != nil);
+ return 0;
+ }
+ case COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI:
+ {
+ CollectParameters(&m_nIp, 3);
+ CObject* pHeli = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ bool found = false;
+ float waterLevel = -1000.0f;
+ CVector pos = pHeli->GetPosition();
+ float radius = *(float*)&ScriptParams[1];
+ float ground = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found);
+ if (!CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))
+ waterLevel = 0.0f;
+ if (waterLevel > ground)
+ ground = waterLevel;
+ if (ScriptParams[2] > 8)
+ ScriptParams[2] = 8;
+ CVehicle::HeliDustGenerate(pHeli, (pos.z - ground - 1.0f - radius) * 0.3 + radius, ground, ScriptParams[2]);
+ return 0;
+ }
+ case COMMAND_REGISTER_FIRE_LEVEL:
+ CollectParameters(&m_nIp, 1);
+ CStats::RegisterLevelFireMission(ScriptParams[0]);
+ return 0;
+ case COMMAND_IS_AUSTRALIAN_GAME:
+ UpdateCompareFlag(false); // should we make some check?
+ return 0;
+ case COMMAND_DISARM_CAR_BOMB:
+ {
+ CollectParameters(&m_nIp, 1);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ if (pVehicle->m_bombType != CARBOMB_NONE) {
+ pVehicle->m_bombType = CARBOMB_NONE;
+ pVehicle->m_pBombRigger = nil;
+ }
+ return 0;
+ }
+#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)
+ case COMMAND_IS_JAPANESE_GAME:
+#ifdef MORE_LANGUAGES
+ UpdateCompareFlag(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_JAPANESE);
+#elif (defined GTAVC_JP_PATCH)
+ UpdateCompareFlag(true);
+#else
+ UpdateCompareFlag(false);
+#endif
+ return 0;
+#elif (!defined GTA_PS2)
+ case COMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED:
+ {
+ script_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);
+ uint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);
+ CollectParameters(&m_nIp, 1);
+ //CUserDisplay::OnscnTimer.SetCounterFlashWhenFirstDisplayed(var, ScriptParams[0]);
+ return 0;
+ }
+#endif
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ case COMMAND_SHUFFLE_CARD_DECKS:
+ {
+ CollectParameters(&m_nIp, 1);
+ script_assert(ScriptParams[0] >= 0 && ScriptParams[0] <= 6);
+ for (int i = 0; i < CARDS_IN_STACK; i++)
+ CTheScripts::CardStack[i] = 0;
+ int16 seq[CARDS_IN_STACK];
+ for (int i = 0; i < MAX_DECKS * CARDS_IN_DECK; i++)
+ seq[i] = i;
+ int cards_left = CARDS_IN_DECK * ScriptParams[0];
+ for (int k = 1; k < CARDS_IN_DECK + 1; k++) {
+ for (int deck = 0; deck < ScriptParams[0]; deck++) {
+ int index = CGeneral::GetRandomNumberInRange(0, cards_left);
+ CTheScripts::CardStack[seq[index]] = k;
+ for (int l = index; l < cards_left; l++) {
+ if (l + 1 < CARDS_IN_STACK)
+ seq[l] = seq[l + 1];
+ else
+ seq[l] = 0;
+ }
+ --cards_left;
+ }
+ }
+ CTheScripts::CardStackPosition = 0;
+ return 0;
+ }
+ case COMMAND_FETCH_NEXT_CARD:
+ {
+ if (CTheScripts::CardStack[CTheScripts::CardStackPosition] == 0)
+ CTheScripts::CardStackPosition = 0;
+ ScriptParams[0] = CTheScripts::CardStack[CTheScripts::CardStackPosition++];
+ if (CTheScripts::CardStackPosition == CARDS_IN_DECK * MAX_DECKS)
+ CTheScripts::CardStackPosition = 0;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_GET_OBJECT_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ *(CVector*)&ScriptParams[0] = GAME_SPEED_TO_METERS_PER_SECOND * pObject->GetMoveSpeed();
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_IS_DEBUG_CAMERA_ON:
+ UpdateCompareFlag(TheCamera.WorldViewerBeingUsed);
+ return 0;
+ case COMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ CVector newSpeed = pObject->GetTurnSpeed() + *(CVector*)&ScriptParams[1] / GAME_SPEED_TO_METERS_PER_SECOND;
+ if (pObject->bIsStatic) {
+ pObject->SetIsStatic(false);
+ pObject->AddToMovingList();
+ }
+ pObject->SetTurnSpeed(newSpeed.x, newSpeed.y, newSpeed.z);
+ return 0;
+ }
+ case COMMAND_SET_OBJECT_ROTATION_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ CVector newSpeed = *(CVector*)&ScriptParams[1] / GAME_SPEED_TO_METERS_PER_SECOND;
+ if (pObject->bIsStatic) {
+ pObject->SetIsStatic(false);
+ pObject->AddToMovingList();
+ }
+ pObject->SetTurnSpeed(newSpeed.x, newSpeed.y, newSpeed.z);
+ return 0;
+ }
+ case COMMAND_IS_OBJECT_STATIC:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ UpdateCompareFlag(pObject->GetIsStatic());
+ return 0;
+ }
+ case COMMAND_GET_ANGLE_BETWEEN_2D_VECTORS:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector2D v1 = *(CVector2D*)&ScriptParams[0];
+ CVector2D v2 = *(CVector2D*)&ScriptParams[2];
+ float c = DotProduct2D(v1, v2) / (v1.Magnitude() * v2.Magnitude());
+#ifdef FIX_BUGS // command is a SA leftover where it was fixed to this
+ *(float*)&ScriptParams[0] = RADTODEG(Acos(c));
+#else
+ *(float*)&ScriptParams[0] = Acos(c);
+#endif
+ return 0;
+ }
+ case COMMAND_DO_2D_RECTANGLES_COLLIDE:
+ {
+ CollectParameters(&m_nIp, 8);
+ float infX1 = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[2] * 0.5; // NB: not float
+ float supX1 = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2] * 0.5;
+ float infX2 = *(float*)&ScriptParams[4] - *(float*)&ScriptParams[6] * 0.5;
+ float supX2 = *(float*)&ScriptParams[4] + *(float*)&ScriptParams[6] * 0.5;
+ float infY1 = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[3] * 0.5;
+ float supY1 = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3] * 0.5;
+ float infY2 = *(float*)&ScriptParams[5] - *(float*)&ScriptParams[7] * 0.5;
+ float supY2 = *(float*)&ScriptParams[5] + *(float*)&ScriptParams[7] * 0.5;
+ bool collide = true;
+ if (infY2 > supY1)
+ collide = false;
+ if (infY1 > supY2)
+ collide = false;
+ if (infX2 > supX1)
+ collide = false;
+ if (infX1 > supX2)
+ collide = false;
+ UpdateCompareFlag(collide);
+ return 0;
+ }
+ case COMMAND_GET_OBJECT_ROTATION_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ *(CVector*)&ScriptParams[0] = pObject->GetTurnSpeed() * GAME_SPEED_TO_METERS_PER_SECOND;
+ StoreParameters(&m_nIp, 3);
+ return 0;
+ }
+ case COMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY:
+ {
+ CollectParameters(&m_nIp, 4);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ CVector vecAddition = *(CVector*)&ScriptParams[1] * CTimer::GetTimeStep() / GAME_SPEED_TO_METERS_PER_SECOND;
+ if (!pObject->bIsStatic) {
+ CVector vecCurrSpeed = pObject->GetSpeed();
+ vecCurrSpeed.Normalise();
+ if (vecCurrSpeed.z != 1.0) { // NB: not float!
+ CVector vx = CrossProduct(vecCurrSpeed, CVector(0.0f, 0.0f, 1.0f));
+ vx.Normalise();
+ CVector vz = CrossProduct(vx, vecCurrSpeed);
+ vz.Normalise();
+ CVector vecNewSpeed = pObject->GetSpeed() + vecAddition.x * vx + vecAddition.y * vecCurrSpeed + vecAddition.z * vecCurrSpeed;
+ if (pObject->bIsStatic) {
+ pObject->SetIsStatic(false);
+ pObject->AddToMovingList();
+ }
+ pObject->SetMoveSpeed(vecNewSpeed);
+ }
+ }
+ return 0;
+ }
+ case COMMAND_GET_OBJECT_SPEED:
+ {
+ CollectParameters(&m_nIp, 1);
+ CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
+ *(float*)&ScriptParams[0] = pObject->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+#endif
+#if (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ case COMMAND_IS_MISSION_SKIP:
+#ifdef MISSION_REPLAY
+ ScriptParams[0] = MissionSkipLevel;
+#else
+ ScriptParams[0] = 0;
+#endif
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_SET_IN_AMMUNATION:
+ CollectParameters(&m_nIp, 1);
+#ifdef MISSION_REPLAY
+ IsInAmmunation = ScriptParams[0];
+#endif
+ return 0;
+ case COMMAND_DO_SAVE_GAME:
+ CollectParameters(&m_nIp, 1);
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ UsingMobileScript = true;
+#endif
+#ifdef MISSION_REPLAY
+ SaveGameForPause(ScriptParams[0]);
+#endif
+ return 0;
+ case COMMAND_IS_RETRY:
+#ifdef MISSION_REPLAY
+ if (strcmp(m_abScriptName, "porno4") != 0)
+ ScriptParams[0] = AllowMissionReplay;
+#ifdef FIX_BUGS
+ else
+ ScriptParams[0] = gbTryingPorn4Again;
+#else
+ else if (gbTryingPorn4Again)
+ ScriptParams[0] = 1;
+#endif
+#else
+ ScriptParams[0] = 0;
+#endif
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ case COMMAND_DUMMY:
+ return 0;
+#endif
+#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ // it is unknown what these commands do but they don't take parameters
+ case COMMAND_MARK_CUTSCENE_START:
+ return 0;
+ case COMMAND_MARK_CUTSCENE_END:
+ return 0;
+ case COMMAND_CUTSCENE_SCROLL:
+ return 0;
+#endif
+ default:
+ script_assert(0);
+ }
+ return -1;
+}
diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h
index a33275f7..9863e852 100644
--- a/src/control/ScriptCommands.h
+++ b/src/control/ScriptCommands.h
@@ -995,7 +995,7 @@ enum {
COMMAND_FORCE_RANDOM_PED_TYPE,
COMMAND_SET_TEXT_DRAW_BEFORE_FADE,
COMMAND_GET_COLLECTABLE1S_COLLECTED,
- COMMAND_REGISTER_EL_BURRO_TIME,
+ COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR,
COMMAND_SET_SPRITES_DRAW_BEFORE_FADE,
COMMAND_SET_TEXT_RIGHT_JUSTIFY,
COMMAND_PRINT_HELP,
@@ -1022,17 +1022,17 @@ enum {
COMMAND_MAKE_PLAYER_SAFE,
COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL,
COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL,
- COMMAND_REGISTER_4X4_ONE_TIME,
- COMMAND_REGISTER_4X4_TWO_TIME,
- COMMAND_REGISTER_4X4_THREE_TIME,
- COMMAND_REGISTER_4X4_MAYHEM_TIME,
+ COMMAND_SET_DRUNK_INPUT_DELAY,
+ COMMAND_SET_CHAR_MONEY,
+ COMMAND_INCREASE_CHAR_MONEY,
+ COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS,
COMMAND_REGISTER_LIFE_SAVED,
COMMAND_REGISTER_CRIMINAL_CAUGHT,
COMMAND_REGISTER_AMBULANCE_LEVEL,
COMMAND_REGISTER_FIRE_EXTINGUISHED,
COMMAND_TURN_PHONE_ON,
COMMAND_REGISTER_LONGEST_DODO_FLIGHT,
- COMMAND_REGISTER_DEFUSE_BOMB_TIME,
+ COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS,
COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES,
COMMAND_BLOW_UP_RC_BUGGY,
COMMAND_REMOVE_CAR_FROM_CHASE,
@@ -1108,7 +1108,6 @@ enum {
COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER,
COMMAND_LOAD_END_OF_GAME_TUNE,
COMMAND_ENABLE_PLAYER_CONTROL_CAMERA,
-#if GTA_VERSION > GTA3_PS2_160
COMMAND_SET_OBJECT_ROTATION,
COMMAND_GET_DEBUG_CAMERA_COORDINATES,
COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR,
@@ -1145,7 +1144,7 @@ enum {
COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D,
COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D,
COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D,
- COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT,
+ COMMAND_SET_CAR_TEMP_ACTION,
COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT,
COMMAND_SET_CAR_HANDBRAKE_STOP,
COMMAND_IS_CHAR_ON_ANY_BIKE,
@@ -1156,13 +1155,324 @@ enum {
COMMAND_IS_CHAR_LYING_DOWN,
COMMAND_CAN_CHAR_SEE_DEAD_CHAR,
COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER,
-#if GTA_VERSION < GTA3_PC_11
COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER,
+ COMMAND_SET_CHAR_CEASE_ATTACK_TIMER,
+ COMMAND_GET_REMOTE_CONTROLLED_CAR,
+ COMMAND_IS_PC_VERSION,
+ COMMAND_REPLAY,
+ COMMAND_IS_REPLAY_PLAYING,
+ COMMAND_IS_MODEL_AVAILABLE,
+ COMMAND_SHUT_CHAR_UP,
+ COMMAND_SET_ENABLE_RC_DETONATE,
+ COMMAND_SET_CAR_RANDOM_ROUTE_SEED,
+ COMMAND_IS_ANY_PICKUP_AT_COORDS,
+ COMMAND_GET_FIRST_PICKUP_COORDS,
+ COMMAND_GET_NEXT_PICKUP_COORDS,
+ COMMAND_REMOVE_ALL_CHAR_WEAPONS,
+ COMMAND_HAS_PLAYER_GOT_WEAPON,
+ COMMAND_HAS_CHAR_GOT_WEAPON,
+ COMMAND_IS_PLAYER_FACING_CHAR,
+ COMMAND_SET_TANK_DETONATE_CARS,
+ COMMAND_GET_POSITION_OF_ANALOGUE_STICKS,
+ COMMAND_IS_CAR_ON_FIRE,
+ COMMAND_IS_CAR_TYRE_BURST,
+ COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD,
+ COMMAND_SET_CAR_WAIT,
+ COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE,
+ COMMAND_IS_PLAYER_FOOT_DOWN,
+ COMMAND_IS_CHAR_FOOT_DOWN,
+ COMMAND_INITIALISE_OBJECT_PATH,
+ COMMAND_START_OBJECT_ON_PATH,
+ COMMAND_SET_OBJECT_PATH_SPEED,
+ COMMAND_SET_OBJECT_PATH_POSITION,
+ COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH,
+ COMMAND_CLEAR_OBJECT_PATH,
+ COMMAND_HELI_GOTO_COORDS,
+ COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT,
+ COMMAND_GET_DEAD_CHAR_PICKUP_COORDS,
+ COMMAND_CREATE_PROTECTION_PICKUP,
+ COMMAND_IS_CHAR_IN_ANY_BOAT,
+ COMMAND_IS_PLAYER_IN_ANY_BOAT,
+ COMMAND_IS_CHAR_IN_ANY_HELI,
+ COMMAND_IS_PLAYER_IN_ANY_HELI,
+ COMMAND_IS_CHAR_IN_ANY_PLANE,
+ COMMAND_IS_PLAYER_IN_ANY_PLANE,
+ COMMAND_IS_CHAR_IN_WATER,
+ COMMAND_SET_VAR_INT_TO_CONSTANT,
+ COMMAND_SET_LVAR_INT_TO_CONSTANT,
+ COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR,
+ COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR,
+ COMMAND_GET_CHAR_WEAPON_IN_SLOT,
+ COMMAND_GET_CLOSEST_STRAIGHT_ROAD,
+ COMMAND_SET_CAR_FORWARD_SPEED,
+ COMMAND_SET_AREA_VISIBLE,
+ COMMAND_SET_CUTSCENE_ANIM_TO_LOOP,
+ COMMAND_MARK_CAR_AS_CONVOY_CAR,
+ COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_GET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_CREATE_SCRIPT_ROADBLOCK,
+ COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS,
+ COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR,
+ COMMAND_IS_PICKUP_IN_ZONE,
+ COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS,
+ COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED,
+ COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR,
+ COMMAND_SWITCH_SECURITY_CAMERA,
+ COMMAND_IS_CHAR_IN_FLYING_VEHICLE,
+ COMMAND_IS_PLAYER_IN_FLYING_VEHICLE,
+ COMMAND_HAS_SONY_CD_BEEN_READ,
+ COMMAND_GET_NUMBER_OF_SONY_CDS_READ,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD,
+ COMMAND_ADD_MONEY_SPENT_ON_CLOTHES,
+ COMMAND_SET_HELI_ORIENTATION,
+ COMMAND_CLEAR_HELI_ORIENTATION,
+ COMMAND_PLANE_GOTO_COORDS,
+ COMMAND_GET_NTH_CLOSEST_CAR_NODE,
+ COMMAND_GET_NTH_CLOSEST_CHAR_NODE,
+ COMMAND_DRAW_WEAPONSHOP_CORONA,
+ COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT,
+ COMMAND_FREEZE_CHAR_POSITION,
+ COMMAND_SET_CHAR_DROWNS_IN_WATER,
+ COMMAND_SET_OBJECT_RECORDS_COLLISIONS,
+ COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING,
+ COMMAND_REMOVE_RC_BUGGY,
+ COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN,
+ COMMAND_GET_CHAR_ARMOUR,
+ COMMAND_SET_CHAR_ARMOUR,
+ COMMAND_SET_HELI_STABILISER,
+ COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE,
+ COMMAND_POP_CAR_BOOT,
+ COMMAND_SHUT_PLAYER_UP,
+ COMMAND_SET_PLAYER_MOOD,
+ COMMAND_REQUEST_COLLISION,
+ COMMAND_LOCATE_OBJECT_2D,
+ COMMAND_LOCATE_OBJECT_3D,
+ COMMAND_IS_OBJECT_IN_WATER,
+ COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR,
+ COMMAND_IS_OBJECT_IN_AREA_2D,
+ COMMAND_IS_OBJECT_IN_AREA_3D,
+ COMMAND_SET_CHAR_CROUCH,
+ COMMAND_SET_ZONE_CIVILIAN_CAR_INFO,
+ COMMAND_REQUEST_ANIMATION,
+ COMMAND_HAS_ANIMATION_LOADED,
+ COMMAND_REMOVE_ANIMATION,
+ COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT,
+ COMMAND_ATTACH_CHAR_TO_OBJECT,
+ COMMAND_SET_CHAR_AS_PLAYER_FRIEND,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING,
+ COMMAND_ADD_SET_PIECE,
+ COMMAND_SET_EXTRA_COLOURS,
+ COMMAND_CLEAR_EXTRA_COLOURS,
+ COMMAND_CLOSE_CAR_BOOT,
+ COMMAND_GET_WHEELIE_STATS,
+ COMMAND_DISARM_CHAR,
+ COMMAND_BURST_CAR_TYRE,
+ COMMAND_IS_CHAR_OBJ_NO_OBJ,
+ COMMAND_IS_PLAYER_WEARING,
+ COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY,
+ COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD,
+ COMMAND_CREATE_SWAT_ROPE,
+ COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA,
+ COMMAND_GET_NEAREST_TYRE_TO_POINT,
+ COMMAND_SET_CAR_MODEL_COMPONENTS,
+ COMMAND_SWITCH_LIFT_CAMERA,
+ COMMAND_CLOSE_ALL_CAR_DOORS,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D,
+ COMMAND_POP_CAR_BOOT_USING_PHYSICS,
+ COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA,
+ COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE,
+ COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR,
+ COMMAND_GET_MAX_WANTED_LEVEL,
+ COMMAND_IS_CHAR_WANDER_PATH_CLEAR,
+ COMMAND_PRINT_HELP_WITH_NUMBER,
+ COMMAND_PRINT_HELP_FOREVER,
+ COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER,
+ COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG,
+ COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE,
+ COMMAND_IS_MISSION_AUDIO_PLAYING,
+ COMMAND_CREATE_LOCKED_PROPERTY_PICKUP,
+ COMMAND_CREATE_FORSALE_PROPERTY_PICKUP,
+ COMMAND_FREEZE_CAR_POSITION,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_GET_RADIO_CHANNEL,
+ COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS,
+ COMMAND_IS_CAR_DROWNING_IN_WATER,
+ COMMAND_IS_CHAR_DROWNING_IN_WATER,
+ COMMAND_DISABLE_CUTSCENE_SHADOWS,
+ COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT,
+ COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED,
+ COMMAND_IS_MISSION_AUDIO_LOADING,
+ COMMAND_ADD_MONEY_SPENT_ON_WEAPONS,
+ COMMAND_ADD_MONEY_SPENT_ON_PROPERTY,
+ COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING,
+ COMMAND_SET_CHAR_ANSWERING_MOBILE,
+ COMMAND_SET_PLAYER_DRUNKENNESS,
+ COMMAND_GET_PLAYER_DRUNKENNESS,
+ COMMAND_SET_PLAYER_DRUG_LEVEL,
+ COMMAND_GET_PLAYER_DRUG_LEVEL,
+ COMMAND_ADD_LOAN_SHARK_VISITS,
+ COMMAND_ADD_STORES_KNOCKED_OFF,
+ COMMAND_ADD_MOVIE_STUNTS,
+ COMMAND_ADD_NUMBER_OF_ASSASSINATIONS,
+ COMMAND_ADD_PIZZAS_DELIVERED,
+ COMMAND_ADD_GARBAGE_PICKUPS,
+ COMMAND_ADD_ICE_CREAMS_SOLD,
+ COMMAND_SET_TOP_SHOOTING_RANGE_SCORE,
+ COMMAND_ADD_SHOOTING_RANGE_RANK,
+ COMMAND_ADD_MONEY_SPENT_ON_GAMBLING,
+ COMMAND_ADD_MONEY_WON_ON_GAMBLING,
+ COMMAND_SET_LARGEST_GAMBLING_WIN,
+ COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT,
+ COMMAND_CLEAR_CHAR_WAIT_STATE,
+ COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE,
+ COMMAND_SET_CAN_BURST_CAR_TYRES,
+ COMMAND_SET_PLAYER_AUTO_AIM,
+ COMMAND_FIRE_HUNTER_GUN,
+ COMMAND_SET_PROPERTY_AS_OWNED,
+ COMMAND_ADD_BLOOD_RING_KILLS,
+ COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING,
+ COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE,
+ COMMAND_IS_PLAYER_TOUCHING_VEHICLE,
+ COMMAND_IS_CHAR_TOUCHING_VEHICLE,
+ COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER,
+ COMMAND_CLEAR_CHAR_FOLLOW_PATH,
+ COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE,
+ COMMAND_LOAD_MISSION_TEXT,
+ COMMAND_SET_TONIGHTS_EVENT,
+ COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY,
+ COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY,
+ COMMAND_FREEZE_OBJECT_POSITION,
+ COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY,
+ COMMAND_SET_RIOT_INTENSITY,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_2D,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_3D,
+ COMMAND_REMOVE_WEAPON_FROM_CHAR,
+ COMMAND_SET_UP_TAXI_SHORTCUT,
+ COMMAND_CLEAR_TAXI_SHORTCUT,
+ COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT,
+ COMMAND_GET_CLOSEST_WATER_NODE,
+ COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH,
+ COMMAND_CREATE_CLOTHES_PICKUP,
+ COMMAND_CHANGE_BLIP_THRESHOLD,
+ COMMAND_MAKE_PLAYER_FIRE_PROOF,
+ COMMAND_INCREASE_PLAYER_MAX_HEALTH,
+ COMMAND_INCREASE_PLAYER_MAX_ARMOUR,
+ COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER,
+ COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER,
+ COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS,
+ COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON,
+ COMMAND_MAKE_HELI_COME_CRASHING_DOWN,
+ COMMAND_ADD_EXPLOSION_NO_SOUND,
+ COMMAND_SET_OBJECT_AREA_VISIBLE,
+ COMMAND_WAS_VEHICLE_EVER_POLICE,
+ COMMAND_SET_CHAR_NEVER_TARGETTED,
+ COMMAND_LOAD_UNCOMPRESSED_ANIM,
+ COMMAND_WAS_CUTSCENE_SKIPPED,
+ COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED,
+ COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE,
+ COMMAND_DOES_CHAR_EXIST,
+ COMMAND_DOES_VEHICLE_EXIST,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_IS_CHAR_STUCK,
+ COMMAND_SET_ALL_TAXIS_HAVE_NITRO,
+ COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY,
+ COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION,
+ COMMAND_REGISTER_VIGILANTE_LEVEL,
+ COMMAND_CLEAR_ALL_CHAR_ANIMS,
+ COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE,
+ COMMAND_WANTED_STARS_ARE_FLASHING,
+ COMMAND_SET_ALLOW_HURRICANES,
+ COMMAND_PLAY_ANNOUNCEMENT,
+ COMMAND_SET_PLAYER_IS_IN_STADIUM,
+ COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER,
+ COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM,
+ COMMAND_DISPLAY_RADAR,
+ COMMAND_REGISTER_BEST_POSITION,
+ COMMAND_IS_PLAYER_IN_INFO_ZONE,
+ COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE,
+ COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED,
+ COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR,
+ COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG,
+ COMMAND_ADD_BIG_GUN_FLASH,
+ COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM,
+ COMMAND_GET_PROGRESS_PERCENTAGE,
+ COMMAND_SET_SHORTCUT_PICKUP_POINT,
+ COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE,
+ COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA,
+ COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS,
+ COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR,
+ COMMAND_SET_VEHICLE_TO_FADE_IN,
+ COMMAND_REGISTER_ODDJOB_MISSION_PASSED,
+ COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI,
+ COMMAND_IS_CHAR_DUCKING,
+ COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI,
+ COMMAND_REGISTER_FIRE_LEVEL,
+ COMMAND_IS_AUSTRALIAN_GAME,
+ COMMAND_DISARM_CAR_BOMB,
+#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)
+ COMMAND_IS_JAPANESE_GAME,
+#elif (!defined GTA_PS2)
+ COMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED,
+#endif
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ COMMAND_SHUFFLE_CARD_DECKS,
+ COMMAND_FETCH_NEXT_CARD,
+ COMMAND_GET_OBJECT_VELOCITY,
+ COMMAND_IS_DEBUG_CAMERA_ON,
+ COMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY,
+ COMMAND_SET_OBJECT_ROTATION_VELOCITY,
+ COMMAND_IS_OBJECT_STATIC,
+ COMMAND_GET_ANGLE_BETWEEN_2D_VECTORS,
+ COMMAND_DO_2D_RECTANGLES_COLLIDE,
+ COMMAND_GET_OBJECT_ROTATION_VELOCITY,
+ COMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY,
+ COMMAND_GET_OBJECT_SPEED,
+#endif
+#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT)
+ COMMAND_MARK_CUTSCENE_START,
+ COMMAND_MARK_CUTSCENE_END,
+ COMMAND_CUTSCENE_SCROLL,
+#elif (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ COMMAND_IS_MISSION_SKIP,
+ COMMAND_SET_IN_AMMUNATION,
+ COMMAND_DO_SAVE_GAME,
+ COMMAND_IS_RETRY,
+ COMMAND_DUMMY,
+ COMMAND_MARK_CUTSCENE_START,
+ COMMAND_MARK_CUTSCENE_END,
+ COMMAND_CUTSCENE_SCROLL,
#endif
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
LAST_SCRIPT_COMMAND
#endif
-#endif
};
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
diff --git a/src/control/ScriptDebug.cpp b/src/control/ScriptDebug.cpp
index 63508217..d48804e6 100644
--- a/src/control/ScriptDebug.cpp
+++ b/src/control/ScriptDebug.cpp
@@ -5,6 +5,10 @@
#include "Debug.h"
#include "FileMgr.h"
+#include "GameLogic.h"
+#ifdef MISSION_REPLAY
+#include "GenericGameStorage.h"
+#endif
#include "Messages.h"
#include "Timer.h"
#include "Stats.h"
@@ -104,7 +108,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_GOSUB, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_RETURN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_LINE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_CREATE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_PLAYER_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_PLAYER_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""),
@@ -169,10 +173,10 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_CSET_VAR_FLOAT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " =#"),
REGISTER_COMMAND(COMMAND_CSET_LVAR_INT_TO_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " =#"),
REGISTER_COMMAND(COMMAND_CSET_LVAR_FLOAT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " =#"),
- REGISTER_COMMAND(COMMAND_ABS_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
- REGISTER_COMMAND(COMMAND_ABS_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
- REGISTER_COMMAND(COMMAND_ABS_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
- REGISTER_COMMAND(COMMAND_ABS_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
+ REGISTER_COMMAND(COMMAND_ABS_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
+ REGISTER_COMMAND(COMMAND_ABS_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
+ REGISTER_COMMAND(COMMAND_ABS_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
+ REGISTER_COMMAND(COMMAND_ABS_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, " ABS"),
REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), false, -1, ""),
@@ -284,7 +288,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_DELETE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_ADD_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
@@ -354,12 +358,12 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_CREATE_GANG_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_SWITCH_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -369,7 +373,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_RESTORE_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SHAKE_PAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TIME_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_FIXED_CAMERA_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -558,8 +562,8 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_SET_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_PRINT_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_FREE_BOMBS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -738,7 +742,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(ARGTYPE_LABEL, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_GROUND_Z_FOR_3D_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_START_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
@@ -753,8 +757,8 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_ADD_POWER_PILL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_BOAT_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
- REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
@@ -766,7 +770,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_START_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_CUTSCENE_TIME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_CUTSCENE_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CUTSCENE_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_RESTORE_CAMERA_JUMPCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_COLLECTABLE1, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -818,8 +822,8 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_REMOVE_ALL_SCRIPT_FIRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_EXPLODE_CHAR_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -830,7 +834,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_START_CHAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_RESPRAY_HAPPENED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_RESPRAY_HAPPENED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAMERA_ZOOM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_PICKUP_WITH_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_RAM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -848,8 +852,8 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_SET_CAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_START_DRUG_RUN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SAVE_PLAYER_FROM_FIRES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_DISPLAY_TEXT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TEXT_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -878,7 +882,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_START_DRUG_DROP_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_FIND_DROP_OFF_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_FLOATING_PACKAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -984,7 +988,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
@@ -996,15 +1000,15 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_ADD_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REMOVE_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_THIS_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_THIS_BIG_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_ACTIVATE_SAVE_MENU, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -1015,7 +1019,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_FORCE_RANDOM_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TEXT_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_COLLECTABLE1S_COLLECTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_EL_BURRO_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_SPRITES_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TEXT_RIGHT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_PRINT_HELP, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -1032,7 +1036,7 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_USE_TEXT_COMMANDS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_CLEAR_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_MAKE_PLAYER_UNSAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -1042,23 +1046,23 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_4X4_ONE_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_4X4_TWO_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_4X4_THREE_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_4X4_MAYHEM_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_DRUNK_INPUT_DELAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_INCREASE_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_REGISTER_LIFE_SAVED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REGISTER_CRIMINAL_CAUGHT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REGISTER_AMBULANCE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REGISTER_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_TURN_PHONE_ON, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REGISTER_LONGEST_DODO_FLIGHT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_REGISTER_DEFUSE_BOMB_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_BLOW_UP_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_REMOVE_CAR_FROM_CHASE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_GANG_PED_MODEL_PREFERENCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
@@ -1128,7 +1132,6 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_LOAD_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_ENABLE_PLAYER_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
-#if GTA_VERSION > GTA3_PS2_160
REGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
@@ -1165,20 +1168,331 @@ const tScriptCommandData commands[] = {
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_TEMP_ACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
- REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
- REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
-#if GTA_VERSION < GTA3_PC_11
REGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_CEASE_ATTACK_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_REMOTE_CONTROLLED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PC_VERSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_REPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_REPLAY_PLAYING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_MODEL_AVAILABLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SHUT_CHAR_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_RANDOM_ROUTE_SEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_ANY_PICKUP_AT_COORDS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_FIRST_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_NEXT_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REMOVE_ALL_CHAR_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_PLAYER_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_FACING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_TANK_DETONATE_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_POSITION_OF_ANALOGUE_STICKS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_ON_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_TYRE_BURST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_INITIALISE_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_START_OBJECT_ON_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HELI_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_DEAD_CHAR_PICKUP_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_PROTECTION_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ="),
+ REGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, " ="),
+ REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >"),
+ REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >"),
+ REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >"),
+ REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >"),
+ REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >="),
+ REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >="),
+ REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >="),
+ REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, " >="),
+ REGISTER_COMMAND(COMMAND_GET_CHAR_WEAPON_IN_SLOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_CLOSEST_STRAIGHT_ROAD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_FORWARD_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM_TO_LOOP, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MARK_CAR_AS_CONVOY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_SCRIPT_ROADBLOCK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PICKUP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SWITCH_SECURITY_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_SONY_CD_BEEN_READ, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SONY_CDS_READ, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_CLOTHES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_PLANE_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DRAW_WEAPONSHOP_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_DROWNS_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_OBJECT_RECORDS_COLLISIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_REMOVE_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_HELI_STABILISER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_POP_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SHUT_PLAYER_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_MOOD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REQUEST_COLLISION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ZONE_CIVILIAN_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REQUEST_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_ANIMATION_LOADED, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_REMOVE_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_AS_PLAYER_FRIEND, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SET_PIECE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLOSE_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_WHEELIE_STATS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISARM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_BURST_CAR_TYRE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_WEARING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_SWAT_ROPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_NEAREST_TYRE_TO_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAR_MODEL_COMPONENTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SWITCH_LIFT_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLOSE_ALL_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_POP_CAR_BOOT_USING_PHYSICS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_WANDER_PATH_CLEAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_PRINT_HELP_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_LOCKED_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_FORSALE_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RADIO_CHANNEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISABLE_CUTSCENE_SHADOWS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_LOADING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_PROPERTY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_ANSWERING_MOBILE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_LOAN_SHARK_VISITS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_STORES_KNOCKED_OFF, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MOVIE_STUNTS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_NUMBER_OF_ASSASSINATIONS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_PIZZAS_DELIVERED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_GARBAGE_PICKUPS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_ICE_CREAMS_SOLD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_TOP_SHOOTING_RANGE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHOOTING_RANGE_RANK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_MONEY_WON_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_LARGEST_GAMBLING_WIN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CAN_BURST_CAR_TYRES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_AUTO_AIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FIRE_HUNTER_GUN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PROPERTY_AS_OWNED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_BLOOD_RING_KILLS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_CHAR_FOLLOW_PATH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOAD_MISSION_TEXT, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_TONIGHTS_EVENT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_RIOT_INTENSITY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_REMOVE_WEAPON_FROM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_UP_TAXI_SHORTCUT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_TAXI_SHORTCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_CLOSEST_WATER_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_CLOTHES_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CHANGE_BLIP_THRESHOLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MAKE_PLAYER_FIRE_PROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MAKE_HELI_COME_CRASHING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_EXPLOSION_NO_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_OBJECT_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_WAS_VEHICLE_EVER_POLICE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_NEVER_TARGETTED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_LOAD_UNCOMPRESSED_ANIM, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_WAS_CUTSCENE_SKIPPED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_DOES_CHAR_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_DOES_VEHICLE_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ALL_TAXIS_HAVE_NITRO, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REGISTER_VIGILANTE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_ALL_CHAR_ANIMS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_WANTED_STARS_ARE_FLASHING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_ALLOW_HURRICANES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_PLAY_ANNOUNCEMENT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_PLAYER_IS_IN_STADIUM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISPLAY_RADAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REGISTER_BEST_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_INFO_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_BIG_GUN_FLASH, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_PROGRESS_PERCENTAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_SHORTCUT_PICKUP_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_VEHICLE_TO_FADE_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REGISTER_ODDJOB_MISSION_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_CHAR_DUCKING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_REGISTER_FIRE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_AUSTRALIAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_DISARM_CAR_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)
+ REGISTER_COMMAND(COMMAND_IS_JAPANESE_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+#elif (!defined GTA_PS2)
+ REGISTER_COMMAND(COMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
#endif
+#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ REGISTER_COMMAND(COMMAND_SHUFFLE_CARD_DECKS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_FETCH_NEXT_CARD, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_DEBUG_CAMERA_ON, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_OBJECT_STATIC, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_ANGLE_BETWEEN_2D_VECTORS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DO_2D_RECTANGLES_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_GET_OBJECT_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""),
+#endif
+#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT)
+ REGISTER_COMMAND(COMMAND_MARK_CUTSCENE_START, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MARK_CUTSCENE_END, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CUTSCENE_SCROLL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+#elif (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)
+ REGISTER_COMMAND(COMMAND_IS_MISSION_SKIP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_SET_IN_AMMUNATION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DO_SAVE_GAME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_IS_RETRY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_DUMMY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MARK_CUTSCENE_START, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_MARK_CUTSCENE_END, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
+ REGISTER_COMMAND(COMMAND_CUTSCENE_SCROLL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""),
#endif
};
#undef REGISTER_COMMAND
@@ -1209,15 +1523,28 @@ static void PrintToLog(const char* format, ...)
#endif
}
+#endif
+
+void FlushLog()
+{
+#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
+#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2
+ if (dbg_log)
+ fflush(dbg_log);
+#endif
+#endif
+}
+
+#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
int CRunningScript::CollectParameterForDebug(char* buf, bool& var)
{
- float tmp;
uint16 varIndex;
char tmpstr[24];
var = false;
switch (CTheScripts::Read1ByteFromScript(&m_nIp))
{
case ARGUMENT_INT32:
+ case ARGUMENT_FLOAT:
return CTheScripts::Read4BytesFromScript(&m_nIp);
case ARGUMENT_GLOBALVAR:
varIndex = CTheScripts::Read2BytesFromScript(&m_nIp);
@@ -1237,9 +1564,6 @@ int CRunningScript::CollectParameterForDebug(char* buf, bool& var)
return CTheScripts::Read1ByteFromScript(&m_nIp);
case ARGUMENT_INT16:
return CTheScripts::Read2BytesFromScript(&m_nIp);
- case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(&m_nIp);
- return *(int32*)&tmp;
default:
PrintToLog("%s - script assertion failed in CollectParameterForDebug", buf);
script_assert(0);
@@ -1384,17 +1708,6 @@ void CRunningScript::LogAfterProcessingCommand(int32 command)
#endif
-void FlushLog()
-{
-#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
-#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2
- if (dbg_log)
- fflush(dbg_log);
-#endif
-#endif
-}
-
-
#ifdef MISSION_SWITCHER
void
CTheScripts::SwitchToMission(int32 mission)
@@ -1416,10 +1729,16 @@ CTheScripts::SwitchToMission(int32 mission)
CMessages::ClearMessages();
}
+ if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && mission <= UINT16_MAX - 2)
+ return;
+
#ifdef MISSION_REPLAY
missionRetryScriptIndex = mission;
- if (missionRetryScriptIndex == 19)
- CStats::LastMissionPassedName[0] = '\0';
+#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT
+ if (CTheScripts::MissionSupportsMissionReplay(missionRetryScriptIndex)) {
+ SaveGameForPause(SAVE_TYPE_QUICKSAVE_FOR_SCRIPT);
+ }
+#endif
#endif
CTimer::Suspend();
int offset = CTheScripts::MultiScriptArray[mission];
@@ -1437,5 +1756,6 @@ CTheScripts::SwitchToMission(int32 mission)
pMissionScript->m_bIsMissionScript = true;
pMissionScript->m_bMissionFlag = true;
CTheScripts::bAlreadyRunningAMissionScript = true;
+ CGameLogic::ClearShortCut();
}
#endif
diff --git a/src/control/SetPieces.cpp b/src/control/SetPieces.cpp
new file mode 100644
index 00000000..5edcd335
--- /dev/null
+++ b/src/control/SetPieces.cpp
@@ -0,0 +1,325 @@
+#include "common.h"
+
+#include "SetPieces.h"
+#include "Automobile.h"
+#include "CarAI.h"
+#include "CopPed.h"
+#include "GenericGameStorage.h"
+#include "PlayerPed.h"
+#include "Timer.h"
+#include "Vehicle.h"
+#include "Wanted.h"
+#include "World.h"
+#include "VarConsole.h"
+#include "SaveBuf.h"
+
+#define TIME_BETWEEN_SETPIECE_SPAWNS 20000
+
+bool CSetPieces::bDebug;
+uint32 CSetPieces::NumSetPieces;
+CSetPiece CSetPieces::aSetPieces[NUM_SETPIECES];
+
+void CSetPieces::Init(void)
+{
+ bDebug = false;
+ NumSetPieces = 0;
+#ifndef MASTER
+ VarConsole.Add("Show set pieces", &bDebug, true);
+#endif
+}
+
+void CSetPieces::AddOne(uint8 type, CVector2D vTriggerInf, CVector2D vTriggerSup, CVector2D vSpawn1, CVector2D vTarget1, CVector2D vSpawn2, CVector2D vTarget2)
+{
+ if (NumSetPieces >= NUM_SETPIECES)
+ return;
+ aSetPieces[NumSetPieces].m_nType = type;
+ aSetPieces[NumSetPieces].m_vTriggerInf.x = Min(vTriggerInf.x, vTriggerSup.x);
+ aSetPieces[NumSetPieces].m_vTriggerInf.y = Min(vTriggerInf.y, vTriggerSup.y);
+ aSetPieces[NumSetPieces].m_vTriggerSup.x = Max(vTriggerInf.x, vTriggerSup.x);
+ aSetPieces[NumSetPieces].m_vTriggerSup.y = Max(vTriggerInf.y, vTriggerSup.y);
+ aSetPieces[NumSetPieces].m_vSpawn1 = vSpawn1;
+ aSetPieces[NumSetPieces].m_vSpawn2 = vSpawn2;
+ aSetPieces[NumSetPieces].m_vTarget1 = vTarget1;
+ aSetPieces[NumSetPieces].m_vTarget2 = vTarget2;
+ ++NumSetPieces;
+}
+
+void CSetPieces::Update(void)
+{
+ int nFirst = NumSetPieces * (CTimer::GetFrameCounter() % 8) / 8;
+ int nLast = NumSetPieces * (CTimer::GetFrameCounter() % 8 + 1) / 8;
+ for (int i = nFirst; i < nLast; i++)
+ aSetPieces[i].Update();
+#ifndef MASTER
+ // TODO: debug code from mobile
+#endif // !MASTER
+}
+
+void CSetPieces::Save(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ WriteSaveBuf(buf, NumSetPieces);
+ for (int i = 0; i < NUM_SETPIECES; i++)
+ WriteSaveBuf(buf, aSetPieces[i]);
+ *size = sizeof(NumSetPieces) + NUM_SETPIECES * sizeof(CSetPiece);
+VALIDATESAVEBUF(*size)
+}
+
+void CSetPieces::Load(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ ReadSaveBuf(&NumSetPieces, buf);
+ for (int i = 0; i < NUM_SETPIECES; i++)
+ ReadSaveBuf(&aSetPieces[i], buf);
+VALIDATESAVEBUF(size)
+}
+
+void CSetPiece::Update(void)
+{
+ if (m_nLastTimeCreated != 0 && CTimer::GetTimeInMilliseconds() <= m_nLastTimeCreated + TIME_BETWEEN_SETPIECE_SPAWNS)
+ return;
+ CVector pos = FindPlayerCoors();
+ if (pos.x < m_vTriggerInf.x || pos.x > m_vTriggerSup.x ||
+ pos.y < m_vTriggerInf.y || pos.y > m_vTriggerSup.y)
+ return;
+ switch (m_nType) {
+ case SETPIECE_TWOCOPCARSINALLEY:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())
+ return;
+ CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);
+ if (!pVehicle1)
+ return;
+ CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);
+ if (!pVehicle2) {
+ CWorld::Remove(pVehicle1);
+ delete pVehicle1;
+ return;
+ }
+ pVehicle1->SetStatus(STATUS_PHYSICS);
+ pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 4;
+ pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;
+ pVehicle1->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1;
+ pVehicle1->AutoPilot.m_vecDestinationCoors.x = m_vTarget1.x;
+ pVehicle1->AutoPilot.m_vecDestinationCoors.y = m_vTarget1.y;
+ pVehicle1->AutoPilot.m_vecDestinationCoors.z = 0.0f;
+ pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000;
+ CCarAI::AddPoliceCarOccupants(pVehicle1);
+ pVehicle2->SetStatus(STATUS_PHYSICS);
+ pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 4;
+ pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;
+ pVehicle2->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1;
+ pVehicle2->AutoPilot.m_vecDestinationCoors.x = m_vTarget2.x;
+ pVehicle2->AutoPilot.m_vecDestinationCoors.y = m_vTarget2.y;
+ pVehicle2->AutoPilot.m_vecDestinationCoors.z = 0.0f;
+ pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000;
+ CCarAI::AddPoliceCarOccupants(pVehicle2);
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ break;
+ }
+ case SETPIECE_CARBLOCKINGPLAYERFROMSIDE:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)
+ return;
+ if (!FindPlayerVehicle())
+ return;
+ if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)
+ return;
+ CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);
+ if (!pVehicle1)
+ return;
+ pVehicle1->SetStatus(STATUS_PHYSICS);
+ pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;
+ pVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;
+ pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle1);
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ case SETPIECE_CARRAMMINGPLAYERFROMSIDE:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)
+ return;
+ if (!FindPlayerVehicle())
+ return;
+ if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)
+ return;
+ CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);
+ if (!pVehicle1)
+ return;
+ pVehicle1->SetStatus(STATUS_PHYSICS);
+ pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ pVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;
+ pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle1);
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ case SETPIECE_CREATECOPPERONFOOT:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())
+ return;
+ CCopPed* pCop = TryToGenerateCopPed(m_vSpawn1);
+ if (!pCop)
+ return;
+ float z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y);
+ pCop->bScriptObjectiveCompleted = false;
+ pCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z));
+ pCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ case SETPIECE_CREATETWOCOPPERSONFOOT:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())
+ return;
+ CCopPed* pCop = TryToGenerateCopPed(m_vSpawn1);
+ if (!pCop)
+ return;
+ float z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y);
+ pCop->bScriptObjectiveCompleted = false;
+ pCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z));
+ pCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ CCopPed* pCop2 = TryToGenerateCopPed(m_vSpawn2);
+ if (!pCop2) {
+ CWorld::Remove(pCop);
+ delete pCop;
+ return;
+ }
+ z = CWorld::FindGroundZForCoord(m_vTarget2.x, m_vTarget2.y);
+ pCop2->bScriptObjectiveCompleted = false;
+ pCop2->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget2.x, m_vTarget2.y, z));
+ pCop2->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ case SETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)
+ return;
+ if (!FindPlayerVehicle())
+ return;
+ if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)
+ return;
+ CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);
+ if (!pVehicle1)
+ return;
+ pVehicle1->SetStatus(STATUS_PHYSICS);
+ pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;
+ pVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;
+ pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle1);
+ CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);
+ if (!pVehicle2) {
+ CWorld::Remove(pVehicle1);
+ delete pVehicle1;
+ return;
+ }
+ pVehicle2->SetStatus(STATUS_PHYSICS);
+ pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;
+ pVehicle2->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;
+ pVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle2);
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ case SETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE:
+ {
+ if (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)
+ return;
+ if (!FindPlayerVehicle())
+ return;
+ if (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)
+ return;
+ CVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);
+ if (!pVehicle1)
+ return;
+ pVehicle1->SetStatus(STATUS_PHYSICS);
+ pVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ pVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;
+ pVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle1);
+ CVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);
+ if (!pVehicle2) {
+ CWorld::Remove(pVehicle1);
+ delete pVehicle1;
+ return;
+ }
+ pVehicle2->SetStatus(STATUS_PHYSICS);
+ pVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 16;
+ pVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ pVehicle2->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;
+ pVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
+ pVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;
+ pVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;
+ pVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f);
+ CCarAI::AddPoliceCarOccupants(pVehicle2);
+ m_nLastTimeCreated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ }
+}
+
+CVehicle* CSetPiece::TryToGenerateCopCar(CVector2D vSpawn, CVector2D vTarget)
+{
+ CVehicle* pVehicle = new CAutomobile(MI_POLICE, RANDOM_VEHICLE);
+ CVector pos(vSpawn.x, vSpawn.y, 1000.0f);
+ CColPoint point;
+ CEntity* pEntity;
+ if (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil))
+ pos.z = point.point.z + pVehicle->GetHeightAboveRoad();
+ CVector vDirection(vTarget.x - vSpawn.x, vTarget.y - vSpawn.y, 0.0f);
+ vDirection.Normalise();
+ pVehicle->GetForward() = CVector(vDirection.x, vDirection.y, 0.0f);
+ pVehicle->GetRight() = CVector(vDirection.y, -vDirection.x, 0.0f);
+ pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ pVehicle->SetPosition(pos);
+ int16 total;
+ CWorld::FindObjectsKindaColliding(pos, pVehicle->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false);
+ if (total != 0) {
+ delete pVehicle;
+ return nil;
+ }
+ pVehicle->ChangeLawEnforcerState(true);
+ CWorld::Add(pVehicle);
+ return pVehicle;
+}
+
+CCopPed* CSetPiece::TryToGenerateCopPed(CVector2D vSpawn)
+{
+ CCopPed* pCop = new CCopPed(COP_STREET);
+ CVector pos(vSpawn.x, vSpawn.y, 1000.0f);
+ CColPoint point;
+ CEntity* pEntity;
+ if (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil))
+ pos.z = point.point.z + 0.9f;
+ pCop->SetPosition(pos);
+ int16 total;
+ CWorld::FindObjectsKindaColliding(pos, pCop->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false);
+ if (total != 0) {
+ delete pCop;
+ return nil;
+ }
+ CWorld::Add(pCop);
+ return pCop;
+} \ No newline at end of file
diff --git a/src/control/SetPieces.h b/src/control/SetPieces.h
new file mode 100644
index 00000000..5c228d4c
--- /dev/null
+++ b/src/control/SetPieces.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "config.h"
+
+class CVehicle;
+class CCopPed;
+
+enum eSetPieceType
+{
+ SETPIECE_NONE = 0,
+ SETPIECE_TWOCOPCARSINALLEY,
+ SETPIECE_CARBLOCKINGPLAYERFROMSIDE,
+ SETPIECE_CARRAMMINGPLAYERFROMSIDE,
+ SETPIECE_CREATECOPPERONFOOT,
+ SETPIECE_CREATETWOCOPPERSONFOOT,
+ SETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE,
+ SETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE
+};
+
+class CSetPiece
+{
+public:
+ uint8 m_nType;
+ uint32 m_nLastTimeCreated;
+ CVector2D m_vTriggerInf;
+ CVector2D m_vTriggerSup;
+ CVector2D m_vSpawn1;
+ CVector2D m_vSpawn2;
+ CVector2D m_vTarget1;
+ CVector2D m_vTarget2;
+
+ CVehicle* TryToGenerateCopCar(CVector2D, CVector2D);
+ CCopPed* TryToGenerateCopPed(CVector2D);
+ void Update(void);
+};
+
+class CSetPieces
+{
+ static bool bDebug;
+ static uint32 NumSetPieces;
+ static CSetPiece aSetPieces[NUM_SETPIECES];
+public:
+ static void Init(void);
+ static void AddOne(uint8 type, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D);
+ static void Save(uint8*, uint32*);
+ static void Load(uint8*, uint32);
+ static void Update(void);
+};
diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp
index 278366a3..e484d3be 100644
--- a/src/control/TrafficLights.cpp
+++ b/src/control/TrafficLights.cpp
@@ -15,8 +15,7 @@
#include "Weather.h"
#include "World.h"
-// TODO: figure out the meaning of this
-enum { SOME_FLAG = 0x80 };
+bool CTrafficLights::bGreenLightsCheat;
void
CTrafficLights::DisplayActualLight(CEntity *ent)
@@ -26,113 +25,288 @@ CTrafficLights::DisplayActualLight(CEntity *ent)
int phase;
if(FindTrafficLightType(ent) == 1)
- phase = LightForCars1();
+ phase = LightForCars1_Visual();
else
- phase = LightForCars2();
-
- int i;
- CBaseModelInfo *mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
- float x = mi->Get2dEffect(0)->pos.x;
- float yMin = mi->Get2dEffect(0)->pos.y;
- float yMax = mi->Get2dEffect(0)->pos.y;
- float zMin = mi->Get2dEffect(0)->pos.z;
- float zMax = mi->Get2dEffect(0)->pos.z;
- for(i = 1; i < 6; i++){
- assert(mi->Get2dEffect(i));
- yMin = Min(yMin, mi->Get2dEffect(i)->pos.y);
- yMax = Max(yMax, mi->Get2dEffect(i)->pos.y);
- zMin = Min(zMin, mi->Get2dEffect(i)->pos.z);
- zMax = Max(zMax, mi->Get2dEffect(i)->pos.z);
+ phase = LightForCars2_Visual();
+
+ int i, m = ent->GetModelIndex();
+ if (MI_TRAFFICLIGHTS == m) {
+ CBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
+ float x = mi->Get2dEffect(0)->pos.x;
+ float yMin = mi->Get2dEffect(0)->pos.y;
+ float yMax = mi->Get2dEffect(0)->pos.y;
+ float zMin = mi->Get2dEffect(0)->pos.z;
+ float zMax = mi->Get2dEffect(0)->pos.z;
+ for (i = 1; i < 6; i++) {
+ assert(mi->Get2dEffect(i));
+ yMin = Min(yMin, mi->Get2dEffect(i)->pos.y);
+ yMax = Max(yMax, mi->Get2dEffect(i)->pos.y);
+ zMin = Min(zMin, mi->Get2dEffect(i)->pos.z);
+ zMax = Max(zMax, mi->Get2dEffect(i)->pos.z);
+ }
+
+ CVector pos1, pos2;
+ uint8 r, g;
+ int id;
+ switch (phase) {
+ case CAR_LIGHTS_GREEN:
+ r = 0;
+ g = 255;
+ pos1 = ent->GetMatrix() * CVector(x, yMax, zMin);
+ pos2 = ent->GetMatrix() * CVector(x, yMin, zMin);
+ id = 0;
+ break;
+ case CAR_LIGHTS_YELLOW:
+ r = 255;
+ g = 128;
+ pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin + zMax) / 2.0f);
+ pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin + zMax) / 2.0f);
+ id = 1;
+ break;
+ case CAR_LIGHTS_RED:
+ r = 255;
+ g = 0;
+ pos1 = ent->GetMatrix() * CVector(x, yMax, zMax);
+ pos2 = ent->GetMatrix() * CVector(x, yMin, zMax);
+ id = 2;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin + zMax) / 2.0f);
+ pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin + zMax) / 2.0f);
+ id = -1;
+ break;
+ }
+
+ if (CWeather::TrafficLightBrightness > 0.5f)
+ CPointLights::AddLight(CPointLights::LIGHT_POINT,
+ pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
+ r / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);
+
+ if (CWeather::TrafficLightBrightness > 0.05f)
+ CShadows::StoreStaticShadow((uintptr)ent,
+ SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
+ 8.0f, 0.0f, 0.0f, -8.0f, 128,
+ r * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ g * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 12.0f, 1.0f, 40.0f, false, 0.0f);
+
+ if (DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
+ CCoronas::RegisterCorona((uintptr)ent + id,
+ r * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ g * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 0 * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 255,
+ pos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ else
+ CCoronas::RegisterCorona((uintptr)ent + id + 3,
+ r * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ g * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 0 * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 255,
+ pos2, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+
+ CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
+ CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
}
+ else if (MI_TRAFFICLIGHTS_VERTICAL == m) {
+ CBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
+ float x = mi->Get2dEffect(0)->pos.x;
+ float yMin = mi->Get2dEffect(0)->pos.y;
+ float yMax = mi->Get2dEffect(0)->pos.y;
+ float zMin = mi->Get2dEffect(0)->pos.z;
+ float zMax = mi->Get2dEffect(0)->pos.z;
+ for (i = 1; i < 6; i++) {
+ assert(mi->Get2dEffect(i));
+ yMin = Min(yMin, mi->Get2dEffect(i)->pos.y);
+ yMax = Max(yMax, mi->Get2dEffect(i)->pos.y);
+ zMin = Min(zMin, mi->Get2dEffect(i)->pos.z);
+ zMax = Max(zMax, mi->Get2dEffect(i)->pos.z);
+ }
+
+ CVector pos1;
+ uint8 r, g;
+ int id;
+ switch (phase) {
+ case CAR_LIGHTS_GREEN:
+ r = 0;
+ g = 255;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;
+ id = 0;
+ break;
+ case CAR_LIGHTS_YELLOW:
+ r = 255;
+ g = 128;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;
+ id = 1;
+ break;
+ case CAR_LIGHTS_RED:
+ r = 255;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;
+ id = 2;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;
+ id = -1;
+ break;
+ }
+
+ CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
- CVector pos1, pos2;
- uint8 r, g;
- int id;
- switch(phase){
- case CAR_LIGHTS_GREEN:
- r = 0;
- g = 255;
- pos1 = ent->GetMatrix() * CVector(x, yMax, zMin);
- pos2 = ent->GetMatrix() * CVector(x, yMin, zMin);
- id = 0;
- break;
- case CAR_LIGHTS_YELLOW:
- r = 255;
- g = 128;
- pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin+zMax)/2.0f);
- pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin+zMax)/2.0f);
- id = 1;
- break;
- case CAR_LIGHTS_RED:
- default:
- r = 255;
- g = 0;
- pos1 = ent->GetMatrix() * CVector(x, yMax, zMax);
- pos2 = ent->GetMatrix() * CVector(x, yMin, zMax);
- id = 2;
- break;
+ if (CWeather::TrafficLightBrightness > 0.5f)
+ CPointLights::AddLight(CPointLights::LIGHT_POINT,
+ pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
+ r / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);
+
+ if (CWeather::TrafficLightBrightness > 0.05f)
+ CShadows::StoreStaticShadow((uintptr)ent,
+ SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
+ 8.0f, 0.0f, 0.0f, -8.0f, 128,
+ r * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ g * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 12.0f, 1.0f, 40.0f, false, 0.0f);
+
+ if (DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
+ CCoronas::RegisterCorona((uintptr)ent + id,
+ r * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ g * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 0 * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 255,
+ pos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
}
+ else if (MI_TRAFFICLIGHTS_MIAMI == m || MI_TRAFFICLIGHTS_TWOVERTICAL == m) {
+ CBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
+ CVector pos1, pos2;
+ uint8 r, g;
+ int id;
+ if (MI_TRAFFICLIGHTS_MIAMI == m) {
+ switch (phase) {
+ case CAR_LIGHTS_GREEN:
+ r = 0;
+ g = 255;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(5)->pos;
+ id = 0;
+ break;
+ case CAR_LIGHTS_YELLOW:
+ r = 255;
+ g = 128;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;
+ id = 1;
+ break;
+ case CAR_LIGHTS_RED:
+ r = 255;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;
+ id = 2;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;
+ id = -1;
+ break;
+ }
+ }
+ else {
+ switch (phase) {
+ case CAR_LIGHTS_GREEN:
+ r = 0;
+ g = 255;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(5)->pos;
+ id = 0;
+ break;
+ case CAR_LIGHTS_YELLOW:
+ r = 255;
+ g = 128;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;
+ id = 1;
+ break;
+ case CAR_LIGHTS_RED:
+ r = 255;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;
+ id = 2;
+ break;
+ default:
+ r = 0;
+ g = 0;
+ pos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;
+ pos2 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;
+ id = -1;
+ break;
+ }
+ }
- if(CClock::GetHours() > 19 || CClock::GetHours() < 6 || CWeather::Foggyness > 0.05f)
- CPointLights::AddLight(CPointLights::LIGHT_POINT,
- pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
- r/255.0f, g/255.0f, 0/255.0f, CPointLights::FOG_NORMAL, true);
-
- CShadows::StoreStaticShadow((uintptr)ent,
- SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
- 8.0f, 0.0f, 0.0f, -8.0f, 128,
- r*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
- g*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
- 0*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
- 12.0f, 1.0f, 40.0f, false, 0.0f);
-
- if(DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
- CCoronas::RegisterCorona((uintptr)ent + id,
- r*CTimeCycle::GetSpriteBrightness()*0.7f,
- g*CTimeCycle::GetSpriteBrightness()*0.7f,
- 0*CTimeCycle::GetSpriteBrightness()*0.7f,
- 255,
- pos1, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- else
- CCoronas::RegisterCorona((uintptr)ent + id + 3,
- r*CTimeCycle::GetSpriteBrightness()*0.7f,
- g*CTimeCycle::GetSpriteBrightness()*0.7f,
- 0*CTimeCycle::GetSpriteBrightness()*0.7f,
- 255,
- pos2, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
-
- CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
- CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
-
- static const float top = -0.127f;
- static const float bot = -0.539f;
- static const float mid = bot + (top-bot)/3.0f;
- static const float left = 1.256f;
- static const float right = 0.706f;
- phase = CTrafficLights::LightForPeds();
- if(phase == PED_LIGHTS_DONT_WALK){
- CVector p0(2.7f, right, top);
- CVector p1(2.7f, left, top);
- CVector p2(2.7f, right, mid);
- CVector p3(2.7f, left, mid);
- CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
- 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
- SHINYTEXT_WALK, 255, 0, 0, 60.0f);
- }else if(phase == PED_LIGHTS_WALK || CTimer::GetTimeInMilliseconds() & 0x100){
- CVector p0(2.7f, right, mid);
- CVector p1(2.7f, left, mid);
- CVector p2(2.7f, right, bot);
- CVector p3(2.7f, left, bot);
- CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
- 1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
- SHINYTEXT_WALK, 255, 255, 255, 60.0f);
+ CVector pos = (pos1 + pos2) / 2;
+ if (id >= 0) {
+ CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
+ CBrightLights::RegisterOne(pos2, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
+ }
+
+ if (CWeather::TrafficLightBrightness > 0.5f)
+ CPointLights::AddLight(CPointLights::LIGHT_POINT,
+ pos, CVector(0.0f, 0.0f, 0.0f), 8.0f,
+ r / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);
+
+ if (CWeather::TrafficLightBrightness > 0.05f)
+ CShadows::StoreStaticShadow((uintptr)ent,
+ SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 8.0f, 0.0f, 0.0f, -8.0f, 128,
+ r * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ g * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,
+ 12.0f, 1.0f, 40.0f, false, 0.0f);
+
+ if (id >= 0) {
+ if (DotProduct(TheCamera.GetForward(), ent->GetForward()) > 0.0f)
+ CCoronas::RegisterCorona((uintptr)ent + id,
+ r * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ g * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 0 * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 255,
+ pos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ else
+ CCoronas::RegisterCorona((uintptr)ent + id,
+ r * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ g * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 0 * CTimeCycle::GetSpriteBrightness() * 0.7f,
+ 255,
+ pos2, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
+ CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
}
}
+bool DoesLineSegmentIntersect(float l1x1, float l1y1, float l1x2, float l1y2, float l2x1, float l2y1, float l2x2, float l2y2)
+{
+ return ((l2y2 - l1y1) * (l1x2 - l1x1) + (l1x1 - l2x2) * (l1y2 - l1y1)) *
+ ((l2y1 - l1y1) * (l1x2 - l1x1) + (l1x1 - l2x1) * (l1y2 - l1y1)) <= 0.0f &&
+ ((l1y2 - l2y1) * (l2x2 - l2x1) + (l2y2 - l2y1) * (l2x1 - l1x2)) *
+ ((l1y1 - l2y1) * (l2x2 - l2x1) + (l2y2 - l2y1) * (l2x1 - l1x1)) <= 0.0f;
+}
+
void
CTrafficLights::ScanForLightsOnMap(void)
{
@@ -145,36 +319,31 @@ CTrafficLights::ScanForLightsOnMap(void)
CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];
for(node = list.first; node; node = node->next){
CEntity *light = (CEntity*)node->item;
- if(light->GetModelIndex() != MI_TRAFFICLIGHTS)
+ if (!IsTrafficLight(light->GetModelIndex()))
continue;
+ CVector pos1 = light->GetMatrix() * CVector(17.0f, 0.0f, 0.0f);
+ CVector pos2 = light->GetMatrix() * CVector(-15.0f, 0.0f, 0.0f);
+
// Check cars
- for(i = 0; i < ThePaths.m_numCarPathLinks; i++){
- CVector2D dist = ThePaths.m_carPathLinks[i].GetPosition() - light->GetPosition();
- float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light
- float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light
- // it has to be on the correct side of the node and also not very far away
- if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){
- float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].GetZ() -
- light->GetPosition().z;
- if(dz < 15.0f){
- ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light);
- // Find two neighbour nodes of this one
- int n1 = -1;
- int n2 = -1;
- for(j = 0; j < ThePaths.m_numPathNodes; j++)
- for(l = 0; l < ThePaths.m_pathNodes[j].numLinks; l++)
- if(ThePaths.m_carPathConnections[ThePaths.m_pathNodes[j].firstLink + l] == i){
- if(n1 == -1)
- n1 = j;
- else
- n2 = j;
- }
- // What's going on here?
- if(ThePaths.m_pathNodes[n1].numLinks <= ThePaths.m_pathNodes[n2].numLinks)
- n1 = n2;
- if(ThePaths.m_carPathLinks[i].pathNodeIndex != n1)
- ThePaths.m_carPathLinks[i].trafficLightType |= SOME_FLAG;
+ for(i = 0; i < ThePaths.m_numCarPathNodes; i++){
+ if ((ThePaths.m_pathNodes[i].GetPosition() - pos1).MagnitudeSqr() >= SQR(100.0f))
+ continue;
+ for (j = 0; j < ThePaths.m_pathNodes[i].numLinks; j++){
+ int con = ThePaths.ConnectedNode(ThePaths.m_pathNodes[i].firstLink + j);
+ if (i < con) {
+ CVector i_pos = ThePaths.m_pathNodes[i].GetPosition();
+ CVector con_pos = ThePaths.m_pathNodes[con].GetPosition();
+ if (Abs(pos1.z - (i_pos.z + con_pos.z) / 2) < 10.0f &&
+ DoesLineSegmentIntersect(pos1.x, pos1.y, pos2.x, pos2.y, i_pos.x, i_pos.y, con_pos.x, con_pos.y)) {
+ //debug("Setting up light: nodes %f %f %f - %f %f %f, light %f %f %f - %f %f %f\n", i_pos.x, i_pos.y, i_pos.z, con_pos.x, con_pos.y, con_pos.z, pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z);
+ int link = ThePaths.m_carPathConnections[ThePaths.m_pathNodes[i].firstLink + j];
+ ThePaths.m_carPathLinks[link].trafficLightType = FindTrafficLightType(light);
+ if (ThePaths.m_pathNodes[i].numLinks > ThePaths.m_pathNodes[con].numLinks)
+ con = i;
+ if (ThePaths.m_carPathLinks[link].pathNodeIndex != con)
+ ThePaths.m_carPathLinks[link].trafficLightDirection = true;
+ }
}
}
}
@@ -205,15 +374,18 @@ bool
CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
{
int node, type;
+ bool direction;
node = vehicle->AutoPilot.m_nNextPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
+ direction = ThePaths.m_carPathLinks[node].trafficLightDirection;
+
if(type){
- if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&
- (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))
+ if((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&
+ (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))
if(alwaysStop ||
- (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
- (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
+ type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
+ type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nNextDirection == -1){
@@ -228,12 +400,13 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
node = vehicle->AutoPilot.m_nCurrentPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
+ direction = ThePaths.m_carPathLinks[node].trafficLightDirection;
if(type){
- if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&
- (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))
+ if((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&
+ (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))
if(alwaysStop ||
- (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
- (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
+ type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
+ type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nCurrentDirection == -1){
@@ -249,12 +422,13 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
if(vehicle->GetStatus() == STATUS_PHYSICS){
node = vehicle->AutoPilot.m_nPreviousPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
+ direction = ThePaths.m_carPathLinks[node].trafficLightDirection;
if(type){
- if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&
- (!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))
+ if((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&
+ (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))
if(alwaysStop ||
- (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
- (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
+ type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
+ type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nPreviousDirection == -1){
@@ -274,8 +448,12 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
bool
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
{
+#ifdef GTA_BRIDGE
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
+#else
+ return false;
+#endif
}
int
@@ -304,6 +482,12 @@ CTrafficLights::LightForPeds(void)
uint8
CTrafficLights::LightForCars1(void)
{
+ if (CWeather::Wind > 1.1f)
+ return CAR_LIGHTS_GREEN;
+
+ if (bGreenLightsCheat)
+ return CAR_LIGHTS_GREEN;
+
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 5000)
@@ -317,6 +501,12 @@ CTrafficLights::LightForCars1(void)
uint8
CTrafficLights::LightForCars2(void)
{
+ if (CWeather::Wind > 1.1f)
+ return CAR_LIGHTS_GREEN;
+
+ if (bGreenLightsCheat)
+ return CAR_LIGHTS_GREEN;
+
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 6000)
@@ -328,3 +518,19 @@ CTrafficLights::LightForCars2(void)
else
return CAR_LIGHTS_RED;
}
+
+uint8
+CTrafficLights::LightForCars1_Visual(void)
+{
+ if (CWeather::Wind <= 1.1f)
+ return LightForCars1();
+ return (CTimer::GetTimeInMilliseconds() & 0x400 ? CAR_LIGHTS_NONE : CAR_LIGHTS_YELLOW);
+}
+
+uint8
+CTrafficLights::LightForCars2_Visual(void)
+{
+ if (CWeather::Wind <= 1.1f)
+ return LightForCars2();
+ return (CTimer::GetTimeInMilliseconds() & 0x400 ? CAR_LIGHTS_NONE : CAR_LIGHTS_YELLOW);
+}
diff --git a/src/control/TrafficLights.h b/src/control/TrafficLights.h
index f3df6cd5..8dba45e1 100644
--- a/src/control/TrafficLights.h
+++ b/src/control/TrafficLights.h
@@ -10,18 +10,23 @@ enum {
CAR_LIGHTS_GREEN = 0,
CAR_LIGHTS_YELLOW,
- CAR_LIGHTS_RED
+ CAR_LIGHTS_RED,
+ CAR_LIGHTS_NONE
};
class CTrafficLights
{
public:
+ static bool bGreenLightsCheat;
+
static void DisplayActualLight(CEntity *ent);
static void ScanForLightsOnMap(void);
static int FindTrafficLightType(CEntity *light);
static uint8 LightForPeds(void);
static uint8 LightForCars1(void);
static uint8 LightForCars2(void);
+ static uint8 LightForCars1_Visual(void);
+ static uint8 LightForCars2_Visual(void);
static bool ShouldCarStopForLight(CVehicle*, bool);
static bool ShouldCarStopForBridge(CVehicle*);
};