From 345b8553a7455926d523b90926edb0eacf88a13a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 27 Jul 2019 21:28:18 +0300 Subject: cargen + some script --- src/control/CarGen.cpp | 309 +++++++++++++++++++++++++++++++++++++++++++++++ src/control/CarGen.h | 56 +++++++++ src/control/Garages.cpp | 5 + src/control/Garages.h | 1 + src/control/Script.cpp | 278 +++++++++++++++++++++++++++++++++++++++++- src/control/Script.h | 8 +- src/core/User.cpp | 2 + src/core/User.h | 2 + src/core/World.cpp | 1 + src/core/World.h | 1 + src/core/config.h | 2 + src/vehicles/Vehicle.cpp | 4 +- src/vehicles/Vehicle.h | 4 +- 13 files changed, 667 insertions(+), 6 deletions(-) create mode 100644 src/control/CarGen.cpp create mode 100644 src/control/CarGen.h diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp new file mode 100644 index 00000000..332ff16d --- /dev/null +++ b/src/control/CarGen.cpp @@ -0,0 +1,309 @@ +#include "common.h" +#include "patcher.h" +#include "CarGen.h" + +#include "Automobile.h" +#include "Boat.h" +#include "Camera.h" +#include "CarCtrl.h" +#include "CutsceneMgr.h" +#include "General.h" +#include "Pools.h" +#include "Streaming.h" +#include "Timer.h" +#include "Vehicle.h" +#include "World.h" + +uint8 &CTheCarGenerators::ProcessCounter = *(uint8*)0x95CDAF; +uint32 &CTheCarGenerators::NumOfCarGenerators = *(uint32*)0x8E2C1C; +CCarGenerator (&CTheCarGenerators::CarGeneratorArray)[NUM_CARGENS] = *(CCarGenerator(*)[NUM_CARGENS])*(uintptr*)0x87CB18; +uint8 &CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = *(uint8*)0x95CDC6; +uint32 &CTheCarGenerators::CurrentActiveCount = *(uint32*)0x8F2C5C; + +void CCarGenerator::SwitchOff() +{ + m_nUsesRemaining = 0; + --CTheCarGenerators::CurrentActiveCount; +} + +void CCarGenerator::SwitchOn() +{ + m_nUsesRemaining = -1; + m_nTimer = CalcNextGen(); + ++CTheCarGenerators::CurrentActiveCount; +} + +uint32 CCarGenerator::CalcNextGen() +{ + return CTimer::GetTimeInMilliseconds() + 4; +} + +void CCarGenerator::DoInternalProcessing() +{ + if (CheckForBlockage()) { + m_nTimer += 4; + if (m_nUsesRemaining == 0) + --CTheCarGenerators::CurrentActiveCount; + return; + } + if (CCarCtrl::NumParkedCars >= 10) + return; + CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY); + if (!CStreaming::HasModelLoaded(m_nModelIndex)) + return; + if (CModelInfo::IsBoatModel(m_nModelIndex)){ + CBoat* pBoat = new CBoat(m_nModelIndex, PARKED_VEHICLE); + pBoat->bIsStatic = false; + pBoat->bEngineOn = false; + CVector pos = m_vecPos; + if (pos.z <= -100.0f) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pos.z += pBoat->GetDistanceFromCentreOfMassToBaseOfModel(); + pBoat->GetPosition() = pos; + pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); + pBoat->m_status = STATUS_ABANDONED; + pBoat->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(pBoat); + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm) + pBoat->m_nAlarmState = -1; + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock) + pBoat->m_nDoorLock = CARLOCK_LOCKED; + if (m_nColor1 != -1 && m_nColor2){ + pBoat->m_currentColour1 = m_nColor1; + pBoat->m_currentColour2 = m_nColor2; + } + m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat); + }else{ + bool groundFound = false; + CVector pos = m_vecPos; + if (pos.z > -100.0f){ + pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound); + }else{ + CColPoint cp; + CEntity* pEntity; + groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f, + cp, pEntity, true, false, false, false, false, false, nil); + if (groundFound) + pos.z = cp.point.z; + } + if (!groundFound) { + debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); + }else{ + CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE); + pCar->bIsStatic = false; + pCar->bEngineOn = false; + pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel(); + pCar->GetPosition() = pos; + pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); + pCar->m_status = STATUS_ABANDONED; + pCar->bLightsOn = false; + pCar->m_nDoorLock = CARLOCK_UNLOCKED; + CWorld::Add(pCar); + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm) + pCar->m_nAlarmState = -1; + if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock) + pCar->m_nDoorLock = CARLOCK_LOCKED; + if (m_nColor1 != -1 && m_nColor2) { + pCar->m_currentColour1 = m_nColor1; + pCar->m_currentColour2 = m_nColor2; + } + m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pCar); + } + } + if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */ + --m_nUsesRemaining; + m_nTimer = CalcNextGen(); + if (m_nUsesRemaining == 0) + --CTheCarGenerators::CurrentActiveCount; +} + +void CCarGenerator::Process() +{ + if (m_nVehicleHandle == -1 && + (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) && + m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayer()) + DoInternalProcessing(); + if (m_nVehicleHandle == -1) + return; + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle); + if (!pVehicle){ + m_nVehicleHandle = -1; + return; + } + if (pVehicle->m_status != STATUS_PLAYER) + return; + m_nTimer += 60000; + m_nVehicleHandle = -1; + m_bIsBlocking = true; + pVehicle->bExtendedRange = false; +} + +void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) +{ + CMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */ + m_vecPos = CVector(x, y, z); + m_fAngle = angle; + m_nModelIndex = mi; + m_nColor1 = color1; + m_nColor2 = color2; + m_bForceSpawn = force; + m_nAlarm = alarm; + m_nDoorlock = lock; + m_nMinDelay = min_delay; + m_nMaxDelay = max_delay; + m_nVehicleHandle = -1; + m_nTimer = CTimer::GetTimeInMilliseconds() + 1; + m_nUsesRemaining = 0; + m_bIsBlocking = false; + m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min; + m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max; + m_fSize = max(m_vecInf.Magnitude(), m_vecSup.Magnitude()); +} + +bool CCarGenerator::CheckForBlockage() +{ + int16 entities; + CWorld::FindObjectsKindaColliding(CVector(m_vecPos), m_fSize, 1, &entities, 2, nil, false, true, true, false, false); + return entities > 0; +} + +bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer() +{ + CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos; + float distance = direction.Magnitude(); + float farclip = 120.0f * TheCamera.GenerationDistMultiplier; + float nearclip = farclip - 20.0f; + if (distance >= farclip){ + if (m_bIsBlocking) + m_bIsBlocking = false; + return false; + } + if (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter) + return true; + if (m_bIsBlocking) + return false; + if (distance < nearclip) + return false; + debug("Value to test: %f\n", DotProduct2D(direction, FindPlayerSpeed())); + return DotProduct2D(direction, FindPlayerSpeed()) <= 0; +} + +void CCarGenerator::Save(uint8* buffer) +{ + *(uint32*)(buffer) = m_nModelIndex; + *(CVector*)(buffer + 4) = m_vecPos; + *(float*)(buffer + 16) = m_fAngle; + *(int16*)(buffer + 20) = m_nColor1; + *(int16*)(buffer + 22) = m_nColor2; + *(bool*)(buffer + 24) = m_bForceSpawn; + *(uint8*)(buffer + 25) = m_nAlarm; + *(uint8*)(buffer + 26) = m_nDoorlock; + *(uint8*)(buffer + 27) = 0; + *(uint16*)(buffer + 28) = m_nMinDelay; + *(uint16*)(buffer + 30) = m_nMaxDelay; + *(uint32*)(buffer + 32) = m_nTimer; + *(int32*)(buffer + 36) = m_nVehicleHandle; + *(uint16*)(buffer + 40) = m_nUsesRemaining; + *(bool*)(buffer + 42) = m_bIsBlocking; + *(uint8*)(buffer + 43) = 0; + *(CVector*)(buffer + 44) = m_vecInf; + *(CVector*)(buffer + 56) = m_vecSup; + *(float*)(buffer + 68) = m_fSize; +} + +void CCarGenerator::Load(uint8* buffer) +{ + m_nModelIndex = *(uint32*)(buffer); + m_vecPos = *(CVector*)(buffer + 4); + m_fAngle = *(float*)(buffer + 16); + m_nColor1 = *(int16*)(buffer + 20); + m_nColor2 = *(int16*)(buffer + 22); + m_bForceSpawn = *(bool*)(buffer + 24); + m_nAlarm = *(uint8*)(buffer + 25); + m_nDoorlock = *(uint8*)(buffer + 26); + m_nMinDelay = *(uint16*)(buffer + 28); + m_nMaxDelay = *(uint16*)(buffer + 30); + m_nTimer = *(uint32*)(buffer + 32); + m_nVehicleHandle = *(int32*)(buffer + 36); + m_nUsesRemaining = *(uint16*)(buffer + 40); + m_bIsBlocking = *(bool*)(buffer + 42); + m_vecInf = *(CVector*)(buffer + 44); + m_vecSup = *(CVector*)(buffer + 56); + m_fSize = *(float*)(buffer + 68); +} + +void CTheCarGenerators::Process() +{ + if (FindPlayerTrain() || CCutsceneMgr::IsRunning()) + return; + if (++CTheCarGenerators::ProcessCounter == 4) + CTheCarGenerators::ProcessCounter = 0; + for (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4) + CTheCarGenerators::CarGeneratorArray[i].Process(); + if (GenerateEvenIfPlayerIsCloseCounter) + GenerateEvenIfPlayerIsCloseCounter--; +} + +int32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay) +{ + CarGeneratorArray[NumOfCarGenerators].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay); + return NumOfCarGenerators++; +} + +void CTheCarGenerators::Init() +{ + GenerateEvenIfPlayerIsCloseCounter = 0; + NumOfCarGenerators = 0; + ProcessCounter = 0; + CurrentActiveCount = 0; +} + +void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size) +{ + *size = 28 + 72 * NUM_CARGENS; + buffer[0] = 'C'; + buffer[1] = 'G'; + buffer[2] = 'N'; + buffer[3] = '\0'; + *(uint32*)(buffer + 4) = *size - 8; + *(uint32*)(buffer + 8) = 12; /* what is this? */ + *(uint32*)(buffer + 12) = NumOfCarGenerators; + *(uint32*)(buffer + 16) = CurrentActiveCount; + *(uint8*)(buffer + 20) = ProcessCounter; + *(uint8*)(buffer + 21) = GenerateEvenIfPlayerIsCloseCounter; + *(uint16*)(buffer + 22) = 0; + *(uint32*)(buffer + 24) = 72 * NUM_CARGENS; + buffer += 28; + for (int i = 0; i < NUM_CARGENS; i++){ + CarGeneratorArray[i].Save(buffer); + buffer += 72; + } +} + +void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size) +{ + Init(); + assert(size == 8 + NUM_CARGENS * 72); + assert(buffer[0] == 'C'); + assert(buffer[1] == 'G'); + assert(buffer[2] == 'N'); + assert(buffer[3] == '\0'); + assert(*(uint32*)(buffer + 4) == size - 8); + buffer += 8; + NumOfCarGenerators = *(uint32*)(buffer + 12); + CurrentActiveCount = *(uint32*)(buffer + 16); + ProcessCounter = *(uint8*)(buffer + 20); + GenerateEvenIfPlayerIsCloseCounter = *(uint8*)(buffer + 21); + assert(*(uint32*)(buffer + 24) == 72 * NUM_CARGENS); + for (int i = 0; i < NUM_CARGENS; i++) { + CarGeneratorArray[i].Load(buffer); + buffer += 72; + } +} + +STARTPATCHES +InjectHook(0x543020, CTheCarGenerators::Init, PATCH_JUMP); +InjectHook(0x542F40, CTheCarGenerators::Process, PATCH_JUMP); +InjectHook(0x543050, CTheCarGenerators::SaveAllCarGenerators, PATCH_JUMP); +InjectHook(0x5431E0, CTheCarGenerators::LoadAllCarGenerators, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/control/CarGen.h b/src/control/CarGen.h new file mode 100644 index 00000000..c1ca304c --- /dev/null +++ b/src/control/CarGen.h @@ -0,0 +1,56 @@ +#pragma once +#include "common.h" +#include "config.h" + +enum { + CARGEN_MAXACTUALLIMIT = 100 +}; + +class CCarGenerator +{ + int32 m_nModelIndex; + CVector m_vecPos; + float m_fAngle; + int16 m_nColor1; + int16 m_nColor2; + uint8 m_bForceSpawn; + uint8 m_nAlarm; + uint8 m_nDoorlock; + int16 m_nMinDelay; + int16 m_nMaxDelay; + uint32 m_nTimer; + int32 m_nVehicleHandle; + uint16 m_nUsesRemaining; + bool m_bIsBlocking; + CVector m_vecInf; + CVector m_vecSup; + float m_fSize; +public: + void SwitchOff(); + void SwitchOn(); + uint32 CalcNextGen(); + void DoInternalProcessing(); + void Process(); + void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay); + bool CheckForBlockage(); + bool CheckIfWithinRangeOfAnyPlayer(); + void Save(uint8*); + void Load(uint8*); + void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; } +}; + +class CTheCarGenerators +{ +public: + static uint8 &ProcessCounter; + static uint32 &NumOfCarGenerators; + static CCarGenerator (&CarGeneratorArray)[NUM_CARGENS]; + static uint8 &GenerateEvenIfPlayerIsCloseCounter; + static uint32 &CurrentActiveCount; + + static void Process(); + static int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay); + static void Init(); + static void SaveAllCarGenerators(uint8 *, uint32 *); + static void LoadAllCarGenerators(uint8 *, uint32); +}; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index acc2b459..0629ac0c 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -63,6 +63,11 @@ CGarages::IsModelIndexADoor(uint32 id) id == MI_CRUSHERLID; } +bool CGarages::HasCarBeenCrushed(int32 handle) +{ + return CrushedCarId == handle; +} + WRAPPER void CGarages::TriggerMessage(char *text, int16, uint16 time, int16) { EAXJMP(0x426B20); } #if 0 diff --git a/src/control/Garages.h b/src/control/Garages.h index 69f9d256..45a9345d 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -24,4 +24,5 @@ public: static bool IsModelIndexADoor(uint32 id); static void TriggerMessage(char *text, int16, uint16 time, int16); static void PrintMessages(void); + static bool HasCarBeenCrushed(int32); }; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 31684e3f..9dbc8439 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -7,12 +7,14 @@ #include "Boat.h" #include "Camera.h" #include "CarCtrl.h" +#include "CarGen.h" #include "CivilianPed.h" #include "Clock.h" #include "CopPed.h" #include "DMAudio.h" #include "EmergencyPed.h" #include "FileMgr.h" +#include "Garages.h" #include "General.h" #include "HandlingMgr.h" #include "Hud.h" @@ -2801,6 +2803,281 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command) return -1; } +#if 1 +WRAPPER int8 CRunningScript::ProcessCommandsFrom300To399(int32 command) { EAXJMP(0x43ED30); } +#else +int8 CRunningScript::ProcessCommandsFrom300To399(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_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_CHANGE_CAR_LOCK: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->m_nDoorLock = (eCarLock)ScriptParams[1]; + return 0; + } + case COMMAND_SHAKE_CAM_WITH_POINT: + CollectParameters(&m_nIp, 4); + TheCamera.CamShake(ScriptParams[0] / 1000.0f, + *(float*)&ScriptParams[1], + *(float*)&ScriptParams[2], + *(float*)&ScriptParams[3]); + return 0; + case COMMAND_IS_CAR_MODEL: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + UpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]); + } + /* Not implemented. + 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); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + float x1, y1, x2, y2; + x1 = *(float*)&ScriptParams[1]; + y1 = *(float*)&ScriptParams[2]; + x2 = *(float*)&ScriptParams[3]; + y2 = *(float*)&ScriptParams[4]; + UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED && + pVehicle->IsWithinArea(x1, y1, x2, y2)); + if (!ScriptParams[5]) + return 0; + CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f); + if (CTheScripts::DbgFlag) + CTheScripts::DrawDebugSquare(x1, y1, x2, y2); + return 0; + } + case COMMAND_IS_CAR_DEAD_IN_AREA_3D: + { + CollectParameters(&m_nIp, 8); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + float x1, y1, z1, x2, y2, z2; + x1 = *(float*)&ScriptParams[1]; + y1 = *(float*)&ScriptParams[2]; + z1 = *(float*)&ScriptParams[3]; + x2 = *(float*)&ScriptParams[4]; + y2 = *(float*)&ScriptParams[5]; + z2 = *(float*)&ScriptParams[6]; + UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED && + pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); + if (!ScriptParams[7]) + return 0; + CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (CTheScripts::DbgFlag) + 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_CAR_CRUSHED: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0])); + return 0; + /* Not implemented. + case COMMAND_CREATE_GANG_CAR: + */ + case COMMAND_CREATE_CAR_GENERATOR: + CollectParameters(&m_nIp, 12); + ScriptParams[0] = CTheCarGenerators::CreateCarGenerator( + *(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(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); + CCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]]; + if (ScriptParams[1] == 0){ + pCarGen->SwitchOff(); + }else if (ScriptParams[1] <= 100){ + pCarGen->SwitchOn(); + }else{ + pCarGen->SwitchOn(); + pCarGen->SetUsesRemaining(ScriptParams[1]); + } + return 0; + } + case COMMAND_ADD_PAGER_MESSAGE: + { + wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp); + CollectParameters(&m_nIp, 3); + CUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]); + return 0; + } + case COMMAND_DISPLAY_ONSCREEN_TIMER: + { + assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.AddClock(CTheScripts::Read2BytesFromScript(&m_nIp), nil); + return 0; + } + case COMMAND_CLEAR_ONSCREEN_TIMER: + { + assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.ClearClock(CTheScripts::Read2BytesFromScript(&m_nIp)); + return 0; + } + case COMMAND_DISPLAY_ONSCREEN_COUNTER: + { + assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + int32 counter = CTheScripts::Read2BytesFromScript(&m_nIp); + CollectParameters(&m_nIp, 1); + CUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil); + return 0; + } + case COMMAND_CLEAR_ONSCREEN_COUNTER: + { + assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR); + m_nIp++; + CUserDisplay::OnscnTimer.ClearCounter(CTheScripts::Read2BytesFromScript(&m_nIp)); + return 0; + } + case COMMAND_SET_ZONE_CAR_INFO: + { + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + m_nIp += 8; + CollectParameters(&m_nIp, 16); + int zone = CTheZones::FindZoneByLabelAndReturnIndex(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]); + return 0; + } + /* Not implemented. + case COMMAND_IS_CHAR_IN_GANG_ZONE: + */ + case COMMAND_IS_CHAR_IN_ZONE: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + char label[12]; + CTheScripts::ReadTextLabelFromScript(&m_nIp, label); + int zone = CTheZones::FindZoneByLabelAndReturnIndex(label); + if (zone != -1) + m_nIp += 8; + 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); + m_nIp += 8; + + } + case COMMAND_SET_PED_DENSITY: + case COMMAND_POINT_CAMERA_AT_PLAYER: + case COMMAND_POINT_CAMERA_AT_CAR: + case COMMAND_POINT_CAMERA_AT_CHAR: + case COMMAND_RESTORE_CAMERA: + case COMMAND_SHAKE_PAD: + case COMMAND_SET_ZONE_PED_INFO: + case COMMAND_SET_TIME_SCALE: + case COMMAND_IS_CAR_IN_AIR: + case COMMAND_SET_FIXED_CAMERA_POSITION: + case COMMAND_POINT_CAMERA_AT_POINT: + case COMMAND_ADD_BLIP_FOR_CAR_OLD: + case COMMAND_ADD_BLIP_FOR_CHAR_OLD: + case COMMAND_ADD_BLIP_FOR_OBJECT_OLD: + case COMMAND_REMOVE_BLIP: + case COMMAND_CHANGE_BLIP_COLOUR: + case COMMAND_DIM_BLIP: + case COMMAND_ADD_BLIP_FOR_COORD_OLD: + case COMMAND_CHANGE_BLIP_SCALE: + case COMMAND_SET_FADING_COLOUR: + case COMMAND_DO_FADE: + case COMMAND_GET_FADING_STATUS: + case COMMAND_ADD_HOSPITAL_RESTART: + case COMMAND_ADD_POLICE_RESTART: + case COMMAND_OVERRIDE_NEXT_RESTART: + case COMMAND_DRAW_SHADOW: + case COMMAND_GET_PLAYER_HEADING: + case COMMAND_SET_PLAYER_HEADING: + case COMMAND_GET_CHAR_HEADING: + case COMMAND_SET_CHAR_HEADING: + case COMMAND_GET_CAR_HEADING: + case COMMAND_SET_CAR_HEADING: + case COMMAND_GET_OBJECT_HEADING: + case COMMAND_SET_OBJECT_HEADING: + case COMMAND_IS_PLAYER_TOUCHING_OBJECT: + case COMMAND_IS_CHAR_TOUCHING_OBJECT: + case COMMAND_SET_PLAYER_AMMO: + case COMMAND_SET_CHAR_AMMO: + 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: + case COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT: + case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT: + case COMMAND_IS_PLAYER_HEALTH_GREATER: + case COMMAND_IS_CHAR_HEALTH_GREATER: + case COMMAND_IS_CAR_HEALTH_GREATER: + case COMMAND_ADD_BLIP_FOR_CAR: + case COMMAND_ADD_BLIP_FOR_CHAR: + case COMMAND_ADD_BLIP_FOR_OBJECT: + case COMMAND_ADD_BLIP_FOR_CONTACT_POINT: + case COMMAND_ADD_BLIP_FOR_COORD: + case COMMAND_CHANGE_BLIP_DISPLAY: + case COMMAND_ADD_ONE_OFF_SOUND: + case COMMAND_ADD_CONTINUOUS_SOUND: + case COMMAND_REMOVE_SOUND: + case COMMAND_IS_CAR_STUCK_ON_ROOF: + default: + assert(0); + } + return -1; +} +#endif + int16 CRunningScript::GetPadState(uint16 pad, uint16 button) { CPad* pPad = CPad::GetPad(pad); @@ -2830,7 +3107,6 @@ int16 CRunningScript::GetPadState(uint16 pad, uint16 button) return 0; } -WRAPPER int8 CRunningScript::ProcessCommandsFrom300To399(int32 command) { EAXJMP(0x43ED30); } WRAPPER int8 CRunningScript::ProcessCommandsFrom400To499(int32 command) { EAXJMP(0x440CB0); } WRAPPER int8 CRunningScript::ProcessCommandsFrom500To599(int32 command) { EAXJMP(0x4429C0); } WRAPPER int8 CRunningScript::ProcessCommandsFrom600To699(int32 command) { EAXJMP(0x444B20); } diff --git a/src/control/Script.h b/src/control/Script.h index 0984952a..47c70914 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -1,5 +1,6 @@ #pragma once #include "common.h" +#include "Text.h" #include "Sprite2d.h" class CEntity; @@ -373,6 +374,11 @@ public: return Read2BytesFromScript(pIp) / 16.0f; } static void ReadTextLabelFromScript(uint32* pIp, char* buf){ - strncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], 8); + strncpy(buf, (const char*)&ScriptSpace[*pIp], 8); + } + static wchar* GetTextByKeyFromScript(uint32* pIp) { + wchar* text = TheText.Get((const char*)&ScriptSpace[*pIp]); + *pIp += 8; + return text; } }; diff --git a/src/core/User.cpp b/src/core/User.cpp index c9cb97cc..f40a06db 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -13,6 +13,8 @@ COnscreenTimer& CUserDisplay::OnscnTimer = *(COnscreenTimer*)0x862238; CPager& CUserDisplay::Pager = *(CPager*)0x8F2744; CCurrentVehicle& CUserDisplay::CurrentVehicle = *(CCurrentVehicle*)0x8F5FE8; +WRAPPER void CPager::AddMessage(wchar*, uint16, uint16, uint16) { EAXJMP(0x52B940); } + void COnscreenTimer::Init() { m_bDisabled = false; for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { diff --git a/src/core/User.h b/src/core/User.h index 8b744c7e..cac2a318 100644 --- a/src/core/User.h +++ b/src/core/User.h @@ -52,6 +52,8 @@ class CCurrentVehicle class CPager { +public: + void AddMessage(wchar*, uint16, uint16, uint16); }; class CUserDisplay diff --git a/src/core/World.cpp b/src/core/World.cpp index 829a64d4..0440a951 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -29,6 +29,7 @@ bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C; bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } +WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } void CWorld::Add(CEntity *ent) diff --git a/src/core/World.h b/src/core/World.h index fd9d6fc3..e4f46589 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -103,6 +103,7 @@ public: static float FindGroundZFor3DCoord(float x, float y, float z, bool *found); static float FindRoofZFor3DCoord(float x, float y, float z, bool *found); static void RemoveReferencesToDeletedObject(CEntity*); + static void FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool); static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); } static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } diff --git a/src/core/config.h b/src/core/config.h index 1bc90496..1f684869 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -64,6 +64,8 @@ enum Config { NUMRADARBLIPS = 32, NUMPICKUPS = 336, NUMEVENTS = 64, + + NUM_CARGENS = 160 }; // We'll use this once we're ready to become independent of the game diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index d8ea6211..51b139e6 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -59,8 +59,8 @@ CVehicle::CVehicle(uint8 CreatedBy) m_pBlowUpEntity = nil; field_1FB = 0; bComedyControls = false; - m_veh_flagB40 = false; - m_veh_flagB80 = false; + bCraneMessageDone = false; + bExtendedRange = false; bTakeLessDamage = false; bIsDamaged = false; bFadeOut = false; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 825c1a6c..1e5a7849 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -176,8 +176,8 @@ public: uint8 bLowVehicle: 1; // Need this for sporty type cars to use low getting-in/out anims uint8 bComedyControls : 1; // Will make the car hard to control (hopefully in a funny way) uint8 bWarnedPeds : 1; // Has scan and warn peds of danger been processed? - uint8 m_veh_flagB40 : 1; - uint8 m_veh_flagB80 : 1; + uint8 bCraneMessageDone : 1; // A crane message has been printed for this car allready + uint8 bExtendedRange : 1; // This vehicle needs to be a bit further away to get deleted uint8 bTakeLessDamage : 1; // This vehicle is stronger (takes about 1/4 of damage) uint8 bIsDamaged : 1; // This vehicle has been damaged and is displaying all its components -- cgit v1.2.3