From 5acce16261606f06e39e09d0bd6ec0d95787ae38 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 25 Jul 2019 23:34:29 +0300 Subject: [PATCH] Running script part 3 --- src/control/CarCtrl.cpp | 4 + src/control/CarCtrl.h | 4 + src/control/Pickups.cpp | 1 + src/control/Pickups.h | 1 + src/control/Remote.cpp | 1 + src/control/Remote.h | 1 + src/control/Replay.cpp | 8 +- src/control/Script.cpp | 667 ++++++++++++++++++++++++++++++++++- src/control/Script.h | 41 ++- src/control/ScriptCommands.h | 2 +- src/core/PlayerInfo.cpp | 9 + src/core/PlayerInfo.h | 1 + src/objects/Object.cpp | 10 + src/objects/Object.h | 2 + src/peds/Ped.cpp | 16 +- src/peds/Ped.h | 4 +- src/render/Shadows.cpp | 2 +- src/vehicles/Boat.cpp | 2 +- src/vehicles/Vehicle.cpp | 3 +- 19 files changed, 758 insertions(+), 21 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 5e436c84..12b444a2 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -7,6 +7,9 @@ int &CCarCtrl::NumAmbulancesOnDuty = *(int*)0x885BB0; int &CCarCtrl::NumFiretrucksOnDuty = *(int*)0x9411F0; bool &CCarCtrl::bCarsGeneratedAroundCamera = *(bool*)0x95CD8A; float& CCarCtrl::CarDensityMultiplier = *(float*)0x5EC8B4; +int32 &CCarCtrl::NumMissionCars = *(int32*)0x8F1B54; +int32 &CCarCtrl::NumRandomCars = *(int32*)0x943118; +int32 &CCarCtrl::NumParkedCars = *(int32*)0x8F29E0; WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } WRAPPER void CCarCtrl::AddToCarArray(int32 id, int32 vehclass) { EAXJMP(0x4182F0); } @@ -17,6 +20,7 @@ WRAPPER void CCarCtrl::JoinCarWithRoadSystem(CVehicle*) { EAXJMP(0x41F820); } WRAPPER void CCarCtrl::SteerAICarWithPhysics(CVehicle*) { EAXJMP(0x41DA60); } WRAPPER void CCarCtrl::UpdateCarOnRails(CVehicle*) { EAXJMP(0x418880); } WRAPPER void CCarCtrl::ScanForPedDanger(CVehicle *veh) { EAXJMP(0x418F40); } +WRAPPER void CCarCtrl::RemoveFromInterestingVehicleList(CVehicle* v) { EAXJMP(0x41F7A0); } bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 677dcf36..2ad52d49 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -15,10 +15,14 @@ public: static void UpdateCarOnRails(CVehicle*); static bool MapCouldMoveInThisArea(float x, float y); static void ScanForPedDanger(CVehicle *veh); + static void RemoveFromInterestingVehicleList(CVehicle*); static int32 &NumLawEnforcerCars; static int32 &NumAmbulancesOnDuty; static int32 &NumFiretrucksOnDuty; + static int32 &NumRandomCars; + static int32 &NumMissionCars; + static int32 &NumParkedCars; static bool &bCarsGeneratedAroundCamera; static float &CarDensityMultiplier; }; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 56254d56..c93798fe 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -9,5 +9,6 @@ WRAPPER void CPickups::DoCollectableEffects(CEntity *ent) { EAXJMP(0x431C30); } WRAPPER void CPickups::DoMoneyEffects(CEntity *ent) { EAXJMP(0x431F40); } WRAPPER void CPickups::DoMineEffects(CEntity *ent) { EAXJMP(0x4321C0); } WRAPPER void CPickups::DoPickUpEffects(CEntity *ent) { EAXJMP(0x431520); } +WRAPPER void CPickups::RemoveAllFloatingPickups() { EAXJMP(0x430800); } WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 9cf485d0..b740e72e 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -41,6 +41,7 @@ public: static void DoMoneyEffects(CEntity *ent); static void DoMineEffects(CEntity *ent); static void DoPickUpEffects(CEntity *ent); + static void RemoveAllFloatingPickups(); static CPickup (&aPickUps)[NUMPICKUPS]; }; diff --git a/src/control/Remote.cpp b/src/control/Remote.cpp index 8d8d08f2..c9ae0d8c 100644 --- a/src/control/Remote.cpp +++ b/src/control/Remote.cpp @@ -2,4 +2,5 @@ #include "patcher.h" #include "Remote.h" +WRAPPER void CRemote::GivePlayerRemoteControlledCar(float, float, float, float) { EAXJMP(0x435C30); } WRAPPER void CRemote::TakeRemoteControlledCarFromPlayer(void) { EAXJMP(0x435DA0); } diff --git a/src/control/Remote.h b/src/control/Remote.h index f8ef96bf..b4482b2d 100644 --- a/src/control/Remote.h +++ b/src/control/Remote.h @@ -3,5 +3,6 @@ class CRemote { public: + static void GivePlayerRemoteControlledCar(float, float, float, float); static void TakeRemoteControlledCarFromPlayer(void); }; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index d9453ad6..1e77da3a 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -240,15 +240,15 @@ void CReplay::Update(void) if (CDraw::FadeValue || !bReplayEnabled) return; if (Mode == MODE_PLAYBACK){ - if (CPad::NewKeyState.F[0] && !CPad::OldKeyState.F[0]) + if (CPad::GetPad(0)->GetFJustDown(0)) FinishPlayback(); } else if (Mode == MODE_RECORD){ - if (CPad::NewKeyState.F[0] && !CPad::OldKeyState.F[0]) + if (CPad::GetPad(0)->GetFJustDown(0)) TriggerPlayback(REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false); - if (CPad::NewKeyState.F[1] && !CPad::OldKeyState.F[1]) + if (CPad::GetPad(0)->GetFJustDown(1)) SaveReplayToHD(); - if (CPad::NewKeyState.F[2] && !CPad::OldKeyState.F[2]) + if (CPad::GetPad(0)->GetFJustDown(2)) PlayReplayFromHD(); } } diff --git a/src/control/Script.cpp b/src/control/Script.cpp index bd43d301..ae49094b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -19,10 +19,12 @@ #include "Messages.h" #include "ModelIndices.h" #include "Pad.h" +#include "Pickups.h" #include "PlayerInfo.h" #include "PlayerPed.h" #include "Pools.h" #include "Population.h" +#include "Remote.h" #include "Replay.h" #include "Streaming.h" #include "Text.h" @@ -170,6 +172,9 @@ void CMissionCleanup::Process() default: break; } + m_sEntities[i].id = 0; + m_sEntities[i].type = CLEANUP_UNUSED; + m_nCount--; } } @@ -426,8 +431,8 @@ void CRunningScript::Init() m_anLocalVariables[i] = 0; m_nAndOrState = 0; m_bNotFlag = false; - m_bWBCheckEnabled = true; - m_bWBChecked = false; + m_bDeatharrestEnabled = true; + m_bDeatharrestExecuted = false; m_bMissionFlag = false; } @@ -1113,6 +1118,13 @@ int8 CRunningScript::ProcessCommandsFrom0To99(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_FLOAT_VAR_EQUAL_TO_NUMBER: { int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL); @@ -1148,6 +1160,13 @@ int8 CRunningScript::ProcessCommandsFrom0To99(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_GOTO_IF_TRUE: CollectParameters(&m_nIp, 1); if (m_bCondResult) @@ -1311,7 +1330,7 @@ int8 CRunningScript::ProcessCommandsFrom0To99(int32 command) UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); if (!ScriptParams[7]) return 0; - CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f); + 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; @@ -1730,6 +1749,9 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) ped->SetWanderPath(path); return 0; } + /* Not implemented. + case COMMAND_CHAR_WANDER_RANGE: + */ case COMMAND_CHAR_FOLLOW_PATH: { CollectParameters(&m_nIp, 4); @@ -1747,7 +1769,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) CollectParameters(&m_nIp, 1); CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(ped); - ped->m_bScriptObjectiveCompleted = false; + ped->bScriptObjectiveCompleted = false; ped->SetObjective(OBJECTIVE_IDLE); return 0; } @@ -1826,7 +1848,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) { CollectParameters(&m_nIp, 1); CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(ped && ped->m_status != PED_DEAD && ped->m_status != PED_DIE); + UpdateCompareFlag(ped && ped->GetPedState() != PED_DEAD && ped->GetPedState() != PED_DIE); return 0; } case COMMAND_IS_CHAR_IN_AREA_2D: @@ -1848,6 +1870,8 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2)); else UpdateCompareFlag(ped->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); @@ -1874,7 +1898,9 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); else UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); - CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f); + 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; @@ -2043,7 +2069,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) } case COMMAND_IS_CAR_STILL_ALIVE: { - CollectParameters(&m_nIp, 4); + CollectParameters(&m_nIp, 1); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); UpdateCompareFlag(car && car->m_status != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater)); return 0; @@ -2085,6 +2111,8 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) x2 = *(float*)&ScriptParams[3]; y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(vehicle->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); @@ -2103,7 +2131,9 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) y2 = *(float*)&ScriptParams[5]; z2 = *(float*)&ScriptParams[6]; UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - CTheScripts::HighlightImportantArea((uint32)this + m_nIp, x1, y1, x2, y2, -100.0f); + 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; @@ -2187,6 +2217,9 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) case COMMAND_RETURN_FALSE: UpdateCompareFlag(false); return 0; + /* Special command only used by compiler. + case COMMAND_VAR_INT: + */ default: assert(0); break; @@ -2194,7 +2227,609 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) return -1; } -WRAPPER int8 CRunningScript::ProcessCommandsFrom200To299(int32 command) { EAXJMP(0x43D530); } +int8 CRunningScript::ProcessCommandsFrom200To299(int32 command) +{ + switch (command) { + /* Special commands. + case COMMAND_VAR_FLOAT: + case COMMAND_LVAR_INT: + case COMMAND_LVAR_FLOAT: + case COMMAND_LBRACKET: + case COMMAND_RBRACKET: + case COMMAND_REPEAT: + case COMMAND_ENDREPEAT: + case COMMAND_IF: + case COMMAND_IFNOT: + case COMMAND_ELSE: + case COMMAND_ENDIF: + case COMMAND_WHILE: + case COMMAND_WHILENOT: + case COMMAND_ENDWHILE: + */ + case COMMAND_ANDOR: + CollectParameters(&m_nIp, 1); + m_nAndOrState = ScriptParams[0]; + if (m_nAndOrState == ANDOR_NONE){ + m_bCondResult = false; // pointless + }else if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8){ + m_bCondResult = true; + m_nAndOrState++; + }else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8){ + m_bCondResult = false; + m_nAndOrState++; + }else{ + assert(0 && "COMMAND_ANDOR: invalid ANDOR state"); + } + return 0; + case COMMAND_LAUNCH_MISSION: + { + CollectParameters(&m_nIp, 1); + CRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]); + pNew->m_bIsMissionScript = true; + return 0; + } + case COMMAND_MISSION_HAS_FINISHED: + { + if (!m_bIsMissionScript) + return 0; + if (strcmp(m_abScriptName, "love3") == 0) /* A Drop in the Ocean */ + CPickups::RemoveAllFloatingPickups(); + CTheScripts::MissionCleanup.Process(); + return 0; + } + case COMMAND_STORE_CAR_CHAR_IS_IN: + { + CollectParameters(&m_nIp, 1); + CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(ped); + CVehicle* pCurrent = nil; + if (ped->bInVehicle) { + pCurrent = ped->m_pMyVehicle; + } + assert(pCurrent); // GetIndex(0) doesn't look good + int handle = CPools::GetVehiclePool()->GetIndex(pCurrent); + if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript){ + CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex); + if (pOld){ + CCarCtrl::RemoveFromInterestingVehicleList(pOld); + if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){ + pOld->VehicleCreatedBy = RANDOM_VEHICLE; + pOld->bIsLocked = false; + CCarCtrl::NumRandomCars++; + CCarCtrl::NumMissionCars--; + CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + } + } + CTheScripts::StoreVehicleIndex = handle; + switch (pCurrent->VehicleCreatedBy){ + case RANDOM_VEHICLE: + pCurrent->VehicleCreatedBy = MISSION_VEHICLE; + CCarCtrl::NumMissionCars++; + CCarCtrl::NumRandomCars--; + CTheScripts::StoreVehicleWasRandom = true; + CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + break; + case PARKED_VEHICLE: + pCurrent->VehicleCreatedBy = MISSION_VEHICLE; + CCarCtrl::NumMissionCars++; + CCarCtrl::NumParkedCars--; + CTheScripts::StoreVehicleWasRandom = true; + CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + break; + case MISSION_VEHICLE: + case PERMANENT_VEHICLE: + CTheScripts::StoreVehicleWasRandom = false; + break; + default: + break; + } + } + ScriptParams[0] = CTheScripts::StoreVehicleIndex; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_STORE_CAR_PLAYER_IS_IN: + { + CollectParameters(&m_nIp, 1); + CPed* ped = CWorld::Players[ScriptParams[0]].m_pPed; + assert(ped); + if (!ped->bInVehicle) + return 0; // No value written to output variable + CVehicle* pCurrent = ped->m_pMyVehicle; + assert(pCurrent); // Here pCurrent shouldn't be NULL anyway + int handle = CPools::GetVehiclePool()->GetIndex(pCurrent); + if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript) { + CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex); + if (pOld) { + CCarCtrl::RemoveFromInterestingVehicleList(pOld); + if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom) { + pOld->VehicleCreatedBy = RANDOM_VEHICLE; + pOld->bIsLocked = false; + CCarCtrl::NumRandomCars++; + CCarCtrl::NumMissionCars--; + CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + } + } + CTheScripts::StoreVehicleIndex = handle; + switch (pCurrent->VehicleCreatedBy) { + case RANDOM_VEHICLE: + pCurrent->VehicleCreatedBy = MISSION_VEHICLE; + CCarCtrl::NumMissionCars++; + CCarCtrl::NumRandomCars--; + CTheScripts::StoreVehicleWasRandom = true; + CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + break; + case PARKED_VEHICLE: + pCurrent->VehicleCreatedBy = MISSION_VEHICLE; + CCarCtrl::NumMissionCars++; + CCarCtrl::NumParkedCars--; + CTheScripts::StoreVehicleWasRandom = true; + CTheScripts::MissionCleanup.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); + break; + case MISSION_VEHICLE: + case PERMANENT_VEHICLE: + CTheScripts::StoreVehicleWasRandom = false; + break; + default: + break; + } + } + ScriptParams[0] = CTheScripts::StoreVehicleIndex; + StoreParameters(&m_nIp, 1); + return 0; + } + case COMMAND_IS_CHAR_IN_CAR: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CVehicle* pCheckedVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + CVehicle* pActualVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; + UpdateCompareFlag(pActualVehicle && pActualVehicle == pCheckedVehicle); + return 0; + } + case COMMAND_IS_PLAYER_IN_CAR: + { + CollectParameters(&m_nIp, 2); + CVehicle* pCheckedVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle == pCheckedVehicle); + return 0; + } + case COMMAND_IS_CHAR_IN_MODEL: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + CVehicle* pActualVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil; + UpdateCompareFlag(pActualVehicle && pActualVehicle->GetModelIndex() == ScriptParams[1]); + return 0; + } + case COMMAND_IS_PLAYER_IN_MODEL: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetModelIndex() == ScriptParams[1]); + return 0; + } + case COMMAND_IS_CHAR_IN_ANY_CAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(pPed->bInVehicle); + return 0; + } + case COMMAND_IS_PLAYER_IN_ANY_CAR: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; + UpdateCompareFlag(pPed->bInVehicle); + return 0; + } + case COMMAND_IS_BUTTON_PRESSED: + { + CollectParameters(&m_nIp, 2); + bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0; + if (CGame::playingIntro && ScriptParams[0] && ScriptParams[1] == 12){ /* pad1, start */ + if (CPad::GetPad(0)->GetLeftMouseJustDown() || + CPad::GetPad(0)->GetPadEnterJustDown() || + CPad::GetPad(0)->GetCharJustDown(' ')) + value = true; + } + UpdateCompareFlag(value); + return 0; + } + case COMMAND_GET_PAD_STATE: + { + CollectParameters(&m_nIp, 1); + ScriptParams[0] = GetPadState(ScriptParams[0], ScriptParams[1]); + 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: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D: + LocatePlayerCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D: + LocatePlayerCharCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CHAR_ANY_MEANS_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D: + LocateCharCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D: + case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D: + LocateCharCharCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D: + LocatePlayerCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D: + case COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: + LocatePlayerCharCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: + case COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D: + case COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D: + LocateCharCommand(command, &m_nIp); + return 0; + case COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D: + case COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D: + case COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D: + LocateCharCharCommand(command, &m_nIp); + return 0; + case COMMAND_CREATE_OBJECT: + { + CollectParameters(&m_nIp, 4); + int mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index; + CObject* pObj = new CObject(mi, 0); + pObj->ObjectCreatedBy = MISSION_OBJECT; + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= -100.0f) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + pos.z += pObj->GetDistanceFromCentreOfMassToBaseOfModel(); + pObj->GetPosition() = pos; + pObj->SetOrientation(0.0f, 0.0f, 0.0f); + pObj->GetMatrix().UpdateRW(); + pObj->UpdateRwFrame(); + CTheScripts::ClearSpaceForMissionEntity(pos, pObj); + CWorld::Add(pObj); + ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT); + return 0; + } + case COMMAND_DELETE_OBJECT: + { + CollectParameters(&m_nIp, 1); + CObject* pObj = CPools::GetObjectPool()->GetAt(ScriptParams[0]); + if (pObj){ + CWorld::Remove(pObj); + CWorld::RemoveReferencesToDeletedObject(pObj); + delete pObj; + } + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT); + return 0; + } + case COMMAND_ADD_SCORE: + CollectParameters(&m_nIp, 2); + CWorld::Players[ScriptParams[0]].m_nMoney += ScriptParams[1]; + return 0; + case COMMAND_IS_SCORE_GREATER: + CollectParameters(&m_nIp, 2); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_nMoney > ScriptParams[1]); + return 0; + case COMMAND_STORE_SCORE: + CollectParameters(&m_nIp, 1); + ScriptParams[0] = CWorld::Players[ScriptParams[0]].m_nMoney; + StoreParameters(&m_nIp, 1); + return 0; + case COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER: + { + CollectParameters(&m_nIp, 5); + CVector pos = *(CVector*)&ScriptParams[1]; + if (pos.z <= -100.0f) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + CRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4])); + return 0; + } + case COMMAND_ALTER_WANTED_LEVEL: + CollectParameters(&m_nIp, 2); + CWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevel(ScriptParams[1]); + return 0; + case COMMAND_ALTER_WANTED_LEVEL_NO_DROP: + CollectParameters(&m_nIp, 2); + CWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevelNoDrop(ScriptParams[1]); + return 0; + case COMMAND_IS_WANTED_LEVEL_GREATER: + CollectParameters(&m_nIp, 2); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->m_pWanted->m_nWantedLevel > ScriptParams[1]); + return 0; + case COMMAND_CLEAR_WANTED_LEVEL: + CollectParameters(&m_nIp, 1); + CWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevel(0); + return 0; + case COMMAND_SET_DEATHARREST_STATE: + CollectParameters(&m_nIp, 1); + m_bDeatharrestEnabled = (ScriptParams[0] == 1); + return 0; + 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); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + 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_IS_PLAYER_DEAD: + CollectParameters(&m_nIp, 1); + UpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_WASTED); + return 0; + case COMMAND_IS_CHAR_DEAD: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(!pPed || pPed->GetPedState() == PED_DIE || pPed->GetPedState() == PED_DEAD); + return 0; + } + case COMMAND_IS_CAR_DEAD: + { + CollectParameters(&m_nIp, 1); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + UpdateCompareFlag(!pVehicle || pVehicle->m_status == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater); + return 0; + } + case COMMAND_SET_CHAR_THREAT_SEARCH: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->m_fearFlags |= ScriptParams[1]; + return 0; + } + /* Not implemented. + case COMMAND_SET_CHAR_THREAT_REACTION: + */ + case COMMAND_SET_CHAR_OBJ_NO_OBJ: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + pPed->bScriptObjectiveCompleted = false; + 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_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); + if (zoneToCheck != -1) + m_nIp += 8; /* why only if zone != 1? */ + CVector pos = pPlayer->GetPos(); + CZone* pZone = CTheZones::GetZone(zoneToCheck); + UpdateCompareFlag(CTheZones::PointLiesWithinZone(pos, pZone)); + return 0; + } + case COMMAND_IS_PLAYER_PRESSING_HORN: + 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: + { + CollectParameters(&m_nIp, 2); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + 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_IS_CHAR_OBJECTIVE_PASSED: + { + CollectParameters(&m_nIp, 1); + CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); + assert(pPed); + UpdateCompareFlag(pPed->bScriptObjectiveCompleted); + return 0; + } + /* Not implemented. + case COMMAND_SET_CHAR_DRIVE_AGGRESSION: + case COMMAND_SET_CHAR_MAX_DRIVESPEED: + */ + case COMMAND_CREATE_CHAR_INSIDE_CAR: + { + CollectParameters(&m_nIp, 3); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + switch (ScriptParams[2]) { + case MI_COP: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_STREET; + break; + case MI_SWAT: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_SWAT; + break; + case MI_FBI: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_FBI; + break; + case MI_ARMY: + if (ScriptParams[1] == PEDTYPE_COP) + ScriptParams[2] = COP_ARMY; + break; + case MI_MEDIC: + if (ScriptParams[1] == PEDTYPE_EMERGENCY) + ScriptParams[2] = PEDTYPE_EMERGENCY; + break; + case MI_FIREMAN: + if (ScriptParams[1] == PEDTYPE_FIREMAN) + ScriptParams[2] = PEDTYPE_FIREMAN; + break; + default: + break; + } + CPed* pPed; + if (ScriptParams[1] == PEDTYPE_COP) + pPed = new CCopPed((eCopType)ScriptParams[2]); + else if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN) + pPed = new CEmergencyPed(ScriptParams[2]); + else + pPed = new CCivilianPed(ScriptParams[1], ScriptParams[2]); + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + pPed->m_ped_flagG2 = false; + pPed->GetPosition() = pVehicle->GetPosition(); + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + pPed->SetPedState(PED_DRIVING); + CPopulation::ms_nTotalMissionPeds++; + assert(!pVehicle->pDriver); + pVehicle->pDriver = pPed; + pVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver); + pPed->m_pMyVehicle = pVehicle; + pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); + pPed->bInVehicle = true; + pVehicle->m_status = STATUS_PHYSICS; + if (!pVehicle->IsBoat()) + pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; + pVehicle->bEngineOn = true; + pPed->bUsesCollision = false; + AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; + pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); + pPed->StopNonPartialAnims(); + pPed->m_level = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + CWorld::Add(pPed); + ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); + StoreParameters(&m_nIp, 1); + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ScriptParams[0], CLEANUP_CHAR); + return 0; + } + case COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD: + { + CollectParameters(&m_nIp, 4); + CVector pos = *(CVector*)&ScriptParams[1]; + CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]]; + if (pos.z <= -100.0f) + pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); + if (pPlayer->m_pPed->bInVehicle){ + assert(pPlayer->m_pPed->m_pMyVehicle); + if (pPlayer->m_pPed->m_pMyVehicle->bIsBus) + pPlayer->m_pPed->bRenderPedInCar = true; + if (pPlayer->m_pPed->m_pMyVehicle->pDriver == pPlayer->m_pPed){ + pPlayer->m_pPed->m_pMyVehicle->RemoveDriver(); + pPlayer->m_pPed->m_pMyVehicle->m_status = STATUS_ABANDONED; + pPlayer->m_pPed->m_pMyVehicle->bEngineOn = false; + pPlayer->m_pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + }else{ + pPlayer->m_pPed->m_pMyVehicle->RemovePassenger(pPlayer->m_pPed); + } + } + 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(); + 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_IDLE_STANCE, 100.0f); + pPlayer->m_pPed->RestartNonPartialAnims(); + AudioManager.PlayerJustLeftCar(); + pos.z += pPlayer->m_pPed->GetDistanceFromCentreOfMassToBaseOfModel(); + pPlayer->m_pPed->Teleport(pos); + CTheScripts::ClearSpaceForMissionEntity(pos, pPlayer->m_pPed); + return 0; + } + /* Not implemented. + case COMMAND_MAKE_CHAR_DO_NOTHING: + */ + default: + assert(0); + break; + } + return -1; +} + +int16 CRunningScript::GetPadState(uint16 pad, uint16 button) +{ + CPad* pPad = CPad::GetPad(pad); + switch (button){ + case 0: return pPad->NewState.LeftStickX; + case 1: return pPad->NewState.LeftStickY; + case 2: return pPad->NewState.RightStickX; + case 3: return pPad->NewState.RightStickY; + case 4: return pPad->NewState.LeftShoulder1; + case 5: return pPad->NewState.LeftShoulder2; + case 6: return pPad->NewState.RightShoulder1; + case 7: return pPad->NewState.RightShoulder2; + case 8: return pPad->NewState.DPadUp; + case 9: return pPad->NewState.DPadDown; + case 10: return pPad->NewState.DPadLeft; + case 11: return pPad->NewState.DPadRight; + case 12: return pPad->NewState.Start; + case 13: return pPad->NewState.Select; + case 14: return pPad->NewState.Square; + case 15: return pPad->NewState.Triangle; + case 16: return pPad->NewState.Cross; + case 17: return pPad->NewState.Circle; + case 18: return pPad->NewState.LeftShock; + case 19: return pPad->NewState.RightShock; + default: break; + } + 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); } @@ -2205,6 +2840,20 @@ WRAPPER int8 CRunningScript::ProcessCommandsFrom900To999(int32 command) { EAXJMP WRAPPER int8 CRunningScript::ProcessCommandsFrom1000To1099(int32 command) { EAXJMP(0x588490); } WRAPPER int8 CRunningScript::ProcessCommandsFrom1100To1199(int32 command) { EAXJMP(0x589D00); } +WRAPPER void CRunningScript::LocatePlayerCommand(int32, uint32*) { EAXJMP(0x44FE10); } +WRAPPER void CRunningScript::LocatePlayerCharCommand(int32, uint32*) { EAXJMP(0x4501E0); } +WRAPPER void CRunningScript::LocatePlayerCarCommand(int32, uint32*) { EAXJMP(0x450540); } +WRAPPER void CRunningScript::LocateCharCommand(int32, uint32*) { EAXJMP(0x450870); } +WRAPPER void CRunningScript::LocateCharCharCommand(int32, uint32*) { EAXJMP(0x450BF0); } +WRAPPER void CRunningScript::LocateCharCarCommand(int32, uint32*) { EAXJMP(0x450F30); } +WRAPPER void CRunningScript::LocateCharObjectCommand(int32, uint32*) { EAXJMP(0x451260); } +WRAPPER void CRunningScript::LocateCarCommand(int32, uint32*) { EAXJMP(0x451590); } +WRAPPER void CRunningScript::LocateSniperBulletCommand(int32, uint32*) { EAXJMP(0x4518A0); } +WRAPPER void CRunningScript::LocatePlayerInAreaCheckCommand(int32, uint32*) { EAXJMP(0x451A60); } +WRAPPER void CRunningScript::LocatePlayerInAngledAreaCheckCommand(int32, uint32*) { EAXJMP(0x451E50); } +WRAPPER void CRunningScript::LocateCharInAreaCheckCommand(int32, uint32*) { EAXJMP(0x4523B0); } +WRAPPER void CRunningScript::LocateCharInAngledAreaCheckCommand(int32, uint32*) { EAXJMP(0x452750); } + WRAPPER void CTheScripts::DrawScriptSpheres() { EAXJMP(0x44FAC0); } WRAPPER void CRunningScript::DoDeatharrestCheck() { EAXJMP(0x452A30); } WRAPPER void CTheScripts::DrawDebugSquare(float, float, float, float) { EAXJMP(0x452D00); } diff --git a/src/control/Script.h b/src/control/Script.h index 9e9d9ab6..0984952a 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -78,8 +78,8 @@ class CRunningScript uint32 m_nWakeTime; uint16 m_nAndOrState; bool m_bNotFlag; - bool m_bWBCheckEnabled; - bool m_bWBChecked; + bool m_bDeatharrestEnabled; + bool m_bDeatharrestExecuted; bool m_bMissionFlag; public: @@ -113,6 +113,40 @@ public: int8 ProcessCommandsFrom1000To1099(int32); int8 ProcessCommandsFrom1100To1199(int32); void UpdateCompareFlag(bool); + int16 GetPadState(uint16, uint16); + void LocatePlayerCommand(int32, uint32*); + void LocatePlayerCharCommand(int32, uint32*); + void LocatePlayerCarCommand(int32, uint32*); + void LocateCharCommand(int32, uint32*); + void LocateCharCharCommand(int32, uint32*); + void LocateCharCarCommand(int32, uint32*); + void LocateCharObjectCommand(int32, uint32*); + void LocateCarCommand(int32, uint32*); + void LocateSniperBulletCommand(int32, uint32*); + void LocatePlayerInAreaCheckCommand(int32, uint32*); + void LocatePlayerInAngledAreaCheckCommand(int32, uint32*); + void LocateCharInAreaCheckCommand(int32, uint32*); + void LocateCharInAngledAreaCheckCommand(int32, uint32*); +private: + enum { + ANDOR_NONE = 0, + ANDS_1 = 1, + ANDS_2, + ANDS_3, + ANDS_4, + ANDS_5, + ANDS_6, + ANDS_7, + ANDS_8, + ORS_1 = 21, + ORS_2, + ORS_3, + ORS_4, + ORS_5, + ORS_6, + ORS_7, + ORS_8 + }; }; enum { @@ -338,4 +372,7 @@ public: static float ReadFloatFromScript(uint32* pIp){ return Read2BytesFromScript(pIp) / 16.0f; } + static void ReadTextLabelFromScript(uint32* pIp, char* buf){ + strncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], 8); + } }; diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h index 55ac4439..fcc0a23f 100644 --- a/src/control/ScriptCommands.h +++ b/src/control/ScriptCommands.h @@ -208,7 +208,7 @@ enum { COMMAND_RBRACKET, COMMAND_REPEAT, COMMAND_ENDREPEAT, - COMMAND_IF_, + COMMAND_IF, COMMAND_IFNOT, COMMAND_ELSE, COMMAND_ENDIF, diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 81c7a199..d9a4c0b0 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -1,7 +1,9 @@ #include "common.h" #include "patcher.h" +#include "PlayerPed.h" #include "PlayerInfo.h" #include "Frontend.h" +#include "Vehicle.h" WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); } WRAPPER void CPlayerInfo::LoadPlayerSkin() { EAXJMP(0x4A1700); } @@ -12,3 +14,10 @@ void CPlayerInfo::SetPlayerSkin(char *skin) strncpy(m_aSkinName, skin, 32); LoadPlayerSkin(); } + +CVector& CPlayerInfo::GetPos() +{ + if (m_pPed->bInVehicle && m_pPed->m_pMyVehicle) + return m_pPed->m_pMyVehicle->GetPosition(); + return m_pPed->GetPosition(); +} diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index d8128424..edcdad27 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -70,6 +70,7 @@ public: void LoadPlayerSkin(); void AwardMoneyForExplosion(CVehicle *vehicle); void SetPlayerSkin(char* skin); + CVector& GetPos(); }; static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index f3ba8087..bba4d7d9 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -8,6 +8,7 @@ WRAPPER void CObject::ObjectDamage(float amount) { EAXJMP(0x4BB240); } WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); } +WRAPPER void CObject::Init(void) { EAXJMP(0x4BAEC0); } int16 &CObject::nNoTempObjects = *(int16*)0x95CCA2; int16 &CObject::nBodyCastHealth = *(int16*)0x5F7D4C; // 1000 @@ -41,6 +42,15 @@ CObject::CObject(void) m_pCollidingEntity = nil; } +CObject::CObject(int32 mi, bool createRW) +{ + if (createRW) + SetModelIndex(mi); + else + SetModelIndexNoCreate(mi); + Init(); +} + CObject::~CObject(void) { CRadar::ClearBlipForEntity(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(this)); diff --git a/src/objects/Object.h b/src/objects/Object.h index 0ce1a3aa..21348b52 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -66,6 +66,7 @@ public: static void operator delete(void*, size_t); CObject(void); + CObject(int32, bool); ~CObject(void); void Render(void); @@ -74,6 +75,7 @@ public: void ObjectDamage(float amount); void RefModelInfo(int32 modelId); + void Init(void); static void DeleteAllTempObjectInArea(CVector, float); }; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 0c4e33d6..c0c49751 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -47,6 +47,7 @@ WRAPPER void CPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); } WRAPPER void CPed::SetSeek(CVector, float) { EAXJMP(0x4D14B0); } WRAPPER bool CPed::Seek(void) { EAXJMP(0x4D1640); } WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); } +WRAPPER void CPed::RemoveInCarAnims(void) { EAXJMP(0x4E4E20); } bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -395,7 +396,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIsPedDieAnimPlaying = false; m_ped_flagD20 = false; m_ped_flagD40 = false; - m_bScriptObjectiveCompleted = false; + bScriptObjectiveCompleted = false; m_ped_flagE1 = false; m_ped_flagE2 = false; @@ -4038,6 +4039,18 @@ CPed::SetAmmo(eWeaponType weaponType, uint32 ammo) } } +void +CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo) +{ + if (HasWeapon(weaponType)) { + GetWeapon(weaponType).m_nAmmoTotal += ammo; + } + else { + GetWeapon(weaponType).Initialise(weaponType, ammo); + m_maxWeaponTypeAllowed++; + } +} + void CPed::SetEvasiveStep(CEntity *reason, uint8 animType) { @@ -4237,5 +4250,6 @@ STARTPATCHES InjectHook(0x4D6540, &CPed::RestoreHeadingRate, PATCH_JUMP); InjectHook(0x4C69E0, (void (CPed::*)(CEntity*)) &CPed::SetAimFlag, PATCH_JUMP); InjectHook(0x4C6960, (void (CPed::*)(float)) &CPed::SetAimFlag, PATCH_JUMP); + InjectHook(0x4CFAD0, &CPed::GrantAmmo, PATCH_JUMP); InjectHook(0x4CFB20, &CPed::SetAmmo, PATCH_JUMP); ENDPATCHES diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 7b8bc2ce..f0e222a0 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -221,7 +221,7 @@ public: uint8 bIsPedDieAnimPlaying : 1; uint8 m_ped_flagD20 : 1; uint8 m_ped_flagD40 : 1; // reset when objective changes - uint8 m_bScriptObjectiveCompleted : 1; + uint8 bScriptObjectiveCompleted : 1; uint8 m_ped_flagE1 : 1; uint8 m_ped_flagE2 : 1; @@ -503,6 +503,7 @@ public: void SetAimFlag(float angle); void SetAmmo(eWeaponType weaponType, uint32 ammo); void SetEvasiveStep(CEntity*, uint8); + void GrantAmmo(eWeaponType, uint32); // Static methods static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); @@ -559,6 +560,7 @@ public: void SetLeader(CEntity* leader); void SetPedStats(ePedStats); bool IsGangMember(void); + void RemoveInCarAnims(void); bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 6bc072ce..2d9f75c9 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -423,7 +423,7 @@ CShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn, } } - ASSERT(false); + //ASSERT(false); } void diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index c18bad25..f614b78f 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -5,7 +5,7 @@ float &fShapeLength = *(float*)0x600E78; float &fShapeTime = *(float*)0x600E7C; float &fRangeMult = *(float*)0x600E80; //0.6f; // 0.75f gta 3 -float &fTimeMult = *(float*)0xA0FCF4; +float &fTimeMult = *(float*)0x943008; float MAX_WAKE_LENGTH = 50.0f; float MIN_WAKE_INTERVAL = 1.0f; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index cc98bbe9..4bcd08db 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -377,12 +377,13 @@ CVehicle::ProcessDelayedExplosion(void) return; int tick = CTimer::GetTimeStep()/60.0f*1000.0f; + int16 prev = m_nBombTimer; if(tick > m_nBombTimer) m_nBombTimer = 0; else m_nBombTimer -= tick; - if(IsCar() && ((CAutomobile*)this)->m_bombType == CARBOMB_TIMEDACTIVE && (m_nBombTimer & 0xFE00) != 0xFE00) + if(IsCar() && ((CAutomobile*)this)->m_bombType == CARBOMB_TIMEDACTIVE && (m_nBombTimer & 0xFE00) != (prev & 0xFE00)) DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_BOMB_TICK, 0.0f); if (m_nBombTimer != 0)