script revision #561

Merged
Nick007J merged 2 commits from miami into miami 5 years ago

@ -54,6 +54,7 @@
#include "Remote.h" #include "Remote.h"
#include "Replay.h" #include "Replay.h"
#include "Restart.h" #include "Restart.h"
#include "RoadBlocks.h"
#include "RpAnimBlend.h" #include "RpAnimBlend.h"
#include "Rubbish.h" #include "Rubbish.h"
#include "Shadows.h" #include "Shadows.h"
@ -92,13 +93,10 @@
uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE]; uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE];
CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS]; 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_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
tCollectiveData CTheScripts::CollectiveArray[MAX_NUM_COLLECTIVES];
tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS]; tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS];
int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@ -119,8 +117,6 @@ uint16 CTheScripts::NumberOfMissionScripts;
uint32 CTheScripts::LargestMissionScriptSize; uint32 CTheScripts::LargestMissionScriptSize;
uint32 CTheScripts::MainScriptSize; uint32 CTheScripts::MainScriptSize;
uint8 CTheScripts::FailCurrentMission; uint8 CTheScripts::FailCurrentMission;
uint8 CTheScripts::CountdownToMakePlayerUnsafe;
uint8 CTheScripts::DelayMakingPlayerUnsafeThisTime;
uint16 CTheScripts::NumScriptDebugLines; uint16 CTheScripts::NumScriptDebugLines;
uint16 CTheScripts::NumberOfIntroRectanglesThisFrame; uint16 CTheScripts::NumberOfIntroRectanglesThisFrame;
uint16 CTheScripts::NumberOfIntroTextLinesThisFrame; uint16 CTheScripts::NumberOfIntroTextLinesThisFrame;
@ -131,6 +127,11 @@ CStuckCarCheck CTheScripts::StuckCars;
uint16 CTheScripts::CommandsExecuted; uint16 CTheScripts::CommandsExecuted;
uint16 CTheScripts::ScriptsUpdated; uint16 CTheScripts::ScriptsUpdated;
int32 ScriptParams[32]; int32 ScriptParams[32];
uint8 CTheScripts::RiotIntensity;
uint32 CTheScripts::LastMissionPassedTime;
uint16 CTheScripts::NumberOfExclusiveMissionScripts;
bool CTheScripts::bPlayerHasMetDebbieHarry;
bool CTheScripts::bPlayerIsInTheStatium;
const uint32 CRunningScript::nSaveStructSize = const uint32 CRunningScript::nSaveStructSize =
@ -272,9 +273,19 @@ void CMissionCleanup::Process()
CPopulation::m_AllRandomPedsThisType = -1; CPopulation::m_AllRandomPedsThisType = -1;
CPopulation::PedDensityMultiplier = 1.0f; CPopulation::PedDensityMultiplier = 1.0f;
CCarCtrl::CarDensityMultiplier = 1.0f; CCarCtrl::CarDensityMultiplier = 1.0f;
CPed::nThreatReactionRangeMultiplier = 1;
CPed::nEnterCarRangeMultiplier = 1;
FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f;
//CRoadBlocks::ClearScriptRoadblocks() // TODO(MIAMI)
CRouteNode::Initialise();
if (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
TheCamera.Restore(); TheCamera.Restore();
TheCamera.SetWideScreenOff(); TheCamera.SetWideScreenOff();
// TODO(MIAMI)
//CSpecialFX::bLiftCam = false;
//CSpecialFX::bVideoCam = false;
//CTimeCycle::StopExtraColour(0);
// TODO(MIAMI): change this to loop when it supports parameters
DMAudio.ClearMissionAudio(); DMAudio.ClearMissionAudio();
CWeather::ReleaseWeather(); CWeather::ReleaseWeather();
for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++) for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++)
@ -283,14 +294,18 @@ void CMissionCleanup::Process()
CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i); CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i);
CStreaming::ms_disableStreaming = false; CStreaming::ms_disableStreaming = false;
CHud::m_ItemToFlash = -1; CHud::m_ItemToFlash = -1;
CHud::SetHelpMessage(nil, false); CHud::SetHelpMessage(nil, false); // TODO(MIAMI): third parameter is false
CUserDisplay::OnscnTimer.m_bDisabled = 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_bIgnoredByCops = false;
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false; CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CWorld::Players[0].MakePlayerSafe(false); CWorld::Players[0].MakePlayerSafe(false);
//TODO(MIAMI): drunkenness, enable drive by
//DMAudio::ShutUpPlayerTalking(0);
CVehicle::bDisableRemoteDetonation = false; CVehicle::bDisableRemoteDetonation = false;
//CVehicle::bDisableRemoteDetonationOnContact = false; // TODO(MIAMI)
//CGameLogic::ClearShortCut(); // TODO(MIAMI)
CTheScripts::RiotIntensity = 0;
CTheScripts::StoreVehicleIndex = -1; CTheScripts::StoreVehicleIndex = -1;
CTheScripts::StoreVehicleWasRandom = true; CTheScripts::StoreVehicleWasRandom = true;
CTheScripts::UpsideDownCars.Init(); CTheScripts::UpsideDownCars.Init();
@ -513,7 +528,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip) int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
{ {
uint32* pIp = &ip; uint32* pIp = &ip;
float tmp;
switch (CTheScripts::Read1ByteFromScript(pIp)) switch (CTheScripts::Read1ByteFromScript(pIp))
{ {
case ARGUMENT_INT32: case ARGUMENT_INT32:
@ -527,8 +541,7 @@ int32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)
case ARGUMENT_INT16: case ARGUMENT_INT16:
return CTheScripts::Read2BytesFromScript(pIp); return CTheScripts::Read2BytesFromScript(pIp);
case ARGUMENT_FLOAT: case ARGUMENT_FLOAT:
tmp = CTheScripts::ReadFloatFromScript(pIp); return CTheScripts::Read4BytesFromScript(pIp);
return *(int32*)&tmp;
default: default:
assert(0); assert(0);
} }
@ -637,14 +650,7 @@ void CTheScripts::Init()
StoreVehicleIndex = -1; StoreVehicleIndex = -1;
StoreVehicleWasRandom = true; StoreVehicleWasRandom = true;
OnAMissionFlag = 0; OnAMissionFlag = 0;
for (int i = 0; i < MAX_NUM_CONTACTS; i++){ LastMissionPassedTime = (uint32)-1;
BaseBriefIdForContact[i] = 0;
OnAMissionForContactFlag[i] = 0;
}
for (int i = 0; i < MAX_NUM_COLLECTIVES; i++){
CollectiveArray[i].index = -1;
CollectiveArray[i].unk_data = 0;
}
NextFreeCollectiveIndex = 0; NextFreeCollectiveIndex = 0;
LastRandomPedId = -1; LastRandomPedId = -1;
for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){ for (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){
@ -658,15 +664,17 @@ void CTheScripts::Init()
bUsingAMultiScriptFile = true; bUsingAMultiScriptFile = true;
for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++) for (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++)
MultiScriptArray[i] = 0; MultiScriptArray[i] = 0;
NumberOfExclusiveMissionScripts = 0;
NumberOfMissionScripts = 0; NumberOfMissionScripts = 0;
LargestMissionScriptSize = 0; LargestMissionScriptSize = 0;
MainScriptSize = 0; MainScriptSize = 0;
ReadMultiScriptFileOffsetsFromScript(); ReadMultiScriptFileOffsetsFromScript();
FailCurrentMission = 0; FailCurrentMission = 0;
CountdownToMakePlayerUnsafe = 0;
DbgFlag = false; DbgFlag = false;
DelayMakingPlayerUnsafeThisTime = 1;
NumScriptDebugLines = 0; NumScriptDebugLines = 0;
RiotIntensity = 0;
bPlayerHasMetDebbieHarry = false;
bPlayerIsInTheStatium = false;
for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){ for (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){
ScriptSphereArray[i].m_bInUse = false; ScriptSphereArray[i].m_bInUse = false;
ScriptSphereArray[i].m_Index = 1; ScriptSphereArray[i].m_Index = 1;
@ -687,6 +695,7 @@ void CTheScripts::Init()
IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255); IntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255);
} }
NumberOfIntroRectanglesThisFrame = 0; NumberOfIntroRectanglesThisFrame = 0;
RemoveScriptTextureDictionary();
for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){ for (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){
BuildingSwapArray[i].m_pBuilding = nil; BuildingSwapArray[i].m_pBuilding = nil;
BuildingSwapArray[i].m_nNewModel = -1; BuildingSwapArray[i].m_nNewModel = -1;
@ -696,6 +705,15 @@ void CTheScripts::Init()
InvisibilitySettingArray[i] = nil; InvisibilitySettingArray[i] = nil;
} }
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) void CRunningScript::RemoveScriptFromList(CRunningScript** ppScript)
{ {
if (prev) if (prev)
@ -739,10 +757,6 @@ void CTheScripts::Process()
DrawScriptSpheres(); DrawScriptSpheres();
if (FailCurrentMission) if (FailCurrentMission)
--FailCurrentMission; --FailCurrentMission;
if (CountdownToMakePlayerUnsafe){
if (--CountdownToMakePlayerUnsafe == 0)
CWorld::Players[0].MakePlayerSafe(false);
}
if (UseTextCommands){ if (UseTextCommands){
for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++) for (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++)
IntroTextLines[i].Reset(); IntroTextLines[i].Reset();
@ -849,6 +863,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
case COMMAND_WAIT: case COMMAND_WAIT:
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0]; m_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];
m_bSkipWakeTime = false;
return 1; return 1;
case COMMAND_GOTO: case COMMAND_GOTO:
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
@ -1262,13 +1277,11 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*ptr1 == *ptr2); UpdateCompareFlag(*ptr1 == *ptr2);
return 0; 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_VAR_NOT_EQUAL_TO_NUMBER: //case COMMAND_IS_INT_LVAR_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_VAR_NOT_EQUAL_TO_INT_VAR: //case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:
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_INT_LVAR:
*/
case COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER: case COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER:
{ {
int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
@ -1304,19 +1317,18 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
UpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2); UpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);
return 0; 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_VAR_NOT_EQUAL_TO_NUMBER: //case COMMAND_IS_FLOAT_LVAR_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_VAR_NOT_EQUAL_TO_FLOAT_VAR: //case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:
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_FLOAT_LVAR: /*
*/
case COMMAND_GOTO_IF_TRUE: case COMMAND_GOTO_IF_TRUE:
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
if (m_bCondResult) if (m_bCondResult)
SetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]); SetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);
/* Check COMMAND_GOTO note. */
return 0; return 0;
*/
case COMMAND_GOTO_IF_FALSE: case COMMAND_GOTO_IF_FALSE:
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
if (!m_bCondResult) if (!m_bCondResult)
@ -1328,12 +1340,14 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
CTheScripts::bAlreadyRunningAMissionScript = false; CTheScripts::bAlreadyRunningAMissionScript = false;
RemoveScriptFromList(&CTheScripts::pActiveScripts); RemoveScriptFromList(&CTheScripts::pActiveScripts);
AddScriptToList(&CTheScripts::pIdleScripts); AddScriptToList(&CTheScripts::pIdleScripts);
m_bIsActive = false;
return 1; return 1;
case COMMAND_START_NEW_SCRIPT: case COMMAND_START_NEW_SCRIPT:
{ {
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
assert(ScriptParams[0] >= 0); assert(ScriptParams[0] >= 0);
CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]); CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);
m_bIsActive = true;
int8 type = CTheScripts::Read1ByteFromScript(&m_nIp); int8 type = CTheScripts::Read1ByteFromScript(&m_nIp);
float tmp; float tmp;
for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) { for (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) {
@ -1381,7 +1395,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
{ {
CollectParameters(&m_nIp, 4); CollectParameters(&m_nIp, 4);
int32 index = ScriptParams[0]; int32 index = ScriptParams[0];
assert(index < 1); /* Constant? Also no more double player glitch */ assert(index < NUMPLAYERS);
printf("&&&&&&&&&&&&&Creating player: %d\n", index); printf("&&&&&&&&&&&&&Creating player: %d\n", index);
if (!CStreaming::HasModelLoaded(MI_PLAYER)) { if (!CStreaming::HasModelLoaded(MI_PLAYER)) {
CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY); CStreaming::RequestSpecialModel(MI_PLAYER, "player", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);
@ -1421,20 +1435,49 @@ int8 CRunningScript::ProcessCommands0To99(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT) if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CPlayerPed* ped = CWorld::Players[index].m_pPed; CPlayerPed* ped = CWorld::Players[index].m_pPed;
if (!ped->bInVehicle) { 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->GetDistanceFromCentreOfMassToBaseOfModel(); pos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();
CVector vOldPos = ped->GetPosition();
ped->Teleport(pos); ped->Teleport(pos);
CTheScripts::ClearSpaceForMissionEntity(pos, ped); CTheScripts::ClearSpaceForMissionEntity(pos, ped);
return 0; 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 == OBJ_15) {
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);
} }
pos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); }
if (ped->m_pMyVehicle->IsBoat()) }
ped->m_pMyVehicle->Teleport(pos); else if (pTestedPed->m_leader == ped) {
CVector vFollowerPos;
if (pTestedPed->m_pedFormation)
vFollowerPos = pTestedPed->GetFormationPosition();
else else
ped->m_pMyVehicle->Teleport(pos); vFollowerPos = ped->GetPosition() + pTestedPed->GetPosition() - vOldPos;
/* I'll keep this condition here but obviously it is absolutely pointless */ CTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);
/* It's clearly present in disassembly so it had to be in original code */ bool bFound = false;
CTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle); 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; return 0;
} }
case COMMAND_IS_PLAYER_IN_AREA_2D: case COMMAND_IS_PLAYER_IN_AREA_2D:
@ -3508,14 +3551,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_DECLARE_MISSION_FLAG: case COMMAND_DECLARE_MISSION_FLAG:
CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp); CTheScripts::OnAMissionFlag = CTheScripts::Read2BytesFromScript(&++m_nIp);
return 0; return 0;
case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: //case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:
CollectParameters(&m_nIp, 1); //case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:
CTheScripts::OnAMissionForContactFlag[ScriptParams[0]] = 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_IS_PLAYER_HEALTH_GREATER: case COMMAND_IS_PLAYER_HEALTH_GREATER:
{ {
CollectParameters(&m_nIp, 2); CollectParameters(&m_nIp, 2);
@ -3830,13 +3867,8 @@ int8 CRunningScript::ProcessCommands400To499(int32 command)
CollectParameters(&m_nIp, 2); CollectParameters(&m_nIp, 2);
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
if (ScriptParams[1]){ if (ScriptParams[1]){
if (CGame::playingIntro || CTheScripts::DelayMakingPlayerUnsafeThisTime){
CTheScripts::CountdownToMakePlayerUnsafe = 50;
if (CTheScripts::DelayMakingPlayerUnsafeThisTime)
CTheScripts::DelayMakingPlayerUnsafeThisTime--;
}else{
pPlayer->MakePlayerSafe(false); pPlayer->MakePlayerSafe(false);
} // TODO(MIAMI): Four Iron hack
}else{ }else{
pPlayer->MakePlayerSafe(true); pPlayer->MakePlayerSafe(true);
if (strcmp(m_abScriptName, "camera") == 0){ if (strcmp(m_abScriptName, "camera") == 0){
@ -7720,9 +7752,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
} }
case COMMAND_REMOVE_TEXTURE_DICTIONARY: case COMMAND_REMOVE_TEXTURE_DICTIONARY:
{ {
for (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++) CTheScripts::RemoveScriptTextureDictionary();
CTheScripts::ScriptSprites[i].Delete();
CTxdStore::RemoveTxd(CTxdStore::FindTxdSlot("script"));
return 0; return 0;
} }
case COMMAND_SET_OBJECT_DYNAMIC: case COMMAND_SET_OBJECT_DYNAMIC:
@ -10446,7 +10476,7 @@ int8 CRunningScript::ProcessCommands1300To1399(int32 command)
char key[8]; char key[8];
CTheScripts::ReadTextLabelFromScript(&m_nIp, key); CTheScripts::ReadTextLabelFromScript(&m_nIp, key);
m_nIp += KEY_LENGTH_IN_SCRIPT; m_nIp += KEY_LENGTH_IN_SCRIPT;
debug("skipping LOAD_MISSION_TEXT\n"); TheText.LoadMissionText(key);
return 0; return 0;
} }
case COMMAND_SET_TONIGHTS_EVENT: case COMMAND_SET_TONIGHTS_EVENT:
@ -12133,29 +12163,6 @@ void CRunningScript::DoDeatharrestCheck()
while (m_nStackPointer > 1) while (m_nStackPointer > 1)
--m_nStackPointer; --m_nStackPointer;
m_nIp = m_anStack[--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; *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;
m_bDeatharrestExecuted = true; m_bDeatharrestExecuted = true;
m_nWakeTime = 0; m_nWakeTime = 0;
@ -12299,8 +12306,8 @@ void CTheScripts::RenderTheScriptDebugLines()
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0);
} }
#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\ #define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) +\
sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)
void CTheScripts::SaveAllScripts(uint8* buf, uint32* size) void CTheScripts::SaveAllScripts(uint8* buf, uint32* size)
{ {
@ -12320,12 +12327,6 @@ INITSAVEBUF
uint32 script_data_size = SCRIPT_DATA_SIZE; uint32 script_data_size = SCRIPT_DATA_SIZE;
WriteSaveBuf(buf, script_data_size); WriteSaveBuf(buf, script_data_size);
WriteSaveBuf(buf, OnAMissionFlag); 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, NextFreeCollectiveIndex);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding; CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding;
@ -12398,12 +12399,6 @@ INITSAVEBUF
ScriptSpace[i] = ReadSaveBuf<uint8>(buf); ScriptSpace[i] = ReadSaveBuf<uint8>(buf);
assert(ReadSaveBuf<uint32>(buf) == SCRIPT_DATA_SIZE); assert(ReadSaveBuf<uint32>(buf) == SCRIPT_DATA_SIZE);
OnAMissionFlag = ReadSaveBuf<uint32>(buf); OnAMissionFlag = ReadSaveBuf<uint32>(buf);
for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) {
OnAMissionForContactFlag[i] = ReadSaveBuf<uint32>(buf);
BaseBriefIdForContact[i] = ReadSaveBuf<uint32>(buf);
}
for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++)
CollectiveArray[i] = ReadSaveBuf<tCollectiveData>(buf);
NextFreeCollectiveIndex = ReadSaveBuf<uint32>(buf); NextFreeCollectiveIndex = ReadSaveBuf<uint32>(buf);
for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {
uint32 type = ReadSaveBuf<uint32>(buf); uint32 type = ReadSaveBuf<uint32>(buf);

@ -228,12 +228,10 @@ enum {
enum { enum {
MAX_NUM_SCRIPTS = 128, MAX_NUM_SCRIPTS = 128,
MAX_NUM_CONTACTS = 16,
MAX_NUM_INTRO_TEXT_LINES = 2, MAX_NUM_INTRO_TEXT_LINES = 2,
MAX_NUM_INTRO_RECTANGLES = 16, MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16, MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16, MAX_NUM_SCRIPT_SPHERES = 16,
MAX_NUM_COLLECTIVES = 32,
MAX_NUM_USED_OBJECTS = 200, MAX_NUM_USED_OBJECTS = 200,
MAX_NUM_MISSION_SCRIPTS = 120, MAX_NUM_MISSION_SCRIPTS = 120,
MAX_NUM_BUILDING_SWAPS = 25, MAX_NUM_BUILDING_SWAPS = 25,
@ -245,13 +243,10 @@ class CTheScripts
{ {
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE]; static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS]; 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_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES];
static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS]; static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];
static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
@ -275,14 +270,17 @@ class CTheScripts
static uint32 LargestMissionScriptSize; static uint32 LargestMissionScriptSize;
static uint32 MainScriptSize; static uint32 MainScriptSize;
static uint8 FailCurrentMission; static uint8 FailCurrentMission;
static uint8 CountdownToMakePlayerUnsafe;
static uint8 DelayMakingPlayerUnsafeThisTime;
static uint16 NumScriptDebugLines; static uint16 NumScriptDebugLines;
static uint16 NumberOfIntroRectanglesThisFrame; static uint16 NumberOfIntroRectanglesThisFrame;
static uint16 NumberOfIntroTextLinesThisFrame; static uint16 NumberOfIntroTextLinesThisFrame;
static uint8 UseTextCommands; static uint8 UseTextCommands;
static uint16 CommandsExecuted; static uint16 CommandsExecuted;
static uint16 ScriptsUpdated; static uint16 ScriptsUpdated;
static uint8 RiotIntensity;
static uint32 LastMissionPassedTime;
static uint16 NumberOfExclusiveMissionScripts;
static bool bPlayerIsInTheStatium;
static bool bPlayerHasMetDebbieHarry;
public: public:
static void Init(); static void Init();
@ -306,9 +304,6 @@ public:
static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; } 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) { static int32 Read4BytesFromScript(uint32* pIp) {
int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp]; int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 4; *pIp += 4;
@ -371,6 +366,7 @@ private:
static int32 AddScriptSphere(int32 id, CVector pos, float radius); static int32 AddScriptSphere(int32 id, CVector pos, float radius);
static int32 GetNewUniqueScriptSphereIndex(int32 index); static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index); static void RemoveScriptSphere(int32 index);
static void RemoveScriptTextureDictionary();
friend class CRunningScript; friend class CRunningScript;
friend class CHud; friend class CHud;
@ -414,6 +410,7 @@ class CRunningScript
uint32 m_anStack[MAX_STACK_DEPTH]; uint32 m_anStack[MAX_STACK_DEPTH];
uint16 m_nStackPointer; uint16 m_nStackPointer;
int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS]; int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];
bool m_bIsActive;
bool m_bCondResult; bool m_bCondResult;
bool m_bIsMissionScript; bool m_bIsMissionScript;
bool m_bSkipWakeTime; bool m_bSkipWakeTime;

@ -173,7 +173,6 @@ void
CPlayerInfo::MakePlayerSafe(bool toggle) CPlayerInfo::MakePlayerSafe(bool toggle)
{ {
if (toggle) { if (toggle) {
CTheScripts::ResetCountdownToMakePlayerUnsafe();
m_pPed->m_pWanted->m_bIgnoredByEveryone = true; m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
CWorld::StopAllLawEnforcersInTheirTracks(); CWorld::StopAllLawEnforcersInTheirTracks();
CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20; CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
@ -194,7 +193,8 @@ CPlayerInfo::MakePlayerSafe(bool toggle)
CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f); CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
CReplay::DisableReplays(); CReplay::DisableReplays();
} else if (!CGame::playingIntro && !CTheScripts::IsCountdownToMakePlayerUnsafeOn()) { }
else {
m_pPed->m_pWanted->m_bIgnoredByEveryone = false; m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20; CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
m_pPed->bBulletProof = false; m_pPed->bBulletProof = false;

@ -20,3 +20,25 @@ CBuilding::ReplaceWithNewModel(int32 id)
if(m_level == LEVEL_NONE || m_level == CGame::currLevel) if(m_level == LEVEL_NONE || m_level == CGame::currLevel)
CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE);
} }
bool
IsBuildingPointerValid(CBuilding* pBuilding)
{
if (!pBuilding)
return false;
if (pBuilding->GetIsATreadable()) {
int index = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding);
#ifdef FIX_BUGS
return index >= 0 && index < CPools::GetTreadablePool()->GetSize();
#else
return index >= 0 && index <= CPools::GetTreadablePool()->GetSize();
#endif
} else {
int index = CPools::GetBuildingPool()->GetJustIndex(pBuilding);
#ifdef FIX_BUGS
return index >= 0 && index < CPools::GetBuildingPool()->GetSize();
#else
return index >= 0 && index <= CPools::GetBuildingPool()->GetSize();
#endif
}
}

@ -16,3 +16,5 @@ public:
virtual bool GetIsATreadable(void) { return false; } virtual bool GetIsATreadable(void) { return false; }
}; };
bool IsBuildingPointerValid(CBuilding*);

@ -50,3 +50,18 @@ CDummy::Remove(void)
m_entryInfoList.DeleteNode(node); m_entryInfoList.DeleteNode(node);
} }
} }
bool
IsDummyPointerValid(CDummy* pDummy)
{
if (!pDummy)
return false;
int index = CPools::GetDummyPool()->GetJustIndex(pDummy);
#ifdef FIX_BUGS
if (index < 0 || index >= CPools::GetDummyPool()->GetSize())
#else
if (index < 0 || index > CPools::GetDummyPool()->GetSize())
#endif
return false;
return pDummy->m_entryInfoList.first;
}

@ -15,3 +15,5 @@ public:
static void *operator new(size_t); static void *operator new(size_t);
static void operator delete(void*, size_t); static void operator delete(void*, size_t);
}; };
bool IsDummyPointerValid(CDummy* pDummy);

@ -28,6 +28,8 @@
#include "Bones.h" #include "Bones.h"
#include "Debug.h" #include "Debug.h"
#include "Renderer.h" #include "Renderer.h"
#include "Ped.h"
#include "Dummy.h"
int gBuildings; int gBuildings;
@ -1028,3 +1030,18 @@ CEntity::LoadEntityFlags(uint8*& buf)
} }
#endif #endif
bool IsEntityPointerValid(CEntity* pEntity)
{
if (!pEntity)
return false;
switch (pEntity->GetType()) {
case ENTITY_TYPE_NOTHING: return false;
case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);
case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);
case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);
case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);
case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);
}
return false;
}

@ -180,3 +180,5 @@ public:
static void AddSteamsFromGround(CPtrList& list); static void AddSteamsFromGround(CPtrList& list);
}; };
bool IsEntityPointerValid(CEntity*);

@ -396,3 +396,18 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius)
} }
} }
} }
bool
IsObjectPointerValid(CObject* pObject)
{
if (!pObject)
return false;
int index = CPools::GetObjectPool()->GetJustIndex(pObject);
#ifdef FIX_BUGS
if (index < 0 || index >= CPools::GetObjectPool()->GetSize())
#else
if (index < 0 || index > CPools::GetObjectPool()->GetSize())
#endif
return false;
return pObject->bIsBIGBuilding || pObject->m_entryInfoList.first;
}

@ -113,3 +113,5 @@ public:
static void DeleteAllTempObjects(); static void DeleteAllTempObjects();
static void DeleteAllTempObjectsInArea(CVector point, float fRadius); static void DeleteAllTempObjectsInArea(CVector point, float fRadius);
}; };
bool IsObjectPointerValid(CObject* pObject);

@ -18600,3 +18600,28 @@ CPed::AddInCarAnims(CVehicle* car, bool isDriver)
StopNonPartialAnims(); StopNonPartialAnims();
} }
bool
IsPedPointerValid_NotInWorld(CPed* pPed)
{
if (!pPed)
return false;
int index = CPools::GetPedPool()->GetJustIndex(pPed);
#ifdef FIX_BUGS
if (index < 0 || index >= NUMPEDS)
#else
if (index < 0 || index > NUMPEDS)
#endif
return false;
return true;
}
bool
IsPedPointerValid(CPed* pPed)
{
if (!IsPedPointerValid_NotInWorld(pPed))
return false;
if (pPed->bInVehicle && pPed->m_pMyVehicle)
return IsEntityPointerValid(pPed->m_pMyVehicle);
return pPed->m_entryInfoList.first || pPed == FindPlayerPed();
}

@ -1018,3 +1018,6 @@ void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg);
#ifndef PED_SKIN #ifndef PED_SKIN
VALIDATE_SIZE(CPed, 0x53C); VALIDATE_SIZE(CPed, 0x53C);
#endif #endif
bool IsPedPointerValid(CPed*);
bool IsPedPointerValid_NotInWorld(CPed*);

@ -1378,3 +1378,18 @@ CVehicle::GetVehicleAppearance(void)
return VEHICLE_APPEARANCE_HELI; return VEHICLE_APPEARANCE_HELI;
return VEHICLE_APPEARANCE_NONE; return VEHICLE_APPEARANCE_NONE;
} }
bool
IsVehiclePointerValid(CVehicle* pVehicle)
{
if (!pVehicle)
return false;
int index = CPools::GetVehiclePool()->GetJustIndex(pVehicle);
#ifdef FIX_BUGS
if (index < 0 || index >= NUMVEHICLES)
#else
if (index < 0 || index > NUMVEHICLES)
#endif
return false;
return pVehicle->m_vehType == VEHICLE_TYPE_PLANE || pVehicle->m_entryInfoList.first;
}

@ -314,3 +314,4 @@ public:
}; };
void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle); void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);
bool IsVehiclePointerValid(CVehicle* pVehicle);