From b072cbca93e9a0bded032fc79c678308d6875a58 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 29 Jun 2020 12:12:52 +0200 Subject: [PATCH 01/85] cleanup --- src/render/MBlur.cpp | 12 ++++++------ src/render/MBlur.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index 0ab9e8df..f2b94848 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -188,31 +188,31 @@ CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect) } void -CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 addalpha) +CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha) { RwRGBA color = { (RwUInt8)red, (RwUInt8)green, (RwUInt8)blue, (RwUInt8)blur }; #ifdef GTA_PS2 if( pFrontBuffer ) - OverlayRender(cam, pFrontBuffer, color, type, addalpha); + OverlayRender(cam, pFrontBuffer, color, type, bluralpha); #else if(BlurOn){ if(pFrontBuffer){ if(ms_bJustInitialised) ms_bJustInitialised = false; else - OverlayRender(cam, pFrontBuffer, color, type, addalpha); + OverlayRender(cam, pFrontBuffer, color, type, bluralpha); } RwRasterPushContext(pFrontBuffer); RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0); RwRasterPopContext(); }else{ - OverlayRender(cam, nil, color, type, addalpha); + OverlayRender(cam, nil, color, type, bluralpha); } #endif } void -CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, uint32 addalpha) +CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha) { int r, g, b, a; @@ -281,7 +281,7 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); - a = addalpha/2; + a = bluralpha/2; if(a < 30) a = 30; diff --git a/src/render/MBlur.h b/src/render/MBlur.h index 157f2882..e2e5d38c 100644 --- a/src/render/MBlur.h +++ b/src/render/MBlur.h @@ -12,6 +12,6 @@ public: static RwBool MotionBlurOpen(RwCamera *cam); static RwBool MotionBlurClose(void); static void CreateImmediateModeData(RwCamera *cam, RwRect *rect); - static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 addalpha); - static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, uint32 bluralpha); + static void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha); + static void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha); }; From 6d396ba73b8954bd44df9e1700ee1a5815956428 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 07:43:20 +0300 Subject: [PATCH 02/85] Fix MBlur --- src/render/MBlur.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index f2b94848..fe30ee0b 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -1,5 +1,9 @@ #define WITHWINDOWS +#define WITHD3D #include "common.h" +#ifndef LIBRW +#include +#endif #include "RwHelper.h" #include "Camera.h" @@ -15,6 +19,9 @@ bool CMBlur::BlurOn; static RwIm2DVertex Vertex[4]; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; +#ifndef LIBRW +extern "C" D3DCAPS8 _RwD3D8DeviceCaps; +#endif RwBool CMBlur::MotionBlurOpen(RwCamera *cam) { @@ -62,12 +69,11 @@ CMBlur::MotionBlurOpen(RwCamera *cam) if(BlurOn) { - int32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1); - int32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1); - int32 depth = RwRasterGetDepth(RwCameraGetRaster(cam)); + uint32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1); + uint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1); + uint32 depth = RwRasterGetDepth(RwCameraGetRaster(cam)); #ifndef LIBRW - extern D3DCAPS8 _RwD3D8DeviceCaps; extern DWORD _dwMemTotalVideo; if ( _RwD3D8DeviceCaps.MaxTextureWidth >= width && _RwD3D8DeviceCaps.MaxTextureHeight >= height ) { From c80bdf3a2a898297eb385659288efca43d8b106b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 07:43:55 +0300 Subject: [PATCH 03/85] Rename IsAnyButtonPressed to CheckForInput --- src/core/Pad.cpp | 9 ++++----- src/core/Pad.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 9065c8ca..851625d2 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -344,15 +344,14 @@ void AltDodoCheat(void) #endif bool -CControllerState::IsAnyButtonPressed(void) +CControllerState::CheckForInput(void) { return !!RightStickX || !!RightStickY || !!LeftStickX || !!LeftStickY || !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Triangle || !!Cross || !!Circle || !!Square || !!Start || !!Select || !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2 - || !!LeftShock || !!RightShock - || !!NetworkTalk; + || !!LeftShock || !!RightShock; } void @@ -1074,7 +1073,7 @@ void CPad::UpdatePads(void) CapturePad(0); #endif #ifdef DETECT_PAD_INPUT_SWITCH - if (GetPad(0)->PCTempJoyState.IsAnyButtonPressed()) + if (GetPad(0)->PCTempJoyState.CheckForInput()) IsAffectedByController = true; else { #endif @@ -1084,7 +1083,7 @@ void CPad::UpdatePads(void) #ifdef DETECT_PAD_INPUT_SWITCH } - if (IsAffectedByController && (GetPad(0)->PCTempKeyState.IsAnyButtonPressed() || GetPad(0)->PCTempMouseState.IsAnyButtonPressed())) + if (IsAffectedByController && (GetPad(0)->PCTempKeyState.CheckForInput() || GetPad(0)->PCTempMouseState.CheckForInput())) IsAffectedByController = false; #endif diff --git a/src/core/Pad.h b/src/core/Pad.h index 6f20571f..8c3bc752 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -29,7 +29,7 @@ public: float GetRightStickX(void) { return RightStickX/32767.0f; }; float GetRightStickY(void) { return RightStickY/32767.0f; }; - bool IsAnyButtonPressed(); + bool CheckForInput(); void Clear(void); }; VALIDATE_SIZE(CControllerState, 0x2A); From 6f81e84bd41056cbf38aeaf9b20bd4493a6ffc5f Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 07:44:51 +0300 Subject: [PATCH 04/85] Restore original code of CControllerState::CheckForInput --- src/core/Pad.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 99b9c8a8..97cc1786 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -518,9 +518,12 @@ void FlyingFishCheat(void) bool CControllerState::CheckForInput(void) { - return !!LeftStickX || !!LeftStickY || !!RightStickX || !!RightStickY || !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2 || - !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight || !!Start || !!Select || !!Square || !!Triangle || !!Cross || !!Circle || !!LeftShock || - !!RightShock; + return !!RightStickX || !!RightStickY || !!LeftStickX || !!LeftStickY + || !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight + || !!Triangle || !!Cross || !!Circle || !!Square + || !!Start || !!Select + || !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2 + || !!LeftShock || !!RightShock; } void From 87fa69385c172305a348f26f1592f17a73cd538d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 07:48:09 +0300 Subject: [PATCH 05/85] remove TheText.Load() from CGame::Initialise --- src/core/Game.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index e3ef8aed..0ba9eb67 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -316,7 +316,6 @@ bool CGame::Initialise(const char* datFile) COcclusion::Init(); CCollision::Init(); CSetPieces::Init(); - TheText.Load(); CTheZones::Init(); CUserDisplay::Init(); CMessages::Init(); From a15f3ddb8b0e80fd62ba462903ae323b421c51a4 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 08:08:50 +0300 Subject: [PATCH 06/85] Fix glfw build --- src/render/MBlur.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index fe30ee0b..ec811e56 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -1,5 +1,7 @@ #define WITHWINDOWS +#ifndef LIBRW #define WITHD3D +#endif #include "common.h" #ifndef LIBRW #include From da93b0a078b728051bb3ad185956a6715f397c2d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 30 Jun 2020 19:06:58 +0300 Subject: [PATCH 07/85] Audio fixes --- src/audio/AudioLogic.cpp | 36 +++++++++++++++--------------------- src/audio/AudioManager.cpp | 4 ++-- src/audio/AudioManager.h | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 77e3a6b5..d3d9f74d 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -157,7 +157,7 @@ cAudioManager::PostInitialiseGameSpecificSetup() m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_bIsPlaying = false; m_sMissionAudio.m_bIsPlayed = false; m_sMissionAudio.m_bPredefinedProperties = true; m_sMissionAudio.m_nMissionAudioCounter = 0; @@ -961,15 +961,15 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) } break; case 'F': - if (automobile->m_aWheelState[VEHWHEEL_FRONT_LEFT] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[CARWHEEL_FRONT_LEFT] == WHEEL_STATE_SPINNING) traction += 0.1f; - if (automobile->m_aWheelState[VEHWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[CARWHEEL_FRONT_RIGHT] == WHEEL_STATE_SPINNING) traction += 0.1f; break; case 'R': - if (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING) traction += 0.1f; - if (automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING) + if (automobile->m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING) traction += 0.1f; break; } @@ -1250,12 +1250,12 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * lostTraction = true; break; case 'F': - if ((automobile->m_aWheelState[VEHWHEEL_FRONT_LEFT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL) && - (automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) + if ((automobile->m_aWheelState[CARWHEEL_FRONT_LEFT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[CARWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL) && + (automobile->m_aWheelState[CARWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL || automobile->m_aWheelState[CARWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) lostTraction = true; break; case 'R': - if ((automobile->m_aWheelState[VEHWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL) || (automobile->m_aWheelState[VEHWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) + if ((automobile->m_aWheelState[CARWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL) || (automobile->m_aWheelState[CARWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)) lostTraction = true; break; } @@ -2426,10 +2426,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) AddSampleToRequestedQueue(); } if (FindPlayerVehicle() == params->m_pVehicle) { - if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) - padAccelerate = Pads[0].GetBrake(); - else - padAccelerate = Pads[0].GetAccelerate(); + padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake()); padRelativeAccerate = padAccelerate / 255; emittingVol = (100.f * padRelativeAccerate) + 15; m_sQueueSample.m_nFrequency = (3000.f * padRelativeAccerate) + 6000; @@ -2468,10 +2465,7 @@ cAudioManager::ProcessBoatEngine(cVehicleParams *params) m_sQueueSample.m_bRequireReflection = false; } else { if (FindPlayerVehicle() == params->m_pVehicle) { - if (Pads[0].GetAccelerate() <= Pads[0].GetBrake()) - padAccelerate = Pads[0].GetBrake(); - else - padAccelerate = Pads[0].GetAccelerate(); + padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake()); if (padAccelerate <= 20) { emittingVol = 45 - 45 * padAccelerate / 40; m_sQueueSample.m_nFrequency = 100 * padAccelerate + 11025; @@ -8672,11 +8666,11 @@ cAudioManager::PreloadMissionAudio(Const char *name) m_sMissionAudio.m_nSampleIndex = missionAudioSfx; m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_bIsPlaying = false; m_sMissionAudio.m_nMissionAudioCounter = m_nTimeSpent * SampleManager.GetStreamedFileLength(missionAudioSfx) / 1000; m_sMissionAudio.m_nMissionAudioCounter *= 4; m_sMissionAudio.m_bIsPlayed = false; - m_sMissionAudio.m_bPredefinedProperties = 1; + m_sMissionAudio.m_bPredefinedProperties = true; g_bMissionAudioLoadFailed = false; } } @@ -8726,7 +8720,7 @@ cAudioManager::ClearMissionAudio() m_sMissionAudio.m_nSampleIndex = NO_SAMPLE; m_sMissionAudio.m_nLoadingStatus = LOADING_STATUS_NOT_LOADED; m_sMissionAudio.m_nPlayStatus = PLAY_STATUS_STOPPED; - m_sMissionAudio.field_22 = 0; + m_sMissionAudio.m_bIsPlaying = false; m_sMissionAudio.m_bIsPlayed = false; m_sMissionAudio.m_bPredefinedProperties = true; m_sMissionAudio.m_nMissionAudioCounter = 0; @@ -8819,7 +8813,7 @@ cAudioManager::ProcessMissionAudio() m_sMissionAudio.m_nMissionAudioCounter = 0; } } - } else if (m_sMissionAudio.field_22) { + } else if (m_sMissionAudio.m_bIsPlaying) { if (SampleManager.IsStreamPlaying(1) || m_nUserPause || m_nPreviousUserPause) { if (m_nUserPause) SampleManager.PauseStream(1, 1); @@ -8839,7 +8833,7 @@ cAudioManager::ProcessMissionAudio() break; nCheckPlayingDelay = 0; } - m_sMissionAudio.field_22 = 1; + m_sMissionAudio.m_bIsPlaying = true; } break; default: diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 757254e6..58483602 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -436,7 +436,7 @@ cAudioManager::ServiceSoundEffects() } ClearActiveSamples(); } - m_nActiveSampleQueue = m_nActiveSampleQueue != 1; + m_nActiveSampleQueue = m_nActiveSampleQueue == 1 ? 0 : 1; ProcessReverb(); ProcessSpecial(); ClearRequestedQueue(); @@ -686,7 +686,7 @@ cAudioManager::AddReleasingSounds() { bool toProcess[44]; // why not 27? - int8 queue = m_nActiveSampleQueue == 0; + int8 queue = m_nActiveSampleQueue == 0 ? 1 : 0; for (int32 i = 0; i < m_SampleRequestQueuesStatus[queue]; i++) { tSound &sample = m_asSamples[queue][m_abSampleQueueIndexTable[queue][i]]; diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 52c26552..8c579ca8 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -103,7 +103,7 @@ public: int32 m_nSampleIndex; uint8 m_nLoadingStatus; uint8 m_nPlayStatus; - uint8 field_22; // todo find a name + bool m_bIsPlaying; int32 m_nMissionAudioCounter; bool m_bIsPlayed; }; From 779d4e02a43fe19e8a0509a9beccf24d9083ebe5 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 1 Jul 2020 15:12:25 +0300 Subject: [PATCH 08/85] little fix --- src/control/Script.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 934571ef..40bbd0cf 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1356,7 +1356,8 @@ static void PrintToLog(const char* format, ...) printf("%s", tmp); #if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2 - fwrite(tmp, 1, strlen(tmp), dbg_log); + if (dbg_log) + fwrite(tmp, 1, strlen(tmp), dbg_log); #endif } From eda50bc32bafaea788def2f00f4ac036329dd46c Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 1 Jul 2020 15:28:43 +0300 Subject: [PATCH 09/85] Restored beta police system(disabled), fixes from miami, debug info for CFO crash (#639) --- src/control/CarAI.cpp | 4 +- src/control/Phones.cpp | 89 ++++++++-- src/control/Phones.h | 7 +- src/control/Script.cpp | 5 + src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 12 +- src/core/Wanted.cpp | 36 +++- src/core/config.h | 4 +- src/core/re3.cpp | 4 - src/extras/frontendoption.cpp | 8 +- src/peds/CivilianPed.cpp | 78 ++++++-- src/peds/Ped.cpp | 322 +++++++++++++++++++++++----------- src/peds/Ped.h | 15 +- src/weapons/Weapon.cpp | 2 +- 14 files changed, 430 insertions(+), 158 deletions(-) diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index b3fc85ae..41dcaa59 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -381,7 +381,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (flatSpeed < SQR(0.018f) && CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nAntiReverseTimer > 2000){ pVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE; if (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE && - pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE || pVehicle->VehicleCreatedBy == RANDOM_VEHICLE) + pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE || pVehicle->VehicleCreatedBy == MISSION_VEHICLE) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1500; else pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 750; @@ -406,7 +406,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400; } } - if (pVehicle->GetUp().z < 0.7f){ + if (pVehicle->GetUp().z < -0.7f){ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; } diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index b89641f9..14e9dc45 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -34,15 +34,14 @@ CPed *CPhoneInfo::pCallBackPed; // ped who picking up the phone (reset after pic after 60 seconds of last phone pick-up. */ -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef PEDS_REPORT_CRIMES_ON_PHONE CPed* crimeReporters[NUMPHONES] = {}; bool isPhoneAvailable(int m_phoneId) { - return gPhoneInfo.m_aPhones[m_phoneId].m_nState == PHONE_STATE_FREE && - (crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || !crimeReporters[m_phoneId]->bRunningToPhone || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_IDLE || + return crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_IDLE || crimeReporters[m_phoneId]->m_nLastPedState != PED_SEEK_POS && - (crimeReporters[m_phoneId]->m_nPedState != PED_MAKE_CALL && crimeReporters[m_phoneId]->m_nPedState != PED_FACE_PHONE && crimeReporters[m_phoneId]->m_nPedState != PED_SEEK_POS)); + (crimeReporters[m_phoneId]->m_nPedState != PED_MAKE_CALL && crimeReporters[m_phoneId]->m_nPedState != PED_FACE_PHONE && crimeReporters[m_phoneId]->m_nPedState != PED_SEEK_POS); } #endif @@ -162,13 +161,14 @@ CPhoneInfo::FindNearestFreePhone(CVector *pos) int nearestPhoneId = -1; float nearestPhoneDist = 60.0f; - for (int phoneId = 0; phoneId < m_nMax; phoneId++) { + for (int phoneId = 0; phoneId < m_nMax; phoneId++) { - if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE -#ifdef TOGGLEABLE_BETA_FEATURES - && isPhoneAvailable(phoneId) +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (isPhoneAvailable(phoneId)) +#else + if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE) #endif - ) { + { float phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D(); if (phoneDist < nearestPhoneDist) { @@ -213,8 +213,42 @@ void CPhoneInfo::Load(uint8 *buf, uint32 size) { INITSAVEBUF - m_nMax = ReadSaveBuf(buf); - m_nScriptPhonesMax = ReadSaveBuf(buf); + int max = ReadSaveBuf(buf); + int scriptPhonesMax = ReadSaveBuf(buf); + +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + m_nMax = Min(NUMPHONES, max); + m_nScriptPhonesMax = 0; + + bool ignoreOtherPhones = false; + + // We can do it without touching saves. We'll only load script phones, others are already loaded in Initialise + for (int i = 0; i < 50; i++) { + CPhone phoneToLoad = ReadSaveBuf(buf); + + if (ignoreOtherPhones) + continue; + + if (i < scriptPhonesMax) { + if (i >= m_nMax) { + assert(0 && "Number of phones used by script exceeds the NUMPHONES or the stored phones in save file. Ignoring some phones"); + ignoreOtherPhones = true; + continue; + } + SwapPhone(phoneToLoad.m_vecPos.x, phoneToLoad.m_vecPos.y, i); + + m_aPhones[i] = phoneToLoad; + // It's saved as building pool index in save file, convert it to true entity + if (m_aPhones[i].m_pEntity) { + m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1); + } + } else + ignoreOtherPhones = true; + } +#else + m_nMax = max; + m_nScriptPhonesMax = scriptPhonesMax; + for (int i = 0; i < NUMPHONES; i++) { m_aPhones[i] = ReadSaveBuf(buf); // It's saved as building pool index in save file, convert it to true entity @@ -222,6 +256,7 @@ INITSAVEBUF m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1); } } +#endif VALIDATESAVEBUF(size) } @@ -259,6 +294,31 @@ CPhoneInfo::SetPhoneMessage_Repeatedly(int phoneId, wchar *msg1, wchar *msg2, wc } } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +void +CPhoneInfo::SwapPhone(float xPos, float yPos, int into) +{ + // "into" should be in 0 - m_nScriptPhonesMax range + int nearestPhoneId = -1; + CVector pos(xPos, yPos, 0.0f); + float nearestPhoneDist = 1.0f; + + for (int phoneId = m_nScriptPhonesMax; phoneId < m_nMax; phoneId++) { + float phoneDistance = (m_aPhones[phoneId].m_vecPos - pos).Magnitude2D(); + if (phoneDistance < nearestPhoneDist) { + nearestPhoneDist = phoneDistance; + nearestPhoneId = phoneId; + } + } + m_aPhones[nearestPhoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED; + + CPhone oldPhone = m_aPhones[into]; + m_aPhones[into] = m_aPhones[nearestPhoneId]; + m_aPhones[nearestPhoneId] = oldPhone; + m_nScriptPhonesMax++; +} +#endif + int CPhoneInfo::GrabPhone(float xPos, float yPos) { @@ -300,6 +360,7 @@ CPhoneInfo::Initialise(void) CBuilding *building = pool->GetSlot(i); if (building) { if (building->GetModelIndex() == MI_PHONEBOOTH1) { + assert(m_nMax < ARRAY_SIZE(m_aPhones) && "NUMPHONES should be increased"); CPhone *maxPhone = &m_aPhones[m_nMax]; maxPhone->m_nState = PHONE_STATE_FREE; maxPhone->m_vecPos = building->GetPosition(); @@ -317,7 +378,11 @@ CPhoneInfo::Save(uint8 *buf, uint32 *size) INITSAVEBUF WriteSaveBuf(buf, m_nMax); WriteSaveBuf(buf, m_nScriptPhonesMax); - for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + for (int phoneId = 0; phoneId < 50; phoneId++) { // We can do it without touching saves +#else + for (int phoneId = 0; phoneId < NUMPHONES; phoneId++) { +#endif CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]); // Convert entity pointer to building pool index while saving diff --git a/src/control/Phones.h b/src/control/Phones.h index 14d47ed1..02c9a928 100644 --- a/src/control/Phones.h +++ b/src/control/Phones.h @@ -61,6 +61,9 @@ public: void Initialise(void); void Shutdown(void); void Update(void); +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + void SwapPhone(float xPos, float yPos, int into); +#endif }; extern CPhoneInfo gPhoneInfo; @@ -68,7 +71,7 @@ extern CPhoneInfo gPhoneInfo; void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg); void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef PEDS_REPORT_CRIMES_ON_PHONE extern CPed *crimeReporters[NUMPHONES]; bool isPhoneAvailable(int); -#endif \ No newline at end of file +#endif diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 40bbd0cf..7354df22 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3297,7 +3297,12 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) ped->ClearAll(); int8 path = ScriptParams[1]; if (ScriptParams[1] < 0 || ScriptParams[1] > 7) + // Max number GetRandomNumberInRange returns is max-1 +#ifdef FIX_BUGS + path = CGeneral::GetRandomNumberInRange(0, 8); +#else path = CGeneral::GetRandomNumberInRange(0, 7); +#endif ped->SetWanderPath(path); return 0; } diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index d038c423..3e5a82a9 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -1688,7 +1688,7 @@ CCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, fl if(Length < 0.002f) Length = 0.002f; Beta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y); -#ifdef TOGGLEABLE_BETA_FEATURES +#if 1 // This is completely made up but Bill's cam manipulates an angle before calling this // and otherwise calculating Beta doesn't make much sense. Beta += fBillsBetaOffset; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 3aefa005..3400d10f 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1217,8 +1217,10 @@ CMenuManager::Draw() rightText = option.drawFunc(&isOptionDisabled); } } - } else + } else { + debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options is borked"); + } break; #endif @@ -4775,8 +4777,10 @@ CMenuManager::ProcessButtonPresses(void) } else if (option.type == FEOPTION_GOBACK) { goBack = true; } - } else + } else { + debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options are borked"); + } break; #endif @@ -4998,8 +5002,10 @@ CMenuManager::ProcessButtonPresses(void) } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } - else + else { + debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options are borked"); + } break; #endif diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index 7508c9f4..909674d0 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -161,7 +161,11 @@ CWanted::RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool po void CWanted::RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare) { - if(!AddCrimeToQ(type, id, coors, false, policeDoesntCare)) +#if defined FIX_SIGNIFICANT_BUGS || defined PEDS_REPORT_CRIMES_ON_PHONE + if (!AddCrimeToQ(type, id, coors, true, policeDoesntCare)) +#else + if (!AddCrimeToQ(type, id, coors, false, policeDoesntCare)) +#endif ReportCrimeNow(type, coors, policeDoesntCare); } @@ -219,6 +223,9 @@ CWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesnt chaos *= 0.333f; switch(type){ case CRIME_POSSESSION_GUN: +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + m_nChaos += 5.0f*chaos; +#endif break; case CRIME_HIT_PED: m_nChaos += 5.0f*chaos; @@ -440,6 +447,30 @@ CWanted::Reset(void) Initialise(); } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +bool +CrimeShouldBeReportedOnPhone(eCrimeType crime) +{ + switch (crime) { + case CRIME_POSSESSION_GUN: + case CRIME_HIT_PED: + case CRIME_HIT_COP: + case CRIME_SHOOT_PED: + case CRIME_SHOOT_COP: + case CRIME_STEAL_CAR: + case CRIME_RECKLESS_DRIVING: + case CRIME_RUNOVER_PED: + case CRIME_RUNOVER_COP: + case CRIME_PED_BURNED: + case CRIME_COP_BURNED: + case CRIME_VEHICLE_BURNED: + return true; + default: + return false; + } +} +#endif + void CWanted::UpdateCrimesQ(void) { @@ -447,6 +478,9 @@ CWanted::UpdateCrimesQ(void) CCrimeBeingQd &crime = m_aCrimes[i]; if (crime.m_nType != CRIME_NONE) { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (!CrimeShouldBeReportedOnPhone(crime.m_nType)) +#endif if (CTimer::GetTimeInMilliseconds() > crime.m_nTime + 500 && !crime.m_bReported) { ReportCrimeNow(crime.m_nType, crime.m_vecPosn, crime.m_bPoliceDoesntCare); crime.m_bReported = true; diff --git a/src/core/config.h b/src/core/config.h index ed36a493..839fbc34 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -190,7 +190,6 @@ enum Config { #endif #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more -#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things #define MORE_LANGUAGES // Add more translations to the game #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible @@ -242,7 +241,7 @@ enum Config { # define MISSION_REPLAY // mobile feature #endif //#define SIMPLIER_MISSIONS // apply simplifications from mobile -#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT +//#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log #ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT @@ -267,6 +266,7 @@ enum Config { #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle // #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER +//#define PEDS_REPORT_CRIMES_ON_PHONE // Camera //#define PS2_CAM_TRANSITION // old way of transitioning between cam modes diff --git a/src/core/re3.cpp b/src/core/re3.cpp index b21bff58..a2edcdee 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -484,11 +484,7 @@ DebugMenuPopulate(void) #ifdef CUSTOM_FRONTEND_OPTIONS DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions); #endif -#ifdef TOGGLEABLE_BETA_FEATURES DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); - DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", &CPed::bMakePedsRunToPhonesToReportCrimes, nil); -#endif - DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index 6ab2801c..bfeca848 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -68,9 +68,11 @@ int8 RegisterNewOption(int screen) { numCustomFrontendOptions++; if (numCustomFrontendOptions == 1) - customFrontendOptions = (FrontendOption*)malloc(numCustomFrontendOptions * sizeof(FrontendOption)); - else - customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, numCustomFrontendOptions * sizeof(FrontendOption)); + customFrontendOptions = (FrontendOption*)malloc(5 * sizeof(FrontendOption)); + else if (numCustomFrontendOptions % 5 == 1) + customFrontendOptions = (FrontendOption*)realloc(customFrontendOptions, (numCustomFrontendOptions + 4) * sizeof(FrontendOption)); + + assert(customFrontendOptions != nil && "Custom frontend options can't be allocated"); uint8 nth = GetNumberOfMenuOptions(screen); if (optionCursor < 0) { diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 2dee0397..b1b6ca82 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -10,6 +10,30 @@ #include "Vehicle.h" #include "SurfaceTable.h" +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +eCrimeType +EventTypeToCrimeType(eEventType event) +{ + eCrimeType crime; + switch (event) { + case EVENT_ASSAULT: crime = CRIME_HIT_PED; break; + case EVENT_RUN_REDLIGHT: crime = CRIME_RUN_REDLIGHT; break; + case EVENT_ASSAULT_POLICE: crime = CRIME_HIT_COP; break; + case EVENT_GUNSHOT: crime = CRIME_POSSESSION_GUN; break; + case EVENT_STEAL_CAR: crime = CRIME_STEAL_CAR; break; + case EVENT_HIT_AND_RUN: crime = CRIME_RUNOVER_PED; break; + case EVENT_HIT_AND_RUN_COP: crime = CRIME_RUNOVER_COP; break; + case EVENT_SHOOT_PED: crime = CRIME_SHOOT_PED; break; + case EVENT_SHOOT_COP: crime = CRIME_SHOOT_COP; break; + case EVENT_PED_SET_ON_FIRE: crime = CRIME_PED_BURNED; break; + case EVENT_COP_SET_ON_FIRE: crime = CRIME_COP_BURNED; break; + case EVENT_CAR_SET_ON_FIRE: crime = CRIME_VEHICLE_BURNED; break; + default: crime = CRIME_NONE; break; + } + return crime; +} +#endif + CCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype) { SetModelIndex(mi); @@ -113,25 +137,20 @@ CCivilianPed::CivilianAI(void) investigateDeadPed = false; } -#ifdef TOGGLEABLE_BETA_FEATURES - eCrimeType crime = (((CPed*)m_pEventEntity)->m_ped_flagI40 ? - (((CPed*)m_pEventEntity)->m_nPedType == PEDTYPE_COP ? CRIME_RUNOVER_COP : CRIME_RUNOVER_PED) : - (((CPed*)m_pEventEntity)->m_nPedType == PEDTYPE_COP ? CRIME_SHOOT_COP : CRIME_SHOOT_PED)); - bool eligibleToReport = bMakePedsRunToPhonesToReportCrimes && killerOfDeadPed && killerOfDeadPed->IsPed() && ((CPed*)killerOfDeadPed)->IsPlayer() && - m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + int32 eventId = CheckForPlayerCrimes((CPed*)m_pEventEntity); + eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type)); + bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear; if (IsGangMember() || !eligibleToReport || !RunToReportCrime(crime)) #endif if (investigateDeadPed) SetInvestigateEvent(EVENT_DEAD_PED, CVector2D(m_pEventEntity->GetPosition()), 1.0f, 20000, 0.0f); } else { -#ifdef TOGGLEABLE_BETA_FEATURES - CEntity* killerOfDeadPed = ((CPed*)m_pEventEntity)->m_threatEntity; - eCrimeType crime = (((CPed*)m_pEventEntity)->m_ped_flagI40 ? - (((CPed*)m_pEventEntity)->m_nPedType == PEDTYPE_COP ? CRIME_RUNOVER_COP : CRIME_RUNOVER_PED) : - (((CPed*)m_pEventEntity)->m_nPedType == PEDTYPE_COP ? CRIME_SHOOT_COP : CRIME_SHOOT_PED)); - bool eligibleToReport = bMakePedsRunToPhonesToReportCrimes && killerOfDeadPed && killerOfDeadPed->IsPed() && ((CPed*)killerOfDeadPed)->IsPlayer() && - m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + int32 eventId = CheckForPlayerCrimes((CPed*)m_pEventEntity); + eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type)); + bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness && m_pedStats->m_temper <= m_pedStats->m_fear; if(!eligibleToReport || !RunToReportCrime(crime)) #endif { @@ -165,22 +184,48 @@ CCivilianPed::CivilianAI(void) } } } else { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + bool youShouldRunEventually = false; + bool dontGoToPhone = false; +#endif if (m_threatEntity && m_threatEntity->IsPed()) { CPed *threatPed = (CPed*)m_threatEntity; if (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) { if (threatPed->GetWeapon(m_currentWeapon).IsTypeMelee() || !GetWeapon()->IsTypeMelee()) { if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) { if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + dontGoToPhone = true; +#endif SetFindPathAndFlee(m_threatEntity, 10000); } } else { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + dontGoToPhone = true; +#endif SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity); } } } else { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + youShouldRunEventually = true; +#else + SetFindPathAndFlee(m_threatEntity, 10000, true); +#endif + } + } + +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (!dontGoToPhone) { + int32 eventId = CheckForPlayerCrimes(nil); + eCrimeType crime = (eventId == -1 ? CRIME_NONE : EventTypeToCrimeType(gaEvent[eventId].type)); + bool eligibleToReport = crime != CRIME_NONE && m_pedStats->m_fear <= m_pedStats->m_lawfulness; + + if ((!eligibleToReport || !RunToReportCrime(crime)) && youShouldRunEventually) { SetFindPathAndFlee(m_threatEntity, 10000, true); } } +#endif } } @@ -217,15 +262,18 @@ CCivilianPed::ProcessControl(void) if (Seek()) { if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) { m_pNextPathNode = nil; -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef PEDS_REPORT_CRIMES_ON_PHONE } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) { if (!isPhoneAvailable(m_phoneId)) { RestorePreviousState(); - crimeReporters[m_phoneId] = nil; + if (crimeReporters[m_phoneId] == this) + crimeReporters[m_phoneId] = nil; + m_phoneId = -1; bRunningToPhone = false; } else { crimeReporters[m_phoneId] = this; + m_facePhoneStart = true; m_nPedState = PED_FACE_PHONE; } #else diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index cf254cf4..2f3931d3 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -118,9 +118,8 @@ void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->N void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((CPed*)p); } -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef DEBUGMENU bool CPed::bPopHeadsOnHeadshot = false; -bool CPed::bMakePedsRunToPhonesToReportCrimes = false; #endif CPed::~CPed(void) @@ -683,7 +682,7 @@ CPed::RemoveBodyPart(PedNode nodeId, int8 direction) if(!IsClumpSkinned(GetClump())) #endif { -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef DEBUGMENU if (bPopHeadsOnHeadshot || nodeId != PED_HEAD) #else if (nodeId != PED_HEAD) @@ -2014,18 +2013,19 @@ CPed::SortPeds(CPed **list, int min, int max) void CPed::BuildPedLists(void) { - if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) % 16) { + if ((CTimer::GetFrameCounter() + m_randomSeed) % 16) { for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) { + bool removePed = false; if (m_nearPeds[i]) { if (m_nearPeds[i]->IsPointerValid()) { float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D(); - if (distSqr < 900.0f) { - i++; - continue; - } - } - + if (distSqr > 900.0f) + removePed = true; + } else + removePed = true; + } + if (removePed) { // If we arrive here, the ped we're checking isn't "near", so we should remove it. for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) { m_nearPeds[j] = m_nearPeds[j + 1]; @@ -2033,7 +2033,7 @@ CPed::BuildPedLists(void) } // Above loop won't work when it's 9, so we need to empty slot 9. m_nearPeds[9] = nil; - m_numNearPeds--; + m_numNearPeds--; } else i++; } @@ -3078,47 +3078,106 @@ CPed::CheckAroundForPossibleCollisions(void) } } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +void +ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg) +{ + CPed* ped = (CPed*)arg; + ped->m_nMoveState = PEDMOVE_STILL; + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); + + if (assoc->blendAmount > 0.5f && ped) { + CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); + } +} + +void +ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg) +{ + assoc->flags |= ASSOC_DELETEFADEDOUT; + assoc->blendDelta = -1000.0f; + CPed* ped = (CPed*)arg; + + if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) { + crimeReporters[ped->m_phoneId] = nil; + gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE; + ped->m_phoneId = -1; + } + + if (assoc->blendAmount > 0.5f) + ped->bUpdateAnimHeading = true; + + ped->SetWanderPath(CGeneral::GetRandomNumber() & 7); +} +#endif + bool CPed::MakePhonecall(void) { -#ifdef TOGGLEABLE_BETA_FEATURES - if (bMakePedsRunToPhonesToReportCrimes) - if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) { +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) { - FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(), - (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)((CPed*)m_pEventEntity)->m_threatEntity), false); - bRunningToPhone = false; - } + FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(), + (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false); + + if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN) + FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1); + + bRunningToPhone = false; + } #endif if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer) return false; - SetIdle(); - gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; -#ifdef TOGGLEABLE_BETA_FEATURES - crimeReporters[m_phoneId] = nil; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK); + if (talkAssoc && talkAssoc->blendAmount > 0.5f) { + CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f); + endAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + endAssoc->SetFinishCallback(ReportPhonePutDownCB, this); + } #endif + SetIdle(); + + gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; +#ifndef PEDS_REPORT_CRIMES_ON_PHONE m_phoneId = -1; +#endif + + // Because SetWanderPath is now done async in ReportPhonePutDownCB +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + return false; +#else return true; +#endif } bool CPed::FacePhone(void) { - // FIX: This function was broken since it's left unused early in development. -#ifdef FIX_BUGS + // This function was broken since it's left unused early in development. +#ifdef PEDS_REPORT_CRIMES_ON_PHONE float phoneDir = CGeneral::GetRadianAngleBetweenPoints( gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y, GetPosition().x, GetPosition().y); - SetLookFlag(phoneDir, false); - bool turnDone = TurnBody(); - if (turnDone) { - SetIdle(); - ClearLookFlag(); - m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; + if (m_facePhoneStart) { + m_lookTimer = 0; + SetLookFlag(phoneDir, true); + m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000; + m_facePhoneStart = false; } - return turnDone; + + if (bIsLooking && TurnBody()) { + ClearLookFlag(); + SetIdle(); + m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000; + CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f); + assoc->SetFinishCallback(ReportPhonePickUpCB, this); + return true; + } + + return false; #else float currentRot = RADTODEG(m_fRotationCur); float phoneDir = CGeneral::GetRadianAngleBetweenPoints( @@ -3165,6 +3224,63 @@ CPed::CheckForDeadPeds(void) return nil; } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE +// returns event id, parameter is optional +int32 +CPed::CheckForPlayerCrimes(CPed *victim) +{ + int i; + float dist; + float mindist = 60.0f; + CPlayerPed *player = FindPlayerPed(); + int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0); + int event = -1; + + for (i = 0; i < NUMEVENTS; i++) { + if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE) + continue; + + // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc. + if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION) + continue; + + if (victim && gaEvent[i].entityRef != victimRef) + continue; + + if (gaEvent[i].criminal != player) + continue; + + dist = (GetPosition() - gaEvent[i].posn).Magnitude(); + if (dist < mindist) { + mindist = dist; + event = i; + } + } + + if (event != -1) { + if (victim) { + m_victimOfPlayerCrime = victim; + } else { + switch (gaEvent[event].entityType) { + case EVENT_ENTITY_PED: + m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_VEHICLE: + m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef); + break; + case EVENT_ENTITY_OBJECT: + m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef); + break; + default: + break; + } + } + } + + return event; +} +#endif + bool CPed::CheckForExplosions(CVector2D &area) { @@ -4542,6 +4658,14 @@ CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump) wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false); } } +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + else if (reason->IsVehicle()) { + if (veh->pDriver && veh->pDriver->IsPlayer()) { + CWanted* wanted = FindPlayerPed()->m_pWanted; + wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false); + } + } +#endif } void @@ -5384,61 +5508,15 @@ CPed::CollideWithPed(CPed *collideWith) SetDirectionToWalkAroundObject(collideWith); } } else { -#ifdef VC_PED_PORTS - if (FindPlayerPed() != m_pedInObjective - || m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT - || collideWith == m_pedInObjective) { -#endif - if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper - || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) && - (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) { - SetDirectionToWalkAroundObject(collideWith); - if (!weAreMissionChar) - Say(SOUND_PED_CHAT); - } else { - SetEvasiveStep(collideWith, 2); - } -#ifdef VC_PED_PORTS - } else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee() - && collideWith->m_pedInObjective == m_pedInObjective) { - - int colliderIsAtPlayerSafePosID = -1; - int weAreAtPlayerSafePosID = -1; - for (int i = 0; i < ARRAY_SIZE(((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos); i++) { - CPed *pedAtSafePos = ((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos[i]; - if (pedAtSafePos == this) { - weAreAtPlayerSafePosID = i; - } else if (pedAtSafePos == collideWith) { - colliderIsAtPlayerSafePosID = i; - } - } - bool weAreCloserToTargetThenCollider = false; - if ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D()) - weAreCloserToTargetThenCollider = true; - - if (weAreAtPlayerSafePosID <= 0 || weAreCloserToTargetThenCollider) { - if (!weAreCloserToTargetThenCollider) { - int time = 300; - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; - } - } else if (colliderIsAtPlayerSafePosID <= 0) { - if (collideWith->m_pedInObjective == FindPlayerPed()) { - // VC specific - // ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this); - int time = 500; - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; - } - } else { - int time = 300; - SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; - } - } else { + if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper + || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) && + (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) { SetDirectionToWalkAroundObject(collideWith); + if (!weAreMissionChar) + Say(SOUND_PED_CHAT); + } else { + SetEvasiveStep(collideWith, 2); } -#endif } } else { if (m_pedStats->m_temper <= m_pedStats->m_fear @@ -5452,12 +5530,20 @@ CPed::CollideWithPed(CPed *collideWith) } else { TurnBody(); SetAttack(collideWith); +#ifdef VC_PED_PORTS + m_fRotationCur = 0.3f + m_fRotationCur; + m_fRotationDest = m_fRotationCur; +#endif } m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450); } } } else { +#ifdef VC_PED_PORTS + if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { +#else if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { +#endif if (heLooksToUs) { SetEvasiveStep(collideWith, 1); m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; @@ -5466,7 +5552,11 @@ CPed::CollideWithPed(CPed *collideWith) if (m_pedStats != collideWith->m_pedStats) { - if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper) { + if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper +#ifdef VC_PED_PORTS + || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer +#endif + ) { if (collideWith->IsPlayer()) { // He's on our right side @@ -5476,16 +5566,19 @@ CPed::CollideWithPed(CPed *collideWith) m_fRotationCur += m_headingRate; } else { // He's on our right side - if (DotProduct(posDiff, GetRight()) <= 0.0f) - m_fRotationCur -= m_headingRate; + if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) + collideWith->m_fRotationCur -= collideWith->m_headingRate; else - m_fRotationCur += m_headingRate; + collideWith->m_fRotationCur += collideWith->m_headingRate; } } else { SetLookFlag(collideWith, false); TurnBody(); animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); animAssoc->flags |= ASSOC_FADEOUTWHENDONE; +#ifdef VC_PED_PORTS + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; +#endif if (!heIsMissionChar) { CVector2D posDiff2D(posDiff); int direction = collideWith->GetLocalDirection(posDiff2D); @@ -8423,10 +8516,6 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) if (car->pDriver) { CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000); -#ifdef TOGGLEABLE_BETA_FEATURES - if (bMakePedsRunToPhonesToReportCrimes) - m_ped_flagI40 = true; -#endif } ePedPieceTypes pieceToDamage; @@ -8966,7 +9055,11 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) return; if (!ped->EnteringCar()) { - ped->QuitEnteringCar(); +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + return; } if (ped->m_fHealth == 0.0f) { @@ -10558,7 +10651,11 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg) return; if (!ped->EnteringCar()) { - ped->QuitEnteringCar(); +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); + return; } @@ -11589,16 +11686,21 @@ CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg) */ } -// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB, but it's not true, someone made it up. +// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up. bool CPed::RunToReportCrime(eCrimeType crimeToReport) { -#ifdef TOGGLEABLE_BETA_FEATURES - if (!bMakePedsRunToPhonesToReportCrimes) - return false; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + if (bRunningToPhone) { + if (!isPhoneAvailable(m_phoneId)) { + m_phoneId = -1; + bIsRunning = false; + ClearSeek(); // clears bRunningToPhone + return false; + } - if (bRunningToPhone) return true; + } #else // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it. if (m_nPedState == PED_SEEK_POS) @@ -11612,11 +11714,13 @@ CPed::RunToReportCrime(eCrimeType crimeToReport) return false; CPhone *phone = &gPhoneInfo.m_aPhones[phoneId]; +#ifndef PEDS_REPORT_CRIMES_ON_PHONE if (phone->m_nState != PHONE_STATE_FREE) return false; +#endif bRunningToPhone = true; - SetSeek(phone->m_pEntity->GetPosition() - phone->m_pEntity->GetForward(), 1.3f); // original: phone.m_vecPos, 0.3f + SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f SetMoveState(PEDMOVE_RUN); bIsRunning = true; // not there in original m_phoneId = phoneId; @@ -13672,6 +13776,11 @@ CPed::SetSeekCar(CVehicle *car, uint32 doorNode) if (m_nPedState == PED_SEEK_CAR) return; +#ifdef VC_PED_PORTS + if (!CanSetPedState() || m_nPedState == PED_DRIVING) + return; +#endif + SetStoredState(); m_pSeekTarget = car; m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); @@ -13789,14 +13898,13 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj) if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) return; -#ifdef TOGGLEABLE_BETA_FEATURES - if (!bMakePedsRunToPhonesToReportCrimes) +#ifndef PEDS_REPORT_CRIMES_ON_PHONE + if (CharCreatedBy != MISSION_CHAR && obj->GetModelIndex() == MI_PHONEBOOTH1) { + bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; + SetFindPathAndFlee(obj, 5000, !isRunning); + return; + } #endif - if (CharCreatedBy != MISSION_CHAR && obj->GetModelIndex() == MI_PHONEBOOTH1) { - bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; - SetFindPathAndFlee(obj, 5000, !isRunning); - return; - } CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f); CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f); diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 6e536ede..68006e62 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -385,9 +385,8 @@ public: #ifdef PED_SKIN uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this #endif - // our own flags - uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator - uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle + uint32 m_ped_flagI40 : 1; + uint32 m_ped_flagI80 : 1; // originally unused, KANGAROO_CHEAT define makes use of this as cheat toggle uint8 CharCreatedBy; eObjective m_objective; @@ -454,6 +453,10 @@ public: float m_distanceToCountSeekDone; bool bRunningToPhone; int16 m_phoneId; +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + bool m_facePhoneStart; + CEntity *m_victimOfPlayerCrime; +#endif eCrimeType m_crimeToReportOnPhone; uint32 m_phoneTalkTimer; CAccident *m_lastAccident; @@ -588,6 +591,9 @@ public: bool MakePhonecall(void); bool FacePhone(void); CPed *CheckForDeadPeds(void); +#ifdef PEDS_REPORT_CRIMES_ON_PHONE + int32 CheckForPlayerCrimes(CPed *victim = nil); +#endif bool CheckForExplosions(CVector2D &area); CPed *CheckForGunShots(void); PointBlankNecessity CheckForPointBlankPeds(CPed*); @@ -872,9 +878,8 @@ public: static bool bPedCheat3; static CVector2D ms_vec2DFleePosition; -#ifdef TOGGLEABLE_BETA_FEATURES +#ifdef DEBUGMENU static bool bPopHeadsOnHeadshot; - static bool bMakePedsRunToPhonesToReportCrimes; #endif #ifndef MASTER diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 378e621a..aea14f6a 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -874,7 +874,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) { CPed *victimPed = (CPed *)victim; - if ( !victimPed->OnGround() && victim != shooter ) + if ( !victimPed->DyingOrDead() && victim != shooter ) { if ( victimPed->DoesLOSBulletHitPed(*point) ) { From a1356f10014c8bccb1454e083929286d28ff9d24 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 1 Jul 2020 15:38:32 +0300 Subject: [PATCH 10/85] copypaste bug --- src/control/Script.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 7354df22..9b3dc1be 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1354,7 +1354,6 @@ static void PrintToLog(const char* format, ...) #endif va_end(va); - printf("%s", tmp); #if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2 if (dbg_log) fwrite(tmp, 1, strlen(tmp), dbg_log); From ade5dff2172d1a58fc7b44069945def38da8b8ac Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 1 Jul 2020 15:43:19 +0300 Subject: [PATCH 11/85] script logging for miami --- src/control/Script.cpp | 2052 +++++++++++++++++++--------------- src/control/ScriptCommands.h | 2 +- src/core/config.h | 2 +- 3 files changed, 1166 insertions(+), 890 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 92f407b7..d5b9c111 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -393,945 +393,1225 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_ANDOR, INPUT_ARGUMENTS(ARGTYPE_ANDOR,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LAUNCH_MISSION, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_MISSION_HAS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_BUTTON_PRESSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_PAD_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), true, -1, ""), - REGISTER_COMMAND(COMMAND_DELETE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL_NO_DROP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_WANTED_LEVEL_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_DEATHARREST_STATE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_DEATHARREST_BEEN_EXECUTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_REACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ORDER_DRIVER_OUT_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_DRIVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PATROL_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_GANGZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_PRESSING_HORN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_BACKDOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_CHAR_TO_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_OBJECTIVE_PASSED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_DRIVE_AGGRESSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_MAX_DRIVESPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_CHAR_INSIDE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_CHAR_DO_NOTHING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PLAYER_BEEN_ARRESTED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_STOP_CHAR_DRIVING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_KILL_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OCCUPATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_CAR_LOCK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SHAKE_CAM_WITH_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_REMAP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_JUST_SUNK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_NO_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_TRAILER_ATTACHED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_PARK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PARK_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_KILL_ALL_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_BULLETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_FLAMEPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_ROCKETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CARBOMB_ACTIVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_CAR_ALARM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PUT_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_CRUSHED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_GANG_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PED_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_BUTTON_PRESSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PAD_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DELETE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL_NO_DROP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_WANTED_LEVEL_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_DEATHARREST_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_DEATHARREST_BEEN_EXECUTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_REACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ORDER_DRIVER_OUT_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_DRIVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PATROL_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_GANGZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_PRESSING_HORN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_BACKDOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_CHAR_TO_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_OBJECTIVE_PASSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_DRIVE_AGGRESSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_MAX_DRIVESPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CHAR_INSIDE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_CHAR_DO_NOTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PLAYER_BEEN_ARRESTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STOP_CHAR_DRIVING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_KILL_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OCCUPATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_CAR_LOCK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SHAKE_CAM_WITH_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_REMAP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_JUST_SUNK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_NO_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_TRAILER_ATTACHED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PARK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PARK_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_KILL_ALL_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_BULLETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_FLAMEPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_ROCKETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CARBOMB_ACTIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_CAR_ALARM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PUT_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_CRUSHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_GANG_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PED_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTORE_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SHAKE_PAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TIME_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FIXED_CAMERA_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_BLIP_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DIM_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_BLIP_SCALE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FADING_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DO_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_FADING_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_HOSPITAL_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_POLICE_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_OVERRIDE_NEXT_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_SHADOW, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_CAMERA_SPLINE, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MOVE_CAMERA_ALONG_SPLINE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_BLIP_DISPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_ONE_OFF_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_CONTINUOUS_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_SOUND, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STUCK_ON_ROOF, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FORCE_WEATHER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FORCE_WEATHER_NOW, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SHAKE_PAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TIME_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FIXED_CAMERA_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_BLIP_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DIM_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_BLIP_SCALE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FADING_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DO_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_FADING_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_HOSPITAL_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_POLICE_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_OVERRIDE_NEXT_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_SHADOW, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_CAMERA_SPLINE, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MOVE_CAMERA_ALONG_SPLINE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_BLIP_DISPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_ONE_OFF_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_CONTINUOUS_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_SOUND, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STUCK_ON_ROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FORCE_WEATHER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FORCE_WEATHER_NOW, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RELEASE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CURRENT_CAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_GAME_TIMER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DONT_REMOVE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DONT_REMOVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DONT_REMOVE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LEAVE_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_ROUTE_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_HEAVY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DEACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CURRENT_CAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_GAME_TIMER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DONT_REMOVE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DONT_REMOVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DONT_REMOVE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LEAVE_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_ROUTE_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_HEAVY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DEACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_VAR_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_VAR_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR_PROPER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_UPSIDEDOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_PLAYER_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR_PROPER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_UPSIDEDOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PLAYER_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CANCEL_OVERRIDE_RESTART, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_POLICE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_KILL_FRENZY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_READ_KILL_FRENZY_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SQRT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCK_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_EXPLODE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_UPRIGHT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PICKUP_BEEN_COLLECTED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FREE_BOMBS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_POWERPOINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ALL_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_STOP_CHAR_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_STOP_PLAYER_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_HELICOPTER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_PLAYER_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_PED_MODELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_SPECIAL_CHARACTER_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_FLASH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FLASH_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FLASH_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_REMOTE_MODE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_ARM_CAR_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_PERSONALITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CUTSCENE_OFFSET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REQUEST_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MODEL_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GRAB_PHONE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_REPEATED_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PHONE_DISPLAYED_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_PHONE_OFF, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_LIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_POLICE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_KILL_FRENZY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_READ_KILL_FRENZY_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SQRT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCK_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_EXPLODE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_UPRIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PICKUP_BEEN_COLLECTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FREE_BOMBS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_POWERPOINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ALL_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STOP_CHAR_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STOP_PLAYER_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_HELICOPTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_PLAYER_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_PED_MODELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SPECIAL_CHARACTER_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FLASH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FLASH_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FLASH_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_REMOTE_MODE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARM_CAR_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_PERSONALITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CUTSCENE_OFFSET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REQUEST_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MODEL_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GRAB_PHONE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_REPEATED_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PHONE_DISPLAYED_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_PHONE_OFF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_LIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTORE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_RESTART_CRITICAL_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_AREA_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_COLL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_CARS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PEDS_IN_COLL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CONTROLLER_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAN_RESPRAY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_UNLOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_RESTART_CRITICAL_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_AREA_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PEDS_IN_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CONTROLLER_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAN_RESPRAY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_UNLOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_TAXI_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_OBJECT_NO_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_MESSAGE_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_WIDESCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_DEACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_SWAT_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FBI_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ARMY_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CAR_GOTO_COORDINATES_ACCURATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_PACMAN_RACE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_TAXI_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_OBJECT_NO_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MESSAGE_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_WIDESCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DEACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_SWAT_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FBI_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ARMY_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CAR_GOTO_COORDINATES_ACCURATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_PACMAN_RACE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_PACMAN_RECORD, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_PACMAN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_PACMAN_SCRAMBLE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_PACMAN_SCRAMBLE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(ARGTYPE_LABEL, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_GROUND_Z_FOR_3D_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COMEDY_CONTROLS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_BOAT_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_BOAT_STOP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_GROUND_Z_FOR_3D_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COMEDY_CONTROLS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_BOAT_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_BOAT_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_POWER_PILL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_BOAT_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_MONEY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_ACCURACY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_POWER_PILL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_BOAT_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_MONEY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_ACCURACY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CUTSCENE_TIME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CUTSCENE_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CUTSCENE_TIME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CUTSCENE_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTORE_CAMERA_JUMPCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_COLLECTABLE1, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLLECTABLE1_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PROJECTILE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_DESTROY_PROJECTILES_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DROP_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DROP_NAUTICAL_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CUTSCENE_HEAD_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SIN, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_COS, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_X, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_Y, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ACTIVATE_CRUSHER_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PLAYER_MADE_PROGRESS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PROGRESS_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_JUMP_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_JUMP_HEIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_JUMP_FLIPS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_JUMP_SPINS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_JUMP_STUNT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_COLLECTABLE1, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLLECTABLE1_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PROJECTILE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DESTROY_PROJECTILES_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DROP_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DROP_NAUTICAL_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CUTSCENE_HEAD_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SIN, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_COS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_X, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_Y, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ACTIVATE_CRUSHER_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLAYER_MADE_PROGRESS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PROGRESS_TOTAL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_JUMP_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_JUMP_HEIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_JUMP_FLIPS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_JUMP_SPINS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_JUMP_STUNT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_UNIQUE_JUMP_FOUND, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_UNIQUE_JUMPS_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_UNIQUE_JUMPS_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_MONEY_MADE_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_MONEY_MADE_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_MISSION_GIVEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_MISSION_PASSED, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_RUNNING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_MISSION_PASSED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_RUNNING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_ALL_SCRIPT_FIRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_EXPLODE_CHAR_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_EXPLODE_PLAYER_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ANCHOR_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ZONE_GROUP, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_CAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_CHAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_RESPRAY_HAPPENED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAMERA_ZOOM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_PICKUP_WITH_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_RAM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_BLOCK_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_NEVER_GETS_TIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_FAST_RELOAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_BLEEDING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_FUNNY_SUSPENSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_BIG_WHEELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FREE_RESPRAYS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_EXPLODE_CHAR_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_EXPLODE_PLAYER_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ANCHOR_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ZONE_GROUP, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_CAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_CHAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_RESPRAY_HAPPENED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAMERA_ZOOM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_PICKUP_WITH_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_RAM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_BLOCK_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_NEVER_GETS_TIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_FAST_RELOAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_BLEEDING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_FUNNY_SUSPENSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_BIG_WHEELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FREE_RESPRAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_DRUG_RUN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SAVE_PLAYER_FROM_FIRES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_TEXT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_WRAPX, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE_SIZE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_PROPORTIONAL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_FONT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SAVE_PLAYER_FROM_FIRES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_TEXT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_WRAPX, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE_SIZE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_PROPORTIONAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_FONT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_INDUSTRIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_COMMERCIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SUBURBAN_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ROTATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SLIDE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_CHAR_ELEGANTLY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_SAME_PLACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_NASTY_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_UNDRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_START_CHASE_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ROTATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SLIDE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_CHAR_ELEGANTLY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_SAME_PLACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_NASTY_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_UNDRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_CHASE_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_CHASE_SCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_DRUG_DROP_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FIND_DROP_OFF_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_FLOATING_PACKAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_OBJECT_TARGETTABLE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_OPEN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLOSE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WARP_CHAR_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_HAIL_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_OBJECT_BEEN_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_START_KILL_FRENZY_HEADSHOT, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ACTIVATE_MILITARY_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WARP_PLAYER_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_CAR_RADIO, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_AUDIO_STREAM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FIND_DROP_OFF_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_FLOATING_PACKAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_OBJECT_TARGETTABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_OPEN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLOSE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WARP_CHAR_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_HAIL_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_OBJECT_BEEN_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_KILL_FRENZY_HEADSHOT, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ACTIVATE_MILITARY_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WARP_PLAYER_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_CAR_RADIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_AUDIO_STREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAMERA_BEHIND_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_MOTION_BLUR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_2_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_2_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_3_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_3_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_4_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_4_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SNIPER_BULLET_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_SET_MOTION_BLUR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_2_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_2_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_3_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_3_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_4_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_4_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SNIPER_BULLET_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_PLAYER_DETONATOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_ICECREAM_JINGLE_ON, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_5_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_5_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_6_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_6_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_ICECREAM_JINGLE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_5_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_5_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_6_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_6_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_ALL_MODELS_NOW, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_RECT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_TEXTURE_DICTIONARY, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_RECT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_TEXTURE_DICTIONARY, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_TEXTURE_DICTIONARY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_DYNAMIC, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_ANIM_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PLAY_MISSION_PASSED_TUNE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FREEZE_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_CAR_SIREN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_WATERTIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_MOVING_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_CAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CRANE_LIFTING_CAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_DRAW_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_STATUS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_MALE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SCRIPT_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FIND_DRUG_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SAVE_INT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SAVE_FLOAT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_DYNAMIC, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_ANIM_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLAY_MISSION_PASSED_TUNE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_CAR_SIREN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_WATERTIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MOVING_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_CAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CRANE_LIFTING_CAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_STATUS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_MALE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SCRIPT_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FIND_DRUG_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SAVE_INT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SAVE_FLOAT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_POLICE_RADIO_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_STRONG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_STREAMING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GARAGE_OPEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GARAGE_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_POLICE_RADIO_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_STRONG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_STREAMING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GARAGE_OPEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GARAGE_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CATALINA_HELI_TAKE_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SWAP_NEAREST_BUILDING_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_WORLD_PROCESSING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_ALL_PLAYER_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GRAB_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ROTATING_GARAGE_DOOR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_SPHERE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWAP_NEAREST_BUILDING_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_WORLD_PROCESSING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_ALL_PLAYER_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GRAB_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ROTATING_GARAGE_DOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_SPHERE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CATALINA_HELI_FLY_AWAY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_EVERYONE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_WANTED_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_EVERYONE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_WANTED_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_VISIBLY_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_OBJECT_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_THIS_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_THIS_BIG_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_VISIBLY_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_OBJECT_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_THIS_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_THIS_BIG_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ACTIVATE_SAVE_MENU, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PED_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FORCE_RANDOM_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_COLLECTABLE1S_COLLECTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_EL_BURRO_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_SPRITES_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TEXT_RIGHT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_PRINT_HELP, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PED_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FORCE_RANDOM_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_COLLECTABLE1S_COLLECTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_SPRITES_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TEXT_RIGHT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_HELP, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_HELP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FLASH_HUD_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FLASH_RADAR_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GENERATE_CARS_AROUND_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FLASH_HUD_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FLASH_RADAR_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GENERATE_CARS_AROUND_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_SMALL_PRINTS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CAN_PLAYER_START_MISSION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_USE_TEXT_COMMANDS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_PLAYER_UNSAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_BODY_CAST_HEALTH, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHARS_CHATTING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_4X4_ONE_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_4X4_TWO_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_4X4_THREE_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_4X4_MAYHEM_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CAN_PLAYER_START_MISSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_USE_TEXT_COMMANDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_PLAYER_UNSAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_BODY_CAST_HEALTH, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHARS_CHATTING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_DRUNK_INPUT_DELAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_INCREASE_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_LIFE_SAVED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_CRIMINAL_CAUGHT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_AMBULANCE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_AMBULANCE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_TURN_PHONE_ON, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_LONGEST_DODO_FLIGHT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - //REGISTER_COMMAND(COMMAND_REGISTER_DEFUSE_BOMB_TIME, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TURN_PHONE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_LONGEST_DODO_FLIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_BLOW_UP_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REMOVE_CAR_FROM_CHASE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GANG_PED_MODEL_PREFERENCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_USE_PEDNODE_SEEK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SWITCH_VEHICLE_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_GET_OUT_OF_JAIL_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_FREE_HEALTH_CARE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DOOR_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_CAR_FROM_CHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_PED_MODEL_PREFERENCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_USE_PEDNODE_SEEK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_VEHICLE_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GET_OUT_OF_JAIL_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FREE_HEALTH_CARE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DOOR_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_OBJECT_DRAW_LAST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_AMMO_IN_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_AMMO_IN_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_DRAW_LAST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_AMMO_IN_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_AMMO_IN_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_KILL_FRENZY_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_SAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_NEAR_CLIP, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_RADIO_CHANNEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_OVERRIDE_HOSPITAL_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_OVERRIDE_POLICE_STATION_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_FORCE_RAIN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_GARAGE_CONTAIN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_TRACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_MEASUREMENTS_IN_METRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CHARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET_INT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_FASTEST_TIME, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_REGISTER_HIGHEST_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_PASSENGER_SEAT_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_SAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_NEAR_CLIP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_RADIO_CHANNEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_OVERRIDE_HOSPITAL_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_OVERRIDE_POLICE_STATION_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FORCE_RAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_GARAGE_CONTAIN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_TRACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_MEASUREMENTS_IN_METRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CHARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_FASTEST_TIME, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_HIGHEST_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_PASSENGER_SEAT_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_CREDITS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CREATE_SINGLE_PARTICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CHASE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_CREDITS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_SINGLE_PARTICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHASE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_START_BOAT_FOAM_ANIMATION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_UPDATE_BOAT_FOAM_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_MUSIC_DOES_FADE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_INTRO_IS_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_PLAYER_HOOKER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_UPDATE_BOAT_FOAM_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_MUSIC_DOES_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_INTRO_IS_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_HOOKER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PLAY_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_SCRIPT_FIRE_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_LIFTING_A_PHONE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_COLLISION_WITH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOAD_SPLASH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_SCRIPT_FIRE_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_LIFTING_A_PHONE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_COLLISION_WITH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_SPLASH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ENABLE_PLAYER_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), -#ifndef GTA_PS2 - REGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FAIL_CURRENT_MISSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_INTERPOLATION_PARAMETERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_POINT_AT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DETACH_CHAR_FROM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_CHANGE_LANE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_DRIVER_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_FOLLOWERS, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - //REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, ""), -#endif + REGISTER_COMMAND(COMMAND_GET_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_INTERPOLATION_PARAMETERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_POINT_AT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DETACH_CHAR_FROM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_CHANGE_LANE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DRIVER_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_FOLLOWERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_TEMP_ACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CEASE_ATTACK_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_REMOTE_CONTROLLED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PC_VERSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_REPLAY_PLAYING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MODEL_AVAILABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SHUT_CHAR_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_RANDOM_ROUTE_SEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_ANY_PICKUP_AT_COORDS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_FIRST_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NEXT_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_ALL_CHAR_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PLAYER_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_FACING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TANK_DETONATE_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_POSITION_OF_ANALOGUE_STICKS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_TYRE_BURST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_INITIALISE_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_START_OBJECT_ON_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HELI_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DEAD_CHAR_PICKUP_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_PROTECTION_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHAR_WEAPON_IN_SLOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_STRAIGHT_ROAD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_FORWARD_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM_TO_LOOP, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MARK_CAR_AS_CONVOY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_SCRIPT_ROADBLOCK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PICKUP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_SECURITY_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SONY_CD_BEEN_READ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SONY_CDS_READ, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_CLOTHES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLANE_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DRAW_WEAPONSHOP_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_DROWNS_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_RECORDS_COLLISIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_HELI_STABILISER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_POP_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SHUT_PLAYER_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_MOOD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REQUEST_COLLISION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ZONE_CIVILIAN_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REQUEST_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_ANIMATION_LOADED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_AS_PLAYER_FRIEND, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SET_PIECE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLOSE_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_WHEELIE_STATS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISARM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_BURST_CAR_TYRE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_WEARING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_SWAT_ROPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_NEAREST_TYRE_TO_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAR_MODEL_COMPONENTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SWITCH_LIFT_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLOSE_ALL_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_POP_CAR_BOOT_USING_PHYSICS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_WANDER_PATH_CLEAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_HELP_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_LOCKED_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_FORSALE_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RADIO_CHANNEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISABLE_CUTSCENE_SHADOWS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_LOADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_PROPERTY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_ANSWERING_MOBILE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_LOAN_SHARK_VISITS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_STORES_KNOCKED_OFF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MOVIE_STUNTS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_NUMBER_OF_ASSASSINATIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PIZZAS_DELIVERED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_GARBAGE_PICKUPS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_ICE_CREAMS_SOLD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TOP_SHOOTING_RANGE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHOOTING_RANGE_RANK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_MONEY_WON_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LARGEST_GAMBLING_WIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CAN_BURST_CAR_TYRES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_AUTO_AIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FIRE_HUNTER_GUN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PROPERTY_AS_OWNED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BLOOD_RING_KILLS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_FOLLOW_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_MISSION_TEXT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_TONIGHTS_EVENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_RIOT_INTENSITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REMOVE_WEAPON_FROM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_UP_TAXI_SHORTCUT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_TAXI_SHORTCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CLOSEST_WATER_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_CLOTHES_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CHANGE_BLIP_THRESHOLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_PLAYER_FIRE_PROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_MAKE_HELI_COME_CRASHING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_EXPLOSION_NO_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_OBJECT_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WAS_VEHICLE_EVER_POLICE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_NEVER_TARGETTED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOAD_UNCOMPRESSED_ANIM, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WAS_CUTSCENE_SKIPPED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_CHAR_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_VEHICLE_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ALL_TAXIS_HAVE_NITRO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_VIGILANTE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_ALL_CHAR_ANIMS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WANTED_STARS_ARE_FLASHING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ALLOW_HURRICANES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_PLAY_ANNOUNCEMENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_PLAYER_IS_IN_STADIUM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISPLAY_RADAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_BEST_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_INFO_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ADD_BIG_GUN_FLASH, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_PROGRESS_PERCENTAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_SHORTCUT_PICKUP_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_VEHICLE_TO_FADE_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_ODDJOB_MISSION_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DUCKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_REGISTER_FIRE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_AUSTRALIAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DISARM_CAR_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), }; #undef REGISTER_COMMAND #undef INPUT_ARGUMENTS @@ -1355,7 +1635,6 @@ static void PrintToLog(const char* format, ...) #endif va_end(va); - printf("%s", tmp); #if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2 fwrite(tmp, 1, strlen(tmp), dbg_log); #endif @@ -1768,13 +2047,13 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total) #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT int CRunningScript::CollectParameterForDebug(char* buf, bool& var) { - float tmp; uint16 varIndex; char tmpstr[24]; var = false; switch (CTheScripts::Read1ByteFromScript(&m_nIp)) { case ARGUMENT_INT32: + case ARGUMENT_FLOAT: return CTheScripts::Read4BytesFromScript(&m_nIp); case ARGUMENT_GLOBALVAR: varIndex = CTheScripts::Read2BytesFromScript(&m_nIp); @@ -1794,9 +2073,6 @@ int CRunningScript::CollectParameterForDebug(char* buf, bool& var) return CTheScripts::Read1ByteFromScript(&m_nIp); case ARGUMENT_INT16: return CTheScripts::Read2BytesFromScript(&m_nIp); - case ARGUMENT_FLOAT: - tmp = CTheScripts::ReadFloatFromScript(&m_nIp); - return *(int32*)&tmp; default: PrintToLog("%s - script assertion failed in CollectParameterForDebug", buf); script_assert(0); @@ -12296,7 +12572,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command) case COMMAND_IS_OBJECT_IN_AREA_3D: ObjectInAreaCheckCommand(command, &m_nIp); return 0; - case COMMAND_TASK_TOGGLE_DUCK: + case COMMAND_SET_CHAR_CROUCH: { CollectParameters(&m_nIp, 3); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h index 6669e43f..18fc9575 100644 --- a/src/control/ScriptCommands.h +++ b/src/control/ScriptCommands.h @@ -1260,7 +1260,7 @@ enum { COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR, COMMAND_IS_OBJECT_IN_AREA_2D, COMMAND_IS_OBJECT_IN_AREA_3D, - COMMAND_TASK_TOGGLE_DUCK, + COMMAND_SET_CHAR_CROUCH, COMMAND_SET_ZONE_CIVILIAN_CAR_INFO, COMMAND_REQUEST_ANIMATION, COMMAND_HAS_ANIMATION_LOADED, diff --git a/src/core/config.h b/src/core/config.h index 7ba1a6fd..5459c336 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -257,7 +257,7 @@ enum Config { //#define MISSION_REPLAY // mobile feature #endif //#define SIMPLIER_MISSIONS // apply simplifications from mobile -//#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT +#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log #ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT From 389123cff3e53b2e2fa1fed89b23684ae0ccf06e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 1 Jul 2020 16:06:16 +0300 Subject: [PATCH 12/85] fix --- src/control/Script.cpp | 664 ++++++++++++++++++++--------------------- 1 file changed, 332 insertions(+), 332 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index d5b9c111..46f9c722 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -395,82 +395,82 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_MISSION_HAS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_BUTTON_PRESSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_BUTTON_PRESSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_PAD_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_DELETE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_STORE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL_NO_DROP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_WANTED_LEVEL_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_WANTED_LEVEL_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_DEATHARREST_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_DEATHARREST_BEEN_EXECUTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_DEATHARREST_BEEN_EXECUTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_REACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ORDER_DRIVER_OUT_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_DRIVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_PATROL_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_GANGZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_PRESSING_HORN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_GANGZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_PRESSING_HORN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_BACKDOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_CHAR_TO_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_OBJECTIVE_PASSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_OBJECTIVE_PASSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_DRIVE_AGGRESSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_MAX_DRIVESPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_CHAR_INSIDE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -480,32 +480,32 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_PLAYER_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PLAYER_BEEN_ARRESTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PLAYER_BEEN_ARRESTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_STOP_CHAR_DRIVING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_KILL_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OCCUPATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CHANGE_CAR_LOCK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SHAKE_CAM_WITH_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_REMAP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_JUST_SUNK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_REMAP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_JUST_SUNK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_NO_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_TRAILER_ATTACHED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_TRAILER_ATTACHED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_PARK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PARK_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PARK_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_KILL_ALL_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_BULLETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_FLAMEPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_ROCKETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CARBOMB_ACTIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CARBOMB_ACTIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_CAR_ALARM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PUT_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_CRUSHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_CRUSHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_GANG_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -515,8 +515,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PED_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -526,7 +526,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SHAKE_PAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_TIME_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_FIXED_CAMERA_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -539,7 +539,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_CHANGE_BLIP_SCALE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FADING_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DO_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_FADING_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_FADING_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_HOSPITAL_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_POLICE_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_OVERRIDE_NEXT_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -552,8 +552,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -563,9 +563,9 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -575,7 +575,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_ADD_ONE_OFF_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_CONTINUOUS_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_SOUND, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STUCK_ON_ROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STUCK_ON_ROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -583,32 +583,32 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -625,7 +625,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -675,8 +675,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_VAR_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_VAR_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR_PROPER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_UPSIDEDOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR_PROPER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_UPSIDEDOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_PLAYER_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CANCEL_OVERRIDE_RESTART, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_POLICE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -684,31 +684,31 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_START_KILL_FRENZY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_READ_KILL_FRENZY_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SQRT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_LOCK_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_EXPLODE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_UPRIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_UPRIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PICKUP_BEEN_COLLECTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PICKUP_BEEN_COLLECTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -716,11 +716,11 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_FREE_BOMBS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_POWERPOINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ALL_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -728,7 +728,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CHANGE_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -746,26 +746,26 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_GANG_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_SPECIAL_CHARACTER_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SPECIAL_CHARACTER_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_FLASH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FLASH_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FLASH_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_REMOTE_MODE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_REMOTE_MODE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ARM_CAR_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_PERSONALITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CUTSCENE_OFFSET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REQUEST_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MODEL_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MODEL_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GRAB_PHONE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_REPEATED_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PHONE_DISPLAYED_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PHONE_DISPLAYED_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_TURN_PHONE_OFF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DRAW_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DRAW_LIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -774,7 +774,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_STORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESTART_CRITICAL_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -810,45 +810,45 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_AREA_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PEDS_IN_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CONTROLLER_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAN_RESPRAY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_UNLOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_TAXI_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_OBJECT_NO_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_MESSAGE_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_WIDESCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -861,25 +861,25 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DEACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_SWAT_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FBI_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ARMY_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CAR_GOTO_COORDINATES_ACCURATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -890,29 +890,29 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_START_PACMAN_SCRAMBLE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_GROUND_Z_FOR_3D_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_START_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COMEDY_CONTROLS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_BOAT_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_BOAT_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_POWER_PILL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_BOAT_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_MONEY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_ACCURACY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CAR_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), @@ -926,11 +926,11 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_RESTORE_CAMERA_JUMPCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_COLLECTABLE1, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLLECTABLE1_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PROJECTILE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PROJECTILE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DESTROY_PROJECTILES_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DROP_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DROP_NAUTICAL_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_SPECIAL_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CUTSCENE_HEAD_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -971,12 +971,12 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_REGISTER_MISSION_PASSED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_RUNNING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_ALL_SCRIPT_FIRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_EXPLODE_CHAR_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_EXPLODE_PLAYER_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ANCHOR_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1001,10 +1001,10 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_PLAYER_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_START_DRUG_RUN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SAVE_PLAYER_FROM_FIRES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_TEXT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_TEXT_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1021,19 +1021,19 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_INDUSTRIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_COMMERCIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SUBURBAN_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ROTATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SLIDE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ROTATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_SLIDE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_CHAR_ELEGANTLY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_SAME_PLACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_NASTY_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_NASTY_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_UNDRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_CHASE_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_CHASE_SCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_START_DRUG_DROP_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_FIND_DROP_OFF_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_FLOATING_PACKAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1044,9 +1044,9 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_CLOSE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_WARP_CHAR_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_HAIL_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_OBJECT_BEEN_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_OBJECT_BEEN_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_START_KILL_FRENZY_HEADSHOT, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ACTIVATE_MILITARY_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_WARP_PLAYER_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1070,19 +1070,19 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_3_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_4_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_4_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_SNIPER_BULLET_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_SNIPER_BULLET_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GIVE_PLAYER_DETONATOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_ICECREAM_JINGLE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_ICECREAM_JINGLE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_5_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_5_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_6_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_6_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_ALL_MODELS_NOW, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DRAW_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1104,10 +1104,10 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_ADD_MOVING_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_TURN_CAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CRANE_LIFTING_CAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CRANE_LIFTING_CAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DRAW_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_STATUS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_MALE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_MALE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SCRIPT_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FIND_DRUG_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), @@ -1120,12 +1120,12 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SWITCH_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_STREAMING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GARAGE_OPEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GARAGE_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GARAGE_OPEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GARAGE_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_START_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CATALINA_HELI_TAKE_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SWAP_NEAREST_BUILDING_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_WORLD_PROCESSING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_ALL_PLAYER_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1138,30 +1138,30 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_EVERYONE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_WANTED_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_VISIBLY_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_OBJECT_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_VISIBLY_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_OBJECT_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_THIS_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_THIS_BIG_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ACTIVATE_SAVE_MENU, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -1177,17 +1177,17 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_CLEAR_HELP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FLASH_HUD_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FLASH_RADAR_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_GENERATE_CARS_AROUND_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_SMALL_PRINTS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CAN_PLAYER_START_MISSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_CAN_PLAYER_START_MISSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_USE_TEXT_COMMANDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), + REGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_MAKE_PLAYER_UNSAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1211,8 +1211,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_BLOW_UP_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_CAR_FROM_CHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1221,7 +1221,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SWITCH_VEHICLE_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_GET_OUT_OF_JAIL_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FREE_HEALTH_CARE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DOOR_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DOOR_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_DRAW_LAST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1234,27 +1234,27 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_OVERRIDE_HOSPITAL_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_OVERRIDE_POLICE_STATION_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FORCE_RAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_GARAGE_CONTAIN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_GARAGE_CONTAIN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_TRACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_MEASUREMENTS_IN_METRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_MEASUREMENTS_IN_METRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_MARK_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CHARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_FASTEST_TIME, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_HIGHEST_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_PASSENGER_SEAT_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_PASSENGER_SEAT_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_START_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_CREDITS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_CREDITS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_SINGLE_PARTICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CHASE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -1266,16 +1266,16 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_PLAY_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_STOP_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_SCRIPT_FIRE_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_LIFTING_A_PHONE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_LIFTING_A_PHONE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_COLLISION_WITH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_SPLASH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1286,9 +1286,9 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1313,49 +1313,49 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_TEMP_ACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CEASE_ATTACK_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_REMOTE_CONTROLLED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PC_VERSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PC_VERSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_REPLAY_PLAYING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_MODEL_AVAILABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_REPLAY_PLAYING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MODEL_AVAILABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SHUT_CHAR_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_RANDOM_ROUTE_SEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_ANY_PICKUP_AT_COORDS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_ANY_PICKUP_AT_COORDS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_FIRST_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_NEXT_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_ALL_CHAR_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PLAYER_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_FACING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PLAYER_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_FACING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_TANK_DETONATE_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_POSITION_OF_ANALOGUE_STICKS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_ON_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_TYRE_BURST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_ON_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_TYRE_BURST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_INITIALISE_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_START_OBJECT_ON_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1363,27 +1363,27 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_HELI_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_DEAD_CHAR_PICKUP_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_PROTECTION_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, " ="), + REGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, " ="), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >"), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >"), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >"), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >"), + REGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >="), + REGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >="), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >="), + REGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, " >="), REGISTER_COMMAND(COMMAND_GET_CHAR_WEAPON_IN_SLOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_CLOSEST_STRAIGHT_ROAD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_FORWARD_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1395,14 +1395,14 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_CREATE_SCRIPT_ROADBLOCK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PICKUP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PICKUP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SWITCH_SECURITY_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_SONY_CD_BEEN_READ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_SONY_CD_BEEN_READ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SONY_CDS_READ, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), @@ -1414,13 +1414,13 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_DRAW_WEAPONSHOP_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_DROWNS_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_RECORDS_COLLISIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_HELI_STABILISER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1429,20 +1429,20 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SHUT_PLAYER_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_MOOD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REQUEST_COLLISION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_LOCATE_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_ZONE_CIVILIAN_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REQUEST_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_ANIMATION_LOADED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_ANIMATION_LOADED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_AS_PLAYER_FRIEND, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1455,8 +1455,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GET_WHEELIE_STATS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_DISARM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_BURST_CAR_TYRE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_WEARING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_WEARING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_SWAT_ROPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1469,33 +1469,33 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_POP_CAR_BOOT_USING_PHYSICS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_GET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_WANDER_PATH_CLEAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_WANDER_PATH_CLEAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_HELP_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_LOCKED_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_FORSALE_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_RADIO_CHANNEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DISABLE_CUTSCENE_SHADOWS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_LOADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_LOADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_PROPERTY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1526,9 +1526,9 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_ADD_BLOOD_RING_KILLS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_CHAR_FOLLOW_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1539,8 +1539,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_RIOT_INTENSITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_REMOVE_WEAPON_FROM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_UP_TAXI_SHORTCUT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_TAXI_SHORTCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1559,17 +1559,17 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_MAKE_HELI_COME_CRASHING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_EXPLOSION_NO_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_OBJECT_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WAS_VEHICLE_EVER_POLICE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WAS_VEHICLE_EVER_POLICE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_NEVER_TARGETTED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_LOAD_UNCOMPRESSED_ANIM, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WAS_CUTSCENE_SKIPPED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WAS_CUTSCENE_SKIPPED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_CHAR_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_DOES_VEHICLE_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_CHAR_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_DOES_VEHICLE_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_ALL_TAXIS_HAVE_NITRO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1579,7 +1579,7 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_REGISTER_VIGILANTE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_ALL_CHAR_ANIMS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_WANTED_STARS_ARE_FLASHING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_WANTED_STARS_ARE_FLASHING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_ALLOW_HURRICANES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_PLAY_ANNOUNCEMENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_PLAYER_IS_IN_STADIUM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1587,15 +1587,15 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_DISPLAY_RADAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_BEST_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_INFO_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_INFO_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_ADD_BIG_GUN_FLASH, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_GET_PROGRESS_PERCENTAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_SHORTCUT_PICKUP_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -1606,11 +1606,11 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_VEHICLE_TO_FADE_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_ODDJOB_MISSION_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_DUCKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CHAR_DUCKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_REGISTER_FIRE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_AUSTRALIAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), + REGISTER_COMMAND(COMMAND_IS_AUSTRALIAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_DISARM_CAR_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, ""), }; #undef REGISTER_COMMAND From 575f35f2c48354c6e5df5b936d35658f6e5bc873 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 1 Jul 2020 18:03:52 +0200 Subject: [PATCH 13/85] fixes to CBoat --- src/math/Matrix.h | 8 +++++++ src/vehicles/Boat.cpp | 52 ++++++++++++++++++++-------------------- src/vehicles/Boat.h | 23 +++++++++--------- src/vehicles/Floater.cpp | 4 ++-- 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/math/Matrix.h b/src/math/Matrix.h index d8920a65..c849a5c4 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -259,6 +259,14 @@ public: m_matrix.at.y = 0.0f; m_matrix.at.z = 1.0f; } + void SetTranslateOnly(float x, float y, float z) { + m_matrix.pos.x = x; + m_matrix.pos.y = y; + m_matrix.pos.z = z; + } + void SetTranslateOnly(const CVector& pos) { + SetTranslateOnly(pos.x, pos.y, pos.z); + } }; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index d86627de..9113800d 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -47,7 +47,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fBrake = 0.0f; m_fSteeringLeftRight = 0.0f; m_nPadID = 0; - m_fMovingHiRotation = 0.0f; + m_fMovingRotation = 0.0f; SetModelIndex(mi); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); @@ -63,11 +63,11 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fGasPedal = 0.0f; m_fBrakePedal = 0.0f; - m_fPropellerZ = 0.25f; - m_fPropellerY = 0.35f; - m_waterMoveDrag = CVector(0.7f, 0.998f, 0.999f); - m_waterTurnDrag = CVector(0.85f, 0.96f, 0.96f); - _unk2 = false; + m_fThrustZ = 0.25f; + m_fThrustY = 0.35f; + m_vecMoveRes = CVector(0.7f, 0.998f, 0.999f); + m_vecTurnRes = CVector(0.85f, 0.96f, 0.96f); + m_boat_unused3 = false; m_fVolumeUnderWater = 7.0f; m_fPrevVolumeUnderWater = 7.0f; @@ -79,7 +79,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) bIsInWater = true; - m_phys_unused1 = 0.0f; + m_boat_unused2 = 0; m_bIsAnchored = true; m_fOrientation = INVALID_ORIENTATION; bTouchingWater = true; @@ -290,7 +290,7 @@ CBoat::ProcessControl(void) } // Handle boat moving forward - if(Abs(m_fGasPedal) > 0.05f || m_vecMoveSpeed.Magnitude() > 0.01f){ + if(Abs(m_fGasPedal) > 0.05f || m_vecMoveSpeed.Magnitude2D() > 0.01f){ if(bBoatInWater) AddWakePoint(GetPosition()); @@ -299,7 +299,7 @@ CBoat::ProcessControl(void) steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward())*0.3f; if(steerFactor < 0.0f) steerFactor = 0.0f; - CVector propeller(0.0f, -pHandling->Dimension.y*m_fPropellerY, -pHandling->Dimension.z*m_fPropellerZ); + CVector propeller(0.0f, -pHandling->Dimension.y*m_fThrustY, -pHandling->Dimension.z*m_fThrustZ); propeller = Multiply3x3(GetMatrix(), propeller); CVector propellerWorld = GetPosition() + propeller; @@ -396,7 +396,7 @@ CBoat::ProcessControl(void) } }else if(!onLand){ float force = 50.0f*DotProduct(m_vecMoveSpeed, GetForward()); - if(force > 10.0f) force = 10.0f; + force = Min(force, 10.0f); CVector propellerForce = propellerDepth * Multiply3x3(GetMatrix(), force*CVector(-steerSin, 0.0f, 0.0f)); ApplyMoveForce(propellerForce * CTimer::GetTimeStep()*0.5f); ApplyTurnForce(propellerForce * CTimer::GetTimeStep()*0.5f, propeller); @@ -415,9 +415,9 @@ CBoat::ProcessControl(void) ApplyWaterResistance(); // No idea what exactly is going on here besides drag in YZ - float fx = Pow(m_waterTurnDrag.x, CTimer::GetTimeStep()); - float fy = Pow(m_waterTurnDrag.y, CTimer::GetTimeStep()); - float fz = Pow(m_waterTurnDrag.z, CTimer::GetTimeStep()); + float fx = Pow(m_vecTurnRes.x, CTimer::GetTimeStep()); + float fy = Pow(m_vecTurnRes.y, CTimer::GetTimeStep()); + float fz = Pow(m_vecTurnRes.z, CTimer::GetTimeStep()); m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space // TODO: figure this out float magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx; @@ -525,7 +525,7 @@ CBoat::ProcessControl(void) // is this some inlined CPlaceable method? CVector pos = GetPosition(); GetMatrix().RotateZ(m_fOrientation - GetForward().Heading()); - GetMatrix().GetPosition() = pos; + GetMatrix().SetTranslateOnly(pos); } } @@ -562,12 +562,12 @@ CBoat::ApplyWaterResistance(void) { float fwdSpeed = DotProduct(GetMoveSpeed(), GetForward()); // TODO: figure out how this works - float magic = (SQR(fwdSpeed) + 0.05f) * (0.001f * SQR(m_fVolumeUnderWater) * m_fMass) + 1.0f; + float resistance = 0.001f * SQR(m_fVolumeUnderWater) * m_fMass; + float magic = (SQR(fwdSpeed) + 0.05f) * resistance + 1.0f; magic = Abs(magic); - // FRAMETIME - float fx = Pow(m_waterMoveDrag.x/magic, 0.5f*CTimer::GetTimeStep()); - float fy = Pow(m_waterMoveDrag.y/magic, 0.5f*CTimer::GetTimeStep()); - float fz = Pow(m_waterMoveDrag.z/magic, 0.5f*CTimer::GetTimeStep()); + float fx = Pow(m_vecMoveRes.x/magic, 0.5f*CTimer::GetTimeStep()); + float fy = Pow(m_vecMoveRes.y/magic, 0.5f*CTimer::GetTimeStep()); + float fz = Pow(m_vecMoveRes.z/magic, 0.5f*CTimer::GetTimeStep()); m_vecMoveSpeed = Multiply3x3(m_vecMoveSpeed, GetMatrix()); // invert - to local space m_vecMoveSpeed.x *= fx; @@ -685,7 +685,7 @@ CBoat::BlowUpCar(CEntity *culprit) dist.Normalise(); if(GetUp().z > 0.0f) dist += GetUp(); - obj->GetMatrix().GetPosition() += GetUp(); + obj->GetMatrix().GetPosition() += dist; CWorld::Add(obj); @@ -707,7 +707,7 @@ CBoat::Render() matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING])); CVector pos = matrix.GetPosition(); - matrix.SetRotateZ(m_fMovingHiRotation); + matrix.SetRotateZ(m_fMovingRotation); matrix.Translate(pos); matrix.UpdateRW(); @@ -715,20 +715,20 @@ CBoat::Render() RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[BOAT_MOVING])); } } - m_fMovingHiRotation += 0.05f; + m_fMovingRotation += 0.05f; ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2); if (!CVehicle::bWheelsOnlyCheat) CEntity::Render(); - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255); KeepWaterOutIndices[0] = 0; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255); KeepWaterOutIndices[1] = 2; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255); KeepWaterOutIndices[2] = 1; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255); KeepWaterOutIndices[3] = 1; KeepWaterOutIndices[4] = 2; KeepWaterOutIndices[5] = 3; + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255); switch (GetModelIndex()) { case MI_SPEEDER: RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f); diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 3cc3513d..56aff264 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -6,33 +6,34 @@ enum eBoatNodes { BOAT_MOVING = 1, BOAT_RUDDER, - BOAT_WINDSCREEN + BOAT_WINDSCREEN, + NUM_BOAT_NODES }; class CBoat : public CVehicle { public: // 0x288 - float m_fPropellerZ; - float m_fPropellerY; - CVector m_waterMoveDrag; - CVector m_waterTurnDrag; - float m_fMovingHiRotation; - int32 _unk0; - RwFrame *m_aBoatNodes[4]; + float m_fThrustZ; + float m_fThrustY; + CVector m_vecMoveRes; + CVector m_vecTurnRes; + float m_fMovingRotation; + int32 m_boat_unused1; + RwFrame *m_aBoatNodes[NUM_BOAT_NODES]; uint8 bBoatInWater : 1; uint8 bPropellerInWater : 1; bool m_bIsAnchored; float m_fOrientation; - int32 _unk1; + int32 m_boat_unused2; float m_fDamage; CEntity *m_pSetOnFireEntity; - bool _unk2; + bool m_boat_unused3; float m_fAccelerate; float m_fBrake; float m_fSteeringLeftRight; uint8 m_nPadID; - int32 _unk3; + int32 m_boat_unused4; float m_fVolumeUnderWater; CVector m_vecBuoyancePoint; float m_fPrevVolumeUnderWater; diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index 1ae1c5c3..4331090d 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -9,10 +9,10 @@ cBuoyancy mod_Buoyancy; -static float fVolMultiplier = 1.0f; +float fVolMultiplier = 1.0f; // amount of boat volume in bounding box // 1.0-volume is the empty space in the bbox -static float fBoatVolumeDistribution[9] = { +float fBoatVolumeDistribution[9] = { // rear 0.75f, 0.9f, 0.75f, 0.95f, 1.0f, 0.95f, From 2141247e0829baec36c9011f0c660ad7d8e40dd8 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 1 Jul 2020 18:03:39 +0200 Subject: [PATCH 14/85] CBoat and friends --- src/core/re3.cpp | 2 + src/modelinfo/VehicleModelInfo.cpp | 10 + src/render/Particle.h | 1 + src/render/Weather.cpp | 2 +- src/rw/VisibilityPlugins.cpp | 8 + src/rw/VisibilityPlugins.h | 1 + src/vehicles/Automobile.cpp | 2 +- src/vehicles/Bike.cpp | 2 +- src/vehicles/Boat.cpp | 961 ++++++++++++++++++++--------- src/vehicles/Boat.h | 28 +- src/vehicles/Floater.cpp | 177 +++++- src/vehicles/Floater.h | 2 + 12 files changed, 883 insertions(+), 313 deletions(-) diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 6032fc4a..d49eff50 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -474,6 +474,8 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn PCJ 600", [](){ SpawnCar(MI_PCJ600); }); DebugMenuAddCmd("Spawn", "Spawn Faggio", [](){ SpawnCar(MI_FAGGIO); }); DebugMenuAddCmd("Spawn", "Spawn Freeway", [](){ SpawnCar(MI_FREEWAY); }); + DebugMenuAddCmd("Spawn", "Spawn Squalo", [](){ SpawnCar(MI_SQUALO); }); + DebugMenuAddCmd("Spawn", "Spawn Skimmer", [](){ SpawnCar(MI_SKIMMER); }); DebugMenuAddVarBool8("Render", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil); DebugMenuAddVarBool8("Render", "Backface Culling", &gBackfaceCulling, nil); diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index d1994c06..f80e908a 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -89,7 +89,17 @@ RwObjectNameIdAssocation boatIds[] = { { "boat_flap_right", BOAT_FLAP_RIGHT, 0 }, { "boat_rearflap_left", BOAT_REARFLAP_LEFT, 0 }, { "boat_rearflap_right", BOAT_REARFLAP_RIGHT, 0 }, +#ifdef FIX_BUGS + // let's just accept both + { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, { "windscreen_hi_ok", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#else +#ifdef GTA_PS2 + { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#else + { "windscreen_hi_ok", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#endif +#endif { "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, { nil, 0, 0 } }; diff --git a/src/render/Particle.h b/src/render/Particle.h index f2c3a459..9c496fe1 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -98,5 +98,6 @@ public: }; extern bool clearWaterDrop; +extern int32 numWaterDropOnScreen; VALIDATE_SIZE(CParticle, 0x58); diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 106e2f89..945e1f5e 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -279,7 +279,7 @@ void CWeather::Update(void) } Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType]; - WindClipped = Max(1.0f, Wind); + WindClipped = Min(1.0f, Wind); if (CClock::GetHours() == 20) TrafficLightBrightness = CClock::GetMinutes() / 60.0f; diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index cff1ff16..25dffb4e 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -625,6 +625,14 @@ CVisibilityPlugins::RenderPedCB(RpAtomic *atomic) return atomic; } +float +CVisibilityPlugins::GetDistanceSquaredFromCamera(RwV3d *pos) +{ + RwV3d dist; + RwV3dSub(&dist, pos, ms_pCameraPosn); + return RwV3dDotProduct(&dist, &dist); +} + float CVisibilityPlugins::GetDistanceSquaredFromCamera(RwFrame *frame) { diff --git a/src/rw/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h index 89583432..d426abec 100644 --- a/src/rw/VisibilityPlugins.h +++ b/src/rw/VisibilityPlugins.h @@ -83,6 +83,7 @@ public: static bool VehicleVisibilityCB(RpClump *clump); static bool VehicleVisibilityCB_BigVehicle(RpClump *clump); + static float GetDistanceSquaredFromCamera(RwV3d *pos); static float GetDistanceSquaredFromCamera(RwFrame *frame); static float GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 925bc884..217b383f 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -3796,7 +3796,7 @@ void CAutomobile::DoDriveByShootings(void) { CAnimBlendAssociation *anim = nil; - CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); + CPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed(); if (playerInfo && !playerInfo->m_bDriveByAllowed) return; diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp index 6f52c33f..e52027f9 100644 --- a/src/vehicles/Bike.cpp +++ b/src/vehicles/Bike.cpp @@ -1989,7 +1989,7 @@ void CBike::DoDriveByShootings(void) { CAnimBlendAssociation *anim; - CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); + CPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed(); if (playerInfo && !playerInfo->m_bDriveByAllowed) return; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 673372b0..786b5f4d 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -2,6 +2,7 @@ #include "General.h" #include "Timecycle.h" +#include "Weather.h" #include "HandlingMgr.h" #include "CarAI.h" #include "CarCtrl.h" @@ -13,9 +14,11 @@ #include "Darkel.h" #include "Explosion.h" #include "Particle.h" +#include "ParticleObject.h" #include "WaterLevel.h" #include "Floater.h" #include "World.h" +#include "Stats.h" #include "Pools.h" #include "Pad.h" #include "Boat.h" @@ -23,6 +26,8 @@ #include "RpAnimBlend.h" #include "Record.h" +//--MIAMI: file done + #define INVALID_ORIENTATION (-9999.99f) float fShapeLength = 0.4f; @@ -51,11 +56,15 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fBrake = 0.0f; m_fSteeringLeftRight = 0.0f; m_nPadID = 0; - m_fMovingHiRotation = 0.0f; + m_fMovingRotation = 0.0f; + m_fMovingSpeed = 0.0f; + m_skimmerThingTimer = 0.0f; + m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds(); SetModelIndex(mi); pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); pFlyingHandling = mod_HandlingManager.GetFlyingPointer((eHandlingId)minfo->m_handlingId); + pBoatHandling = mod_HandlingManager.GetBoatPointer((eHandlingId)minfo->m_handlingId); minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2); m_fMass = pHandling->fMass; @@ -68,11 +77,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fGasPedal = 0.0f; m_fBrakePedal = 0.0f; - m_fPropellerZ = 0.25f; - m_fPropellerY = 0.35f; - m_waterMoveDrag = CVector(0.7f, 0.998f, 0.999f); - m_waterTurnDrag = CVector(0.85f, 0.96f, 0.96f); - _unk2 = false; + m_boat_unused3 = false; m_fVolumeUnderWater = 7.0f; m_fPrevVolumeUnderWater = 7.0f; @@ -85,6 +90,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) bIsInWater = true; m_phys_unused1 = 0.0f; + m_boat_unused2 = 0; m_bIsAnchored = true; m_fOrientation = INVALID_ORIENTATION; bTouchingWater = true; @@ -96,6 +102,11 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_afWakePointLifeTime[i] = 0.0f; m_nAmmoInClip = 20; + + if(GetModelIndex() == MI_MARQUIS) + m_boom.Init(-PI/10.0f, PI/10.0f, 0, 2); + else + m_boom.Init(-PI/5.0f, PI/5.0f, 0, 2); } void @@ -118,32 +129,51 @@ CBoat::ProcessControl(void) PruneWakeTrail(); + if(bRenderScorched) + m_fBuoyancy *= 0.99f; + + if(FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && GetModelIndex() == MI_PREDATOR){ + CVehicle *playerVeh = FindPlayerVehicle(); + if(playerVeh && playerVeh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT && + (AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || + AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE || + AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_FARAWAY || + AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_CLOSE || + AutoPilot.m_nCarMission == MISSION_ATTACKPLAYER) && + CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer){ + DMAudio.PlayOneShot(m_audioEntityId, SOUND_115, 0.0f); + m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber()&0xFFF); + } + } + int r, g, b; + RwRGBA dropColor = { 0, 0, 0, 0 }; RwRGBA splashColor, jetColor; - r = 114.75f*(CTimeCycle::GetAmbientRed() + 0.5f*CTimeCycle::GetDirectionalRed()); - g = 114.75f*(CTimeCycle::GetAmbientGreen() + 0.5f*CTimeCycle::GetDirectionalGreen()); - b = 114.75f*(CTimeCycle::GetAmbientBlue() + 0.5f*CTimeCycle::GetDirectionalBlue()); + r = 127.5f*(CTimeCycle::GetAmbientRed_Obj() + 0.5f*CTimeCycle::GetDirectionalRed()); + g = 127.5f*(CTimeCycle::GetAmbientGreen_Obj() + 0.5f*CTimeCycle::GetDirectionalGreen()); + b = 127.5f*(CTimeCycle::GetAmbientBlue_Obj() + 0.5f*CTimeCycle::GetDirectionalBlue()); r = clamp(r, 0, 255); g = clamp(g, 0, 255); b = clamp(b, 0, 255); splashColor.red = r; splashColor.green = g; splashColor.blue = b; - splashColor.alpha = CGeneral::GetRandomNumberInRange(128, 150); + splashColor.alpha = CGeneral::GetRandomNumberInRange(160, 196); - r = 242.25f*(CTimeCycle::GetAmbientRed() + 0.5f*CTimeCycle::GetDirectionalRed()); - g = 242.25f*(CTimeCycle::GetAmbientGreen() + 0.5f*CTimeCycle::GetDirectionalGreen()); - b = 242.25f*(CTimeCycle::GetAmbientBlue() + 0.5f*CTimeCycle::GetDirectionalBlue()); + r = 229.5f*(CTimeCycle::GetAmbientRed() + 0.85f*CTimeCycle::GetDirectionalRed()); + g = 229.5f*(CTimeCycle::GetAmbientGreen() + 0.85f*CTimeCycle::GetDirectionalGreen()); + b = 229.5f*(CTimeCycle::GetAmbientBlue() + 0.85f*CTimeCycle::GetDirectionalBlue()); r = clamp(r, 0, 255); g = clamp(g, 0, 255); b = clamp(b, 0, 255); jetColor.red = r; jetColor.green = g; jetColor.blue = b; - jetColor.alpha = CGeneral::GetRandomNumberInRange(96, 128); + jetColor.alpha = CGeneral::GetRandomNumberInRange(196, 228); CGeneral::GetRandomNumber(); // unused + UpdateClumpAlpha(); ProcessCarAlarm(); switch(GetStatus()){ @@ -181,7 +211,7 @@ CBoat::ProcessControl(void) bIsHandbrakeOn = false; m_fBrakePedal = 0.5f; m_fGasPedal = 0.0f; - if((GetPosition() - CWorld::Players[CWorld::PlayerInFocus].GetPos()).Magnitude() > 150.0f){ + if((GetPosition() - FindPlayerCentreOfWorld_NoSniperShift()).Magnitude() > 150.0f){ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); return; @@ -192,33 +222,42 @@ CBoat::ProcessControl(void) float collisionDamage = pHandling->fCollisionDamageMultiplier * m_fDamageImpulse; #ifdef FIX_BUGS - if (collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED && m_fHealth >= 150.0f && !bCollisionProof) { + if(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f) + collisionDamage *= 0.5f; + if (collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED && !bCollisionProof) { #else - if(collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED && m_fHealth >= 150.0f){ + if(collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED){ #endif float prevHealth = m_fHealth; - if(this == FindPlayerVehicle()){ - if(bTakeLessDamage) - m_fHealth -= (collisionDamage-25.0f)/6.0f; - else - m_fHealth -= (collisionDamage-25.0f)/2.0f; - }else{ - if(collisionDamage > 60.0f && pDriver) - pDriver->Say(SOUND_PED_CAR_COLLISION); - if(bTakeLessDamage) - m_fHealth -= (collisionDamage-25.0f)/12.0f; - else - m_fHealth -= (collisionDamage-25.0f)/4.0f; - } + if(prevHealth >= 250.0f){ +#ifndef FIX_BUGS + // if collisionDamage < 50 we actually increase health here... + if(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f) + collisionDamage *= 0.5f; +#endif + if(this == FindPlayerVehicle()){ + if(bTakeLessDamage) + m_fHealth -= (collisionDamage-25.0f)/6.0f; + else + m_fHealth -= (collisionDamage-25.0f)/2.0f; + }else{ + if(collisionDamage > 60.0f && pDriver) + pDriver->Say(SOUND_PED_CAR_COLLISION); + if(bTakeLessDamage) + m_fHealth -= (collisionDamage-25.0f)/12.0f; + else + m_fHealth -= (collisionDamage-25.0f)/4.0f; + } - if(m_fHealth <= 0.0f && prevHealth > 0.0f){ - m_fHealth = 1.0f; - m_pSetOnFireEntity = m_pDamageEntity; + if(m_fHealth <= 0.0f && prevHealth > 0.0f){ + m_fHealth = 1.0f; + m_pSetOnFireEntity = m_pDamageEntity; + } } } // Damage particles - if(m_fHealth <= 600.0f && GetStatus() != STATUS_WRECKED && + if(m_fHealth <= 460.0f && GetStatus() != STATUS_WRECKED && Abs(GetPosition().x - TheCamera.GetPosition().x) < 200.0f && Abs(GetPosition().y - TheCamera.GetPosition().y) < 200.0f){ float speedSq = m_vecMoveSpeed.MagnitudeSqr(); @@ -244,7 +283,7 @@ CBoat::ProcessControl(void) smokePos = GetMatrix() * smokePos; // On fire - if(m_fHealth < 150.0f){ + if(m_fHealth < 250.0f){ CParticle::AddParticle(PARTICLE_CARFLAME, smokePos, CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(2.25f/200.0f, 0.09f)), nil, 0.9f); @@ -261,23 +300,26 @@ CBoat::ProcessControl(void) if(speedSq < 0.25f && (CTimer::GetFrameCounter() + m_randomSeed) & 1) CParticle::AddParticle(PARTICLE_ENGINE_STEAM, smokePos, smokeDir); - if(speedSq < 0.25f && m_fHealth <= 350.0f) + if(speedSq < 0.25f && m_fHealth <= 390.0f) CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, smokePos, 1.25f*smokeDir); } + bool bSeparateTurnForce = bHasHitWall; CPhysical::ProcessControl(); CVector buoyanceImpulse(0.0f, 0.0f, 0.0f); CVector buoyancePoint(0.0f, 0.0f, 0.0f); - if(mod_Buoyancy.ProcessBuoyancy(this, pHandling->fBuoyancy, &buoyancePoint, &buoyanceImpulse)){ + if(mod_Buoyancy.ProcessBuoyancyBoat(this, pHandling->fBuoyancy, &buoyancePoint, &buoyanceImpulse, bSeparateTurnForce)){ // Process boat in water if(0.1f * m_fMass * GRAVITY*CTimer::GetTimeStep() < buoyanceImpulse.z){ bBoatInWater = true; bIsInWater = true; if (GetUp().z < -0.6f && Abs(GetMoveSpeed().x) < 0.05 && Abs(GetMoveSpeed().y) < 0.05) { bIsDrowning = true; - if (pDriver) + if (pDriver){ + pDriver->bTouchingWater = true; pDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + } } else bIsDrowning = false; @@ -289,32 +331,61 @@ CBoat::ProcessControl(void) m_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater; m_vecBuoyancePoint = buoyancePoint; - ApplyMoveForce(buoyanceImpulse); - if(!onLand) - ApplyTurnForce(buoyanceImpulse, buoyancePoint); + if(GetModelIndex() == MI_SKIMMER && GetUp().z < -0.5f && Abs(m_vecMoveSpeed.x) < 0.2f && Abs(m_vecMoveSpeed.y) < 0.2f) + ApplyMoveForce(0.03f*buoyanceImpulse); + else + ApplyMoveForce(buoyanceImpulse); + if(bSeparateTurnForce) + ApplyTurnForce(0.4f*buoyanceImpulse, buoyancePoint); + + // TODO: what is this? + if(GetModelIndex() == MI_SKIMMER) + if(m_skimmerThingTimer != 0.0f || + GetForward().z < -0.5f && GetUp().z > -0.5f && m_vecMoveSpeed.z < -0.15f && + buoyanceImpulse.z > 0.01f*m_fMass * GRAVITY*CTimer::GetTimeStep() && + buoyanceImpulse.z < 0.4f*m_fMass * GRAVITY*CTimer::GetTimeStep()){ + float turnImpulse = -0.00017f*GetForward().z*buoyanceImpulse.z * m_fMass*CTimer::GetTimeStep(); + ApplyTurnForce(turnImpulse*GetForward(), GetUp()); + bBoatInWater = false; + //BUG? aren't we forgetting the timestep here? + float moveImpulse = -0.5f*DotProduct(m_vecMoveSpeed, GetForward()) * m_fMass; + ApplyMoveForce(moveImpulse*GetForward()); + if(m_skimmerThingTimer == 0.0f) + m_skimmerThingTimer = CTimer::GetTimeInMilliseconds() + 300.0f; + else if(m_skimmerThingTimer < CTimer::GetTimeInMilliseconds()) + m_skimmerThingTimer = 0.0f; + } if(!onLand && bBoatInWater && GetUp().z > 0.0f){ - float impulse; - if(m_fGasPedal > 0.05f) - impulse = m_vecMoveSpeed.MagnitudeSqr()*pHandling->fSuspensionForceLevel*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f*m_fGasPedal; + float impulse = m_vecMoveSpeed.MagnitudeSqr()*pBoatHandling->fAqPlaneForce*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f; + if(GetModelIndex() == MI_SKIMMER) + impulse *= 1.0f + m_fGasPedal; + else if(m_fGasPedal > 0.05f) + impulse *= m_fGasPedal; else impulse = 0.0f; - impulse = Min(impulse, GRAVITY*pHandling->fSuspensionDampingLevel*m_fMass*CTimer::GetTimeStep()); + impulse = Min(impulse, GRAVITY*pBoatHandling->fAqPlaneLimit*m_fMass*CTimer::GetTimeStep()); ApplyMoveForce(impulse*GetUp()); - ApplyTurnForce(impulse*GetUp(), buoyancePoint - pHandling->fSuspensionBias*GetForward()); + ApplyTurnForce(impulse*GetUp(), buoyancePoint - pBoatHandling->fAqPlaneOffset*GetForward()); } // Handle boat moving forward - if(Abs(m_fGasPedal) > 0.05f || m_vecMoveSpeed.Magnitude() > 0.01f){ - if(bBoatInWater) + float fwdSpeed = 1.0f; + if(Abs(m_fGasPedal) > 0.05f || (fwdSpeed = m_vecMoveSpeed.Magnitude2D()) > 0.01f){ + if(bBoatInWater && fwdSpeed > 0.05f) AddWakePoint(GetPosition()); - float steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward()); -// if (GetModelIndex() == MI_GHOST) -// steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward())*0.3f; - if(steerFactor < 0.0f) steerFactor = 0.0f; + float steerFactor = 1.0f; + if(GetStatus() == STATUS_PLAYER){ + float steerLoss = DotProduct(m_vecMoveSpeed, GetForward())*pHandling->fTractionBias; + if(CPad::GetPad(0)->GetHandBrake()) + steerLoss *= 0.5f; + steerFactor -= steerLoss; + steerFactor = clamp(steerFactor, 0.0f, 1.0f); + } - CVector propeller(0.0f, -pHandling->Dimension.y*m_fPropellerY, -pHandling->Dimension.z*m_fPropellerZ); + CVector boundMin = GetColModel()->boundingBox.min; + CVector propeller(0.0f, boundMin.y*pBoatHandling->fThrustY, boundMin.z*pBoatHandling->fThrustZ); propeller = Multiply3x3(GetMatrix(), propeller); CVector propellerWorld = GetPosition() + propeller; @@ -330,7 +401,11 @@ CBoat::ProcessControl(void) propellerDepth = SQR(propellerDepth); bPropellerInWater = true; - if(Abs(m_fGasPedal) > 0.05f){ + bool bSlowAhead = false; + if(Abs(m_fGasPedal) > 0.01f && GetModelIndex() != MI_SKIMMER){ + if(Abs(m_fGasPedal) < 0.05f) + bSlowAhead = true; + CVector forceDir = Multiply3x3(GetMatrix(), CVector(-steerSin, steerCos, -Abs(m_fSteerAngle))); CVector force = propellerDepth * m_fGasPedal * 40.0f * pHandling->Transmission.fEngineAcceleration * pHandling->fMass * forceDir; if(force.z > 0.2f) @@ -345,80 +420,75 @@ CBoat::ProcessControl(void) ApplyMoveForce(force * CTimer::GetTimeStep()); }else{ ApplyMoveForce(force * CTimer::GetTimeStep()); - ApplyTurnForce(force * CTimer::GetTimeStep(), propeller - pHandling->fTractionBias*GetUp()); - float rightForce = DotProduct(GetRight(), force); - ApplyTurnForce(-rightForce*GetRight() * CTimer::GetTimeStep(), GetUp()); + ApplyTurnForce(force * CTimer::GetTimeStep(), propeller - pBoatHandling->fThrustAppZ*GetUp()); + float rightForce = -DotProduct(GetRight(), force)*pHandling->fTractionMultiplier; + ApplyTurnForce(rightForce*GetRight() * CTimer::GetTimeStep(), GetUp()); } // Spray some particles CVector jetDir = -0.04f * force; if(m_fGasPedal > 0.0f){ if(GetStatus() == STATUS_PLAYER){ - bool cameraHack = TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || - TheCamera.WhoIsInControlOfTheCamera == CAMCONTROL_OBBE; CVector sternPos = GetColModel()->boundingBox.min; sternPos.x = 0.0f; sternPos.z = 0.0f; sternPos = Multiply3x3(GetMatrix(), sternPos); - CVector jetPos = GetPosition() + sternPos; - if(cameraHack) - jetPos.z = 1.0f; - else - jetPos.z = 0.0f; - -#ifdef PC_PARTICLE CVector wakePos = GetPosition() + sternPos; - wakePos.z -= 0.65f; -#else - CVector wakePos = GetPosition() + sternPos; - wakePos.z = -0.3f; -#endif - - CVector wakeDir = 0.75f * jetDir; - - CParticle::AddParticle(PARTICLE_BOAT_THRUSTJET, jetPos, jetDir, nil, 0.0f, jetColor); -#ifdef PC_PARTICLE - CParticle::AddParticle(PARTICLE_CAR_SPLASH, jetPos, 0.25f * jetDir, nil, 1.0f, splashColor, + // no actual particles for player... + }else if(IsVisible() && ((CTimer::GetFrameCounter() + m_randomSeed) & 1) && + CVisibilityPlugins::GetDistanceSquaredFromCamera((RwV3d*)&propellerWorld) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){ + jetDir.z = 0.015f; + jetDir.x *= 3.5f; + jetDir.y *= 3.5f; + propellerWorld.z += 0.5f; + + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 1.25f, jetColor, + CGeneral::GetRandomNumberInRange(0, 5), + CGeneral::GetRandomNumberInRange(0, 90), 1, 500); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, propellerWorld, 0.75f * jetDir, nil, 0.5f, splashColor, CGeneral::GetRandomNumberInRange(0, 30), - CGeneral::GetRandomNumberInRange(0, 90), 3); -#endif - //TODO: MIAMI: - //if(!cameraHack) - // CParticle::AddParticle(PARTICLE_BOAT_WAKE, wakePos, wakeDir, nil, 0.0f, jetColor); - }else if((CTimer::GetFrameCounter() + m_randomSeed) & 1){ -#ifdef PC_PARTICLE - jetDir.z = 0.018f; - jetDir.x *= 0.01f; - jetDir.y *= 0.01f; - propellerWorld.z += 1.5f; - - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 1.5f, jetColor); -#else - jetDir.z = 0.018f; - jetDir.x *= 0.03f; - jetDir.y *= 0.03f; - propellerWorld.z += 1.0f; - - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 0.0f, jetColor); -#endif - -#ifdef PC_PARTICLE - CParticle::AddParticle(PARTICLE_CAR_SPLASH, propellerWorld, 0.1f * jetDir, nil, 0.5f, splashColor, - CGeneral::GetRandomNumberInRange(0, 30), - CGeneral::GetRandomNumberInRange(0, 90), 3); -#endif + CGeneral::GetRandomNumberInRange(0, 45), 3, 500); } } - }else if(!onLand){ - float force = 50.0f*DotProduct(m_vecMoveSpeed, GetForward()); - if(force > 10.0f) force = 10.0f; + }else + bSlowAhead = true; + + if(!onLand && bSlowAhead){ + float force = pHandling->fTractionLoss*DotProduct(m_vecMoveSpeed, GetForward()); + force = Min(force, 0.01f*m_fTurnMass); + if(m_fGasPedal > 0.01f){ + if(GetStatus() == STATUS_PLAYER) + force *= (0.55f - Abs(m_fGasPedal)) * 1.3f; + else + force *= (0.55f - Abs(m_fGasPedal)) * 2.5f; + } + if(m_fGasPedal < 0.0f && force > 0.0f || m_fGasPedal > 0.0f && force < 0.0f) + force *= -1.0f; CVector propellerForce = propellerDepth * Multiply3x3(GetMatrix(), force*CVector(-steerSin, 0.0f, 0.0f)); - ApplyMoveForce(propellerForce * CTimer::GetTimeStep()*0.5f); - ApplyTurnForce(propellerForce * CTimer::GetTimeStep()*0.5f, propeller); + ApplyMoveForce(propellerForce * CTimer::GetTimeStep()); + ApplyTurnForce(propellerForce * CTimer::GetTimeStep(), propeller); + float rightForce = -steerSin * force * 0.75f/steerFactor * Max(CTimer::GetTimeStep(), 0.01f); + ApplyTurnForce(GetRight() * rightForce, GetUp()); } }else bPropellerInWater = false; + + if(pHandling->fSuspensionBias != 0.0f){ + CVector right = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f)); + float rightSpeed = DotProduct(m_vecMoveSpeed, right); + float impulse = 0.1f*pHandling->fSuspensionBias * m_fMass * m_fVolumeUnderWater * rightSpeed * CTimer::GetTimeStep(); + ApplyMoveForce(right - impulse * 0.3f * CVector(-right.y, right.x, 0.0f)); + } + + if(GetStatus() == STATUS_PLAYER && CPad::GetPad(0)->GetHandBrake()){ + float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()); + if(fwdSpeed > 0.0f){ + float impulse = -0.1f*pHandling->fSuspensionLowerLimit * m_fMass * m_fVolumeUnderWater * fwdSpeed * CTimer::GetTimeStep(); + ApplyMoveForce(impulse * GetForward()); + } + } } // Slow down or push down boat as it approaches the world limits @@ -427,111 +497,249 @@ CBoat::ProcessControl(void) m_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MAX_Y-100.0f))*0.01f); // north m_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MIN_Y+100.0f))*0.01f); // south - if(!onLand && bBoatInWater) + if(!onLand && bBoatInWater && !bSeparateTurnForce) ApplyWaterResistance(); - // No idea what exactly is going on here besides drag in YZ - float fx = Pow(m_waterTurnDrag.x, CTimer::GetTimeStep()); - float fy = Pow(m_waterTurnDrag.y, CTimer::GetTimeStep()); - float fz = Pow(m_waterTurnDrag.z, CTimer::GetTimeStep()); - m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space - // TODO: figure this out - float magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx; - m_vecTurnSpeed.y *= fy; - m_vecTurnSpeed.z *= fz; - float forceUp = (magic - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass; - m_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed); // back to world - CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass); - ApplyTurnForce(CVector(0.0f, 0.0f, forceUp), com + GetForward()); + if((GetModelIndex() != MI_SKIMMER || m_skimmerThingTimer == 0.0f) && !bSeparateTurnForce){ + // No idea what exactly is going on here besides drag in YZ + float fx = Pow(pBoatHandling->vecTurnRes.x, CTimer::GetTimeStep()); + float fy = Pow(pBoatHandling->vecTurnRes.y, CTimer::GetTimeStep()); + float fz = Pow(pBoatHandling->vecTurnRes.z, CTimer::GetTimeStep()); + m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space + // TODO: figure this out + float magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx; + m_vecTurnSpeed.y *= fy; + m_vecTurnSpeed.z *= fz; + float forceUp = (magic - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass; + m_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed); // back to world + CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass); + ApplyTurnForce(forceUp*GetUp(), com + GetForward()); + } m_nDeltaVolumeUnderWater = (m_fVolumeUnderWater-m_fPrevVolumeUnderWater)*10000; // Falling into water - if(!onLand && bBoatInWater && GetUp().z > 0.0f && m_nDeltaVolumeUnderWater > 200){ - DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, m_nDeltaVolumeUnderWater); + if(!onLand && bBoatInWater && GetUp().z > 0.0f){ + float splashVol = m_nDeltaVolumeUnderWater*pBoatHandling->fWaveAudioMult; + if(splashVol > 200.0f) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, splashVol); - float speedUp = m_vecMoveSpeed.MagnitudeSqr() * m_nDeltaVolumeUnderWater * 0.0004f; - if(speedUp + m_vecMoveSpeed.z > pHandling->fBrakeDeceleration) - speedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z; - if(speedUp < 0.0f) speedUp = 0.0f; - float speedFwd = DotProduct(m_vecMoveSpeed, GetForward()); - speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias; - CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp); - CVector splashImpulse = speed * m_fMass; - ApplyMoveForce(splashImpulse); - ApplyTurnForce(splashImpulse, buoyancePoint); + if(m_nDeltaVolumeUnderWater > 200){ + float speedUp = m_vecMoveSpeed.MagnitudeSqr() * m_nDeltaVolumeUnderWater * 0.001f; + if(speedUp + m_vecMoveSpeed.z > pHandling->fBrakeDeceleration) + speedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z; + if(speedUp < 0.0f) speedUp = 0.0f; + float speedFwd = DotProduct(m_vecMoveSpeed, GetForward()); + speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias; + CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp); + CVector splashImpulse = speed * m_fMass; + ApplyMoveForce(splashImpulse); + ApplyTurnForce(splashImpulse, buoyancePoint); + } } - // Spray particles on sides of boat -#ifdef PC_PARTICLE - if(m_nDeltaVolumeUnderWater > 75) -#else - if(m_nDeltaVolumeUnderWater > 120) -#endif - { - float speed = m_vecMoveSpeed.Magnitude(); - float splash1Size = speed; - float splash2Size = float(m_nDeltaVolumeUnderWater) * 0.005f * 0.2f; - float front = 0.9f * GetColModel()->boundingBox.max.y; - if(splash1Size > 0.75f) splash1Size = 0.75f; + // Splashes + float speed = m_vecMoveSpeed.Magnitude(); + if(speed > 0.05f && GetUp().x > 0.0f && !TheCamera.GetLookingForwardFirstPerson() && IsVisible() && + (AutoPilot.m_nCarMission != MISSION_CRUISE || (CTimer::GetFrameCounter()&2) == 0)){ + CVector splashPos, splashDir; + float splashSize, front, waterLevel; - CVector dir, pos; + switch(GetModelIndex()){ + case MI_RIO: + splashSize = speed; + front = 0.9f * GetColModel()->boundingBox.max.y; + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir += 0.35f*speed*GetRight(); + splashPos = GetPosition() + 1.85f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_SQUALO: + splashSize = speed; + front = 0.75f * GetColModel()->boundingBox.max.y; + splashDir = -0.125f * m_vecMoveSpeed; + splashDir.z += 0.15f*speed; + splashDir += 0.25f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint + 0.5f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_REEFER: + splashSize = speed; + front = 0.75f * GetColModel()->boundingBox.max.y; + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.15f*speed; + splashDir += 0.5f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint + 1.3f*GetRight() + front*GetForward(); + break; + case MI_COASTG: + splashSize = 0.25f*speed; + front = 0.8f * GetColModel()->boundingBox.max.y; + splashDir = 0.165f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir += 0.15f*speed*GetRight(); + splashPos = GetPosition() + 0.65f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_DINGHY: + splashSize = 0.25f*speed; + front = 0.9f * GetColModel()->boundingBox.max.y; + splashDir = 0.35f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir += 0.25f*speed*GetRight(); + splashPos = GetPosition() + 0.6f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + default: + splashSize = speed; + front = 0.9f * GetColModel()->boundingBox.max.y; + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir += 0.35f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint + 0.5f*GetRight() + front*GetForward(); + break; + } + if(splashSize > 0.75f) splashSize = 0.75f; + if(AutoPilot.m_nCarMission == MISSION_CRUISE) + splashDir *= 1.5f; + static float lifeMult = 1000.0f; + static float lifeBase = 300.0f; + splashDir.z += 0.0003f*m_nDeltaVolumeUnderWater; + CWaterLevel::GetWaterLevel(splashPos, &waterLevel, true); + if(splashPos.z-waterLevel < 3.0f && + CVisibilityPlugins::GetDistanceSquaredFromCamera((RwV3d*)&splashPos) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){ + splashPos.z = waterLevel + 0.1f; + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashPos, 0.75f*splashDir, nil, splashSize+0.1f, splashColor, + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), CGeneral::GetRandomNumberInRange(0.0f, 90.0f), + 1, lifeBase + splashDir.z*lifeMult); + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, splashPos, splashDir, nil, splashSize, jetColor, + CGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), + 0, lifeBase + splashDir.z*lifeMult); + } - // right -#ifdef PC_PARTICLE - dir = -0.5f*m_vecMoveSpeed; - dir.z += 0.1f*speed; - dir += 0.5f*GetRight()*speed; - pos = front*GetForward() + 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint; - CWaterLevel::GetWaterLevel(pos, &pos.z, true); -#else - dir = 0.3f*m_vecMoveSpeed; - dir.z += 0.05f*speed; - dir += 0.5f*GetRight()*speed; - pos = (GetPosition() + m_vecBuoyancePoint) + (1.5f*GetRight()); -#endif - -#ifdef PC_PARTICLE - CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor, - CGeneral::GetRandomNumberInRange(0, 30), - CGeneral::GetRandomNumberInRange(0, 90), 1); - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor); -#else - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size); -#endif - + switch(GetModelIndex()){ + case MI_RIO: + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir -= 0.35f*speed*GetRight(); + splashPos = GetPosition() - 1.85f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_SQUALO: + splashDir = -0.125f * m_vecMoveSpeed; + splashDir.z += 0.15f*speed; + splashDir -= 0.25f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint - 0.5f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_REEFER: + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.15f*speed; + splashDir -= 0.5f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint - 1.3f*GetRight() + front*GetForward(); + break; + case MI_COASTG: + splashDir = 0.165f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir -= 0.15f*speed*GetRight(); + splashPos = GetPosition() - 0.65f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + case MI_DINGHY: + splashDir = 0.35f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir -= 0.25f*speed*GetRight(); + splashPos = GetPosition() - 0.6f*GetRight() + front*GetForward(); + splashPos.z += 0.5f; + break; + default: + splashDir = -0.5f * m_vecMoveSpeed; + splashDir.z += 0.25f*speed; + splashDir -= 0.35f*speed*GetRight(); + splashPos = GetPosition() + m_vecBuoyancePoint - 0.5f*GetRight() + front*GetForward(); + break; + } + if(AutoPilot.m_nCarMission == MISSION_CRUISE) + splashDir *= 1.5f; + splashDir.z += 0.0003f*m_nDeltaVolumeUnderWater; + CWaterLevel::GetWaterLevel(splashPos, &waterLevel, true); + if(splashPos.z-waterLevel < 3.0f && + CVisibilityPlugins::GetDistanceSquaredFromCamera((RwV3d*)&splashPos) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){ + splashPos.z = waterLevel + 0.1f; + CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashPos, 0.75f*splashDir, nil, splashSize+0.1f, splashColor, + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), CGeneral::GetRandomNumberInRange(0.0f, 90.0f), + 1, lifeBase + splashDir.z*lifeMult); + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, splashPos, splashDir, nil, splashSize, jetColor, + CGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), + 0, lifeBase + splashDir.z*lifeMult); + } + } - // left -#ifdef PC_PARTICLE - dir = -0.5f*m_vecMoveSpeed; - dir.z += 0.1f*speed; - dir -= 0.5f*GetRight()*speed; - pos = front*GetForward() - 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint; - CWaterLevel::GetWaterLevel(pos, &pos.z, true); -#else - dir = 0.3f*m_vecMoveSpeed; - dir.z += 0.05f*speed; - dir -= 0.5f*GetRight()*speed; - pos = (GetPosition() + m_vecBuoyancePoint) - (1.5f*GetRight()); -#endif - -#ifdef PC_PARTICLE - CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor, - CGeneral::GetRandomNumberInRange(0, 30), - CGeneral::GetRandomNumberInRange(0, 90), 1); - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor); -#else - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size); -#endif + // Spray waterdrops on screen + if(TheCamera.GetLookingForwardFirstPerson() && FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && + m_nDeltaVolumeUnderWater > 0 && numWaterDropOnScreen < 20){ + CVector dropPos; + CVector dropDir(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f), CGeneral::GetRandomNumberInRange(1.0f, 0.75f), 0.0f); + + int frm = CGeneral::GetRandomNumber() & 1; + if(TheCamera.m_CameraAverageSpeed < 0.35f){ + dropPos.x = CGeneral::GetRandomNumberInRange(50, (int)SCREEN_WIDTH-50); + dropPos.y = CGeneral::GetRandomNumberInRange(50, (int)SCREEN_HEIGHT-50); + }else{ + dropPos.x = CGeneral::GetRandomNumberInRange(200, (int)SCREEN_WIDTH-200); + dropPos.y = CGeneral::GetRandomNumberInRange(150, (int)SCREEN_HEIGHT-150); + } + dropPos.z = 1.0f; + + if(TheCamera.m_CameraAverageSpeed > 0.35f){ + if((int)SCREEN_WIDTH / 2 < dropPos.x) + dropPos.x += CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f; + else + dropPos.x -= CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f; + + if((int)SCREEN_HEIGHT / 2 < dropPos.y) + dropPos.y += CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f; + else + dropPos.y -= CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f; + } + + if(CParticle::AddParticle(PARTICLE_WATERDROP, dropPos, dropDir, nil, + CGeneral::GetRandomNumberInRange(0.1f, 0.15f), dropColor, 0, 0, frm)) + numWaterDropOnScreen++; + } + + if(m_fPrevVolumeUnderWater == 0.0f && m_fVolumeUnderWater > 0.0f && GetModelIndex() == MI_SKIMMER){ + CVector splashDir(0.0f, 0.0f, 0.25f*speed); + CVector splashPos = GetPosition(); + float level; + CWaterLevel::GetWaterLevel(splashPos, &level, true); + splashPos.z = level; + CParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, splashPos, splashDir, 0.0f, 65, splashColor, true); } m_fPrevVolumeUnderWater = m_fVolumeUnderWater; }else{ bBoatInWater = false; bIsInWater = false; +#ifdef FIX_BUGS bIsDrowning = false; +#endif } + if(m_modelIndex == MI_SKIMMER && CTimer::GetTimeStep() > 0.0f){ + if(GetStatus() == STATUS_PLAYER){ + if(m_fMovingSpeed < 0.22f) + m_fMovingSpeed += 0.001f*CTimer::GetTimeStep(); + FlyingControl(FLIGHT_MODEL_SEAPLANE); + }else{ + if(m_fMovingSpeed > 0.0005f*CTimer::GetTimeStep()) + m_fMovingSpeed -= 0.0005f*CTimer::GetTimeStep(); + else + m_fMovingSpeed = 0.0f; + } + }else if(bCheat8) + FlyingControl(FLIGHT_MODEL_PLANE); + if(m_bIsAnchored){ m_vecMoveSpeed.x = 0.0f; m_vecMoveSpeed.y = 0.0f; @@ -542,29 +750,7 @@ CBoat::ProcessControl(void) // is this some inlined CPlaceable method? CVector pos = GetPosition(); GetMatrix().RotateZ(m_fOrientation - GetForward().Heading()); - GetMatrix().GetPosition() = pos; - } - } - - if (m_modelIndex == MI_SKIMMER && CTimer::GetTimeStep() > 0.0f) { - if (GetStatus() == STATUS_PLAYER) { - if (m_fPropellerY <= CTimer::GetTimeStep() * 0.0005f) { - m_fPropellerY = 0.0f; - } - else { - m_fPropellerY -= CTimer::GetTimeStep() * 0.0005f; - } - } - else { - if (m_fPropellerY < 0.22f) { - m_fPropellerY += CTimer::GetTimeStep() * 0.001f; - } - FlyingControl(FLIGHT_MODEL_SEAPLANE); - } - } - else { - if (bCheat8) { - FlyingControl(FLIGHT_MODEL_PLANE); + GetMatrix().SetTranslateOnly(pos); } } @@ -596,17 +782,21 @@ CBoat::ProcessControlInputs(uint8 pad) m_fGasPedal = m_fAccelerate; } +float fSeaPlaneWaterResistance = 30.0f; + void CBoat::ApplyWaterResistance(void) { - float fwdSpeed = DotProduct(GetMoveSpeed(), GetForward()); // TODO: figure out how this works - float magic = (SQR(fwdSpeed) + 0.05f) * (0.001f * SQR(m_fVolumeUnderWater) * m_fMass) + 1.0f; + float resistance = 0.001f * pHandling->fSuspensionForceLevel * SQR(m_fVolumeUnderWater) * m_fMass; + if(GetModelIndex() == MI_SKIMMER) + resistance *= fSeaPlaneWaterResistance; + float fwdSpeed = DotProduct(GetMoveSpeed(), GetForward()); + float magic = (SQR(fwdSpeed) + 0.05f) * resistance + 1.0f; magic = Abs(magic); - // FRAMETIME - float fx = Pow(m_waterMoveDrag.x/magic, 0.5f*CTimer::GetTimeStep()); - float fy = Pow(m_waterMoveDrag.y/magic, 0.5f*CTimer::GetTimeStep()); - float fz = Pow(m_waterMoveDrag.z/magic, 0.5f*CTimer::GetTimeStep()); + float fx = Pow(pBoatHandling->vecMoveRes.x/magic, 0.5f*CTimer::GetTimeStep()); + float fy = Pow(pBoatHandling->vecMoveRes.y/magic, 0.5f*CTimer::GetTimeStep()); + float fz = Pow(pBoatHandling->vecMoveRes.z/magic, 0.5f*CTimer::GetTimeStep()); m_vecMoveSpeed = Multiply3x3(m_vecMoveSpeed, GetMatrix()); // invert - to local space m_vecMoveSpeed.x *= fx; @@ -655,19 +845,14 @@ CBoat::BlowUpCar(CEntity *culprit) m_nBombTimer = 0; TheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z); - if(this == FindPlayerVehicle()) - FindPlayerPed()->m_fHealth = 0.0f; // kill player - if(pDriver){ - CDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION); - pDriver->SetDead(); - pDriver->FlagToDestroyWhenNextProcessed(); - } + KillPedsInVehicle(); bEngineOn = false; bLightsOn = false; ChangeLawEnforcerState(false); - CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0); + CExplosion::AddExplosion(this, culprit, EXPLOSION_HELI, GetPosition(), 0); + CDarkel::RegisterCarBlownUpByPlayer(this); if(m_aBoatNodes[BOAT_MOVING] == nil) return; @@ -695,6 +880,7 @@ CBoat::BlowUpCar(CEntity *culprit) RpAtomicSetFrame(atomic, frame); CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); obj->AttachToRwObject((RwObject*)atomic); + obj->bDontStream = true; // init object obj->m_fMass = 10.0f; @@ -724,7 +910,7 @@ CBoat::BlowUpCar(CEntity *culprit) dist.Normalise(); if(GetUp().z > 0.0f) dist += GetUp(); - obj->GetMatrix().GetPosition() += GetUp(); + obj->GetMatrix().GetPosition() += dist; CWorld::Add(obj); @@ -734,41 +920,200 @@ CBoat::BlowUpCar(CEntity *culprit) RpAtomicSetFlags(atomic, 0); } +void +CBoat::PreRender(void) +{ + CMatrix matrix; + CVector pos; + RpAtomic *atomic; + + if(GetModelIndex() == MI_SKIMMER){ + m_fMovingRotation += m_fMovingSpeed*CTimer::GetTimeStep(); + if(m_fMovingRotation > TWOPI) m_fMovingRotation -= TWOPI; + int alpha = (1.0f - Min(2.0f*m_fMovingSpeed*8.0f/PI, 1.0f))*255.0f; + if(GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE || GetStatus() == STATUS_PLAYER_PLAYBACKFROMBUFFER){ + if(m_aBoatNodes[BOAT_RUDDER]){ + float sine = Sin(m_fSteerAngle); + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_RUDDER])); + pos = matrix.GetPosition(); + matrix.SetRotate(0.0f, 0.0f, -m_fSteerAngle); + matrix.Rotate(0.0f, DEGTORAD(22.0f)*sine, 0.0f); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_FLAP_LEFT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_LEFT])); + pos = matrix.GetPosition(); + matrix.SetRotateX(-m_fSteerAngle); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_FLAP_RIGHT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_RIGHT])); + pos = matrix.GetPosition(); + matrix.SetRotateX(m_fSteerAngle); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_REARFLAP_LEFT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_LEFT])); + pos = matrix.GetPosition(); + matrix.SetRotateX(-CPad::GetPad(0)->GetSteeringUpDown()/128.0f); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_REARFLAP_RIGHT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_RIGHT])); + pos = matrix.GetPosition(); + matrix.SetRotateX(-CPad::GetPad(0)->GetSteeringUpDown()/128.0f); + matrix.Translate(pos); + matrix.UpdateRW(); + } + } + if(m_aBoatNodes[BOAT_MOVING]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING])); + pos = matrix.GetPosition(); + matrix.SetRotateY(m_fMovingRotation); + matrix.Translate(pos); + matrix.UpdateRW(); + + atomic = nil; + RwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic); + if(atomic) + SetComponentAtomicAlpha(atomic, alpha); + } + if(m_aBoatNodes[BOAT_WINDSCREEN]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_WINDSCREEN])); + pos = matrix.GetPosition(); + matrix.SetRotateY(-m_fMovingRotation); + matrix.Translate(pos); + matrix.UpdateRW(); + + atomic = nil; + RwFrameForAllObjects(m_aBoatNodes[BOAT_WINDSCREEN], GetBoatAtomicObjectCB, &atomic); + if(atomic) + SetComponentAtomicAlpha(atomic, Max(150-alpha, 0)); + } + //CShadows::StoreShadowForVehicle(this); + }else if(GetModelIndex() == MI_COASTG || GetModelIndex() == MI_DINGHY || GetModelIndex() == MI_RIO || + GetModelIndex() == MI_SQUALO || GetModelIndex() == MI_MARQUIS){ + if(m_aBoatNodes[BOAT_RUDDER]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_RUDDER])); + pos = matrix.GetPosition(); + matrix.SetRotateZ(-m_fSteerAngle); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_REARFLAP_LEFT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_LEFT])); + pos = matrix.GetPosition(); + matrix.SetRotateZ(-m_fSteerAngle); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_REARFLAP_RIGHT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_RIGHT])); + pos = matrix.GetPosition(); + matrix.SetRotateZ(-m_fSteerAngle); + matrix.Translate(pos); + matrix.UpdateRW(); + } + } + + if(GetModelIndex() == MI_RIO || GetModelIndex() == MI_MARQUIS){ + float axes[3] = { 0.0f, 0.0f, 0.0f }; + m_boom.Process(this); + axes[m_boom.m_nAxis] = m_boom.m_fAngle; + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_LEFT])); + pos = matrix.GetPosition(); + matrix.SetRotate(axes[0], axes[1], axes[2]); + matrix.Translate(pos); + matrix.UpdateRW(); + } + + if(GetModelIndex() == MI_RIO){ + // That little wind propeller + if(m_aBoatNodes[BOAT_FLAP_RIGHT]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_RIGHT])); + pos = matrix.GetPosition(); + + float flapHeading = matrix.GetForward().Heading(); + float boatHeading = GetForward().Heading(); + float rot = -DEGTORAD(45.0f) - (flapHeading + boatHeading); + // eh what? + rot = CGeneral::LimitRadianAngle(rot); + if(rot > HALFPI) rot = PI; + else if(rot < -HALFPI) rot = -PI; + rot = clamp(rot, -DEGTORAD(63.0f), DEGTORAD(63.0f)); + m_fMovingSpeed += (0.008f * CWeather::Wind + 0.002f) * rot; + m_fMovingSpeed *= Pow(0.9985f, CTimer::GetTimeStep())/(500.0f*SQR(m_fMovingSpeed) + 1.0f); + + matrix.SetRotateZ(flapHeading + m_fMovingSpeed*CTimer::GetTimeStep()); + matrix.Translate(pos); + matrix.UpdateRW(); + } + if(m_aBoatNodes[BOAT_MOVING]){ + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING])); + pos = matrix.GetPosition(); + matrix.SetRotateY(m_fMovingRotation); + matrix.Translate(pos); + matrix.UpdateRW(); + + CVector wind = CVector(0.707f, 0.707f, 0.0f) * (CWeather::Wind + 0.15f)*0.4f; + m_fMovingRotation += (m_vecMoveSpeed + wind).Magnitude()*CTimer::GetTimeStep(); + } + }else if(GetModelIndex() == MI_PREDATOR || GetModelIndex() == MI_REEFER){ + if (m_aBoatNodes[BOAT_MOVING] != nil) { + matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING])); + + CVector pos = matrix.GetPosition(); + matrix.SetRotateZ(m_fMovingRotation); + matrix.Translate(pos); + + matrix.UpdateRW(); + if (CVehicle::bWheelsOnlyCheat) { + RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[BOAT_MOVING])); + } + } + m_fMovingRotation += 0.02f * CTimer::GetTimeStep(); + } +} + RwIm3DVertex KeepWaterOutVertices[4]; RwImVertexIndex KeepWaterOutIndices[6]; void CBoat::Render() { - CMatrix matrix; - - if (m_aBoatNodes[BOAT_MOVING] != nil) { - matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING])); - - CVector pos = matrix.GetPosition(); - matrix.SetRotateZ(m_fMovingHiRotation); - matrix.Translate(pos); - - matrix.UpdateRW(); - if (CVehicle::bWheelsOnlyCheat) { - RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[BOAT_MOVING])); - } - } - m_fMovingHiRotation += 0.05f; ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2); + m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000; if (!CVehicle::bWheelsOnlyCheat) CEntity::Render(); - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255); + if(GetModelIndex() == MI_SKIMMER) + return; KeepWaterOutIndices[0] = 0; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255); KeepWaterOutIndices[1] = 2; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255); KeepWaterOutIndices[2] = 1; - RwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255); KeepWaterOutIndices[3] = 1; KeepWaterOutIndices[4] = 2; KeepWaterOutIndices[5] = 3; + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255); switch (GetModelIndex()) { + case MI_RIO: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.3f, -1.016f, 0.51f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.3f, -1.016f, 0.51f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.3f, -2.832f, 0.51f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.3f, -2.832f, 0.51f); + break; + case MI_SQUALO: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.222f, 2.004f, 0.846f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.222f, 2.004f, 0.846f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.24f, -1.367f, 0.846f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.24f, -1.367f, 0.846f); + break; case MI_SPEEDER: RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f); RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.15f, 3.61f, 1.03f); @@ -782,12 +1127,37 @@ CBoat::Render() RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.66f, -4.48f, 0.83f); break; case MI_PREDATOR: - default: RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.45f, 1.9f, 0.96f); RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.45f, 1.9f, 0.96f); RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.45f, -3.75f, 0.96f); RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.45f, -3.75f, 0.96f); break; + case MI_TROPIC: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.886f, -2.347f, 0.787f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.886f, -2.347f, 0.787f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.886f, -4.67f, 0.842f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.886f, -4.67f, 0.842f); + break; + case MI_COASTG: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -0.663f, 3.565f, 0.382f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 0.663f, 3.565f, 0.382f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.087f, 0.83f, 0.381f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.087f, 0.83f, 0.381f); + break; + case MI_DINGHY: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -0.797f, 1.641f, 0.573f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 0.797f, 1.641f, 0.573f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -0.865f, -1.444f, 0.509f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 0.865f, -1.444f, 0.509f); + break; + case MI_MARQUIS: + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.246f, -1.373f, 0.787f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.246f, -1.373f, 0.787f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.023f, -5.322f, 0.787f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.023f, -5.322f, 0.787f); + break; + default: + return; } KeepWaterOutVertices[0].u = 0.0f; KeepWaterOutVertices[0].v = 0.0f; @@ -806,6 +1176,28 @@ CBoat::Render() RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, KeepWaterOutIndices, 6); RwIm3DEnd(); } + bool drawAnotherRect = false; + if(GetModelIndex() == MI_COASTG){ + drawAnotherRect = true; + RwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.087f, 0.831f, 0.381f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[1], 1.087f, 0.831f, 0.381f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.097f, -2.977f, 0.381f); + RwIm3DVertexSetPos(&KeepWaterOutVertices[3], 1.097f, -2.977f, 0.381f); + } + if(drawAnotherRect){ + KeepWaterOutVertices[0].u = 0.0f; + KeepWaterOutVertices[0].v = 0.0f; + KeepWaterOutVertices[1].u = 1.0f; + KeepWaterOutVertices[1].v = 0.0f; + KeepWaterOutVertices[2].u = 0.0f; + KeepWaterOutVertices[2].v = 1.0f; + KeepWaterOutVertices[3].u = 1.0f; + KeepWaterOutVertices[3].v = 1.0f; + if (!CVehicle::bWheelsOnlyCheat && RwIm3DTransform(KeepWaterOutVertices, 4, GetMatrix().m_attachment, rwIM3D_VERTEXUV)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, KeepWaterOutIndices, 6); + RwIm3DEnd(); + } + } RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); @@ -822,6 +1214,7 @@ CBoat::Teleport(CVector v) CWorld::Add(this); } +//--MIAMI: unused bool CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats) { @@ -853,6 +1246,7 @@ CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats) return numVerts != 0; } +//--MIAMI: unused float CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat) { @@ -889,22 +1283,35 @@ CBoat::FillBoatList() apFrameWakeGeneratingBoats[1] = nil; apFrameWakeGeneratingBoats[2] = nil; apFrameWakeGeneratingBoats[3] = nil; - + CVector2D camPos = TheCamera.GetPosition(); + CVector2D camFwd = TheCamera.GetForward(); + float camDist = camFwd.Magnitude(); + if(camDist > 0.0f) + camFwd /= camDist; for (int i = CPools::GetVehiclePool()->GetSize() - 1; i >= 0; i--) { CBoat *boat = (CBoat *)(CPools::GetVehiclePool()->GetSlot(i)); if (boat && boat->m_vehType == VEHICLE_TYPE_BOAT) { - int16 nNumWakePoints = boat->m_nNumWakePoints; - if (nNumWakePoints != 0) { + if (boat->m_nNumWakePoints != 0) { + CVector2D camToBoat = CVector2D(boat->GetPosition()) - camPos; + float distToCam = DotProduct2D(camFwd, camToBoat); + if(distToCam > 100.0f || distToCam < -15.0f) + continue; + float distSq = camToBoat.MagnitudeSqr(); + if(distSq > SQR(70.0f)) + continue; if (frameId >= ARRAY_SIZE(apFrameWakeGeneratingBoats)) { + float nearest = 999999.88f; int16 frameId2 = -1; for (int16 j = 0; j < ARRAY_SIZE(apFrameWakeGeneratingBoats); j++) { - if (apFrameWakeGeneratingBoats[j]->m_nNumWakePoints < nNumWakePoints) { + float tmpDistSq = (CVector2D(apFrameWakeGeneratingBoats[j]->GetPosition()) - camPos).MagnitudeSqr(); + if (tmpDistSq < nearest) { + nearest = tmpDistSq; frameId2 = j; - nNumWakePoints = apFrameWakeGeneratingBoats[j]->m_nNumWakePoints; } } - if (frameId2 != -1) + if (frameId2 != -1 && + (distSq < nearest || boat->GetStatus() == STATUS_PLAYER)) apFrameWakeGeneratingBoats[frameId2] = boat; } else { apFrameWakeGeneratingBoats[frameId++] = boat; @@ -935,33 +1342,28 @@ void CBoat::AddWakePoint(CVector point) { int i; - if (m_afWakePointLifeTime[0] > 0.0f) { - if ((CVector2D(GetPosition()) - m_avec2dWakePoints[0]).MagnitudeSqr() < SQR(2.0f)) { - if (GetStatus() == STATUS_PHYSICS) { - if (VehicleCreatedBy == MISSION_VEHICLE) { - if (m_nNumWakePoints >= 20) - m_nNumWakePoints = 20; - } - else { - if (m_nNumWakePoints >= 15) - m_nNumWakePoints = 15; - } - } - else { - if (m_nNumWakePoints >= 31) + if(m_afWakePointLifeTime[0] > 0.0f){ + if((CVector2D(GetPosition()) - m_avec2dWakePoints[0]).MagnitudeSqr() < SQR(2.0f)) { + if(GetStatus() == STATUS_PLAYER){ + if(m_nNumWakePoints >= 31) m_nNumWakePoints = 31; + }else if(VehicleCreatedBy == MISSION_VEHICLE){ + if(m_nNumWakePoints >= 20) + m_nNumWakePoints = 20; + }else{ + if(m_nNumWakePoints >= 15) + m_nNumWakePoints = 15; } - for (i = m_nNumWakePoints; i != 0; i--) { - m_avec2dWakePoints[i] = m_avec2dWakePoints[i - 1]; - m_afWakePointLifeTime[i] = m_afWakePointLifeTime[i - 1]; + for(i = m_nNumWakePoints; i != 0; i--){ + m_avec2dWakePoints[i] = m_avec2dWakePoints[i-1]; + m_afWakePointLifeTime[i] = m_afWakePointLifeTime[i-1]; } m_avec2dWakePoints[0] = point; m_afWakePointLifeTime[0] = 150.0f; - if (m_nNumWakePoints < ARRAY_SIZE(m_afWakePointLifeTime)) + if(m_nNumWakePoints < ARRAY_SIZE(m_afWakePointLifeTime)) m_nNumWakePoints++; } - } - else { + }else{ m_avec2dWakePoints[0] = point; m_afWakePointLifeTime[0] = 150.0f; m_nNumWakePoints = 1; @@ -972,7 +1374,7 @@ void CBoat::DoDriveByShootings(void) { CAnimBlendAssociation *anim = nil; - CPlayerInfo* playerInfo = ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed(); + CPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed(); if (playerInfo && !playerInfo->m_bDriveByAllowed) return; @@ -984,7 +1386,8 @@ CBoat::DoDriveByShootings(void) bool lookingLeft = false; bool lookingRight = false; - if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN){ + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || + TheCamera.m_bObbeCinematicCarCamOn){ if(CPad::GetPad(0)->GetLookLeft()) lookingLeft = true; if(CPad::GetPad(0)->GetLookRight()) diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index c6f4b7ad..5f8cc8a8 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -1,6 +1,7 @@ #pragma once #include "Vehicle.h" +#include "Door.h" enum eBoatNodes { @@ -10,33 +11,34 @@ enum eBoatNodes BOAT_FLAP_LEFT, BOAT_FLAP_RIGHT, BOAT_REARFLAP_LEFT, - BOAT_REARFLAP_RIGHT + BOAT_REARFLAP_RIGHT, + NUM_BOAT_NODES }; class CBoat : public CVehicle { public: - // 0x288 - float m_fPropellerZ; - float m_fPropellerY; - CVector m_waterMoveDrag; - CVector m_waterTurnDrag; - float m_fMovingHiRotation; - int32 _unk0; - RwFrame *m_aBoatNodes[4]; + float m_fMovingRotation; + float m_fMovingSpeed; + int32 m_boat_unused1; + RwFrame *m_aBoatNodes[NUM_BOAT_NODES]; + CDoor m_boom; + tBoatHandlingData *pBoatHandling; uint8 bBoatInWater : 1; uint8 bPropellerInWater : 1; bool m_bIsAnchored; float m_fOrientation; - int32 _unk1; + uint32 m_nPoliceShoutTimer; + int32 m_boat_unused2; float m_fDamage; CEntity *m_pSetOnFireEntity; - bool _unk2; + float m_skimmerThingTimer; + bool m_boat_unused3; float m_fAccelerate; float m_fBrake; float m_fSteeringLeftRight; uint8 m_nPadID; - int32 _unk3; + int32 m_boat_unused4; float m_fVolumeUnderWater; CVector m_vecBuoyancePoint; float m_fPrevVolumeUnderWater; @@ -54,7 +56,7 @@ public: virtual void SetModelIndex(uint32 id); virtual void ProcessControl(); virtual void Teleport(CVector v); - virtual void PreRender(void) {}; + virtual void PreRender(void); virtual void Render(void); virtual void ProcessControlInputs(uint8); virtual void GetComponentWorldPosition(int32 component, CVector &pos); diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index 1ae1c5c3..92e3d80e 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -7,18 +7,40 @@ #include "Vehicle.h" #include "Floater.h" +//--MIAMI: done + cBuoyancy mod_Buoyancy; -static float fVolMultiplier = 1.0f; +float fVolMultiplier = 1.0f; // amount of boat volume in bounding box // 1.0-volume is the empty space in the bbox -static float fBoatVolumeDistribution[9] = { +float fBoatVolumeDistribution[9] = { // rear 0.75f, 0.9f, 0.75f, 0.95f, 1.0f, 0.95f, - 0.3f, 0.7f, 0.3f + 0.4f, 0.7f, 0.4f // bow }; +float fBoatVolumeDistributionCat[9] = { + 0.9f, 0.3f, 0.9f, + 1.0f, 0.5f, 1.0f, + 0.95f, 0.4f, 0.95f +}; +float fBoatVolumeDistributionSail[9] = { + 0.55f, 0.95f, 0.55f, + 0.75f, 1.1f, 0.75f, + 0.3f, 0.8f, 0.3f +}; +float fBoatVolumeDistributionDinghy[9] = { + 0.65f, 0.85f, 0.65f, + 0.85f, 1.1f, 0.85f, + 0.65f, 0.95f, 0.65f +}; +float fBoatVolumeDistributionSpeed[9] = { + 0.7f, 0.9f, 0.7f, + 0.95f, 1.0f, 0.95f, + 0.6f, 0.7f, 0.6f +}; bool cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVector *impulse) @@ -37,6 +59,76 @@ cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVec return f != 0.0f; } +bool +cBuoyancy::ProcessBuoyancyBoat(CVehicle *veh, float buoyancy, CVector *point, CVector *impulse, bool bNoTurnForce) +{ + m_numSteps = 2.0f; + + if(!CWaterLevel::GetWaterLevel(veh->GetPosition(), &m_waterlevel, veh->bTouchingWater)) + return false; + m_matrix = veh->GetMatrix(); + PreCalcSetup(veh, buoyancy); + + + float x, y; + int ix, i; + tWaterLevel waterPosition; + CVector waterNormal; + + // Floater is divided into 3x3 parts. Process and sum each of them + float volDiv = 1.0f/((m_dimMax.z - m_dimMin.z)*sq(m_numSteps+1.0f)); + ix = 0; + for(x = m_dimMin.x; x <= m_dimMax.x; x += m_step.x){ + i = ix; + for(y = m_dimMin.y; y <= m_dimMax.y; y += m_step.y){ + CVector waterLevel(x, y, 0.0f); + FindWaterLevelNorm(m_positionZ, &waterLevel, &waterPosition, &waterNormal); + switch(veh->GetModelIndex()){ + case MI_RIO: + fVolMultiplier = fBoatVolumeDistributionCat[i]; + break; + case MI_SQUALO: + case MI_SPEEDER: + case MI_JETMAX: + fVolMultiplier = fBoatVolumeDistributionSpeed[i]; + break; + case MI_COASTG: + case MI_DINGHY: + fVolMultiplier = fBoatVolumeDistributionDinghy[i]; + break; + case MI_MARQUIS: + fVolMultiplier = fBoatVolumeDistributionSail[i]; + break; + case MI_PREDATOR: + case MI_SKIMMER: + case MI_REEFER: + case MI_TROPIC: + default: + fVolMultiplier = fBoatVolumeDistribution[i]; + break; + } + if(waterPosition != FLOATER_ABOVE_WATER){ + float volume = SimpleSumBuoyancyData(waterLevel, waterPosition); + float upImpulse = volume * volDiv * buoyancy * CTimer::GetTimeStep(); + CVector speed = veh->GetSpeed(Multiply3x3(veh->GetMatrix(), CVector(x, y, 0.0f))); + float damp = 1.0f - DotProduct(speed, waterNormal)*veh->pHandling->fSuspensionDampingLevel; + float finalImpulse = upImpulse*Max(damp, 0.0f); + impulse->z += finalImpulse; + if(!bNoTurnForce) + veh->ApplyTurnForce(finalImpulse*waterNormal, Multiply3x3(m_matrix, waterLevel)); + } + i += 3; + } + ix++; + } + + m_volumeUnderWater *= volDiv; + + *point = Multiply3x3(m_matrix, m_impulsePoint); + return m_isBoat || m_haveVolume; + +} + void cBuoyancy::PreCalcSetup(CPhysical *phys, float buoyancy) { @@ -48,17 +140,55 @@ cBuoyancy::PreCalcSetup(CPhysical *phys, float buoyancy) m_dimMax = colModel->boundingBox.max; if(m_isBoat){ - if(phys->GetModelIndex() == MI_PREDATOR){ + switch(phys->GetModelIndex()){ + case MI_PREDATOR: + default: + m_dimMax.y *= 1.05f; + m_dimMin.y *= 0.9f; + break; + case MI_SPEEDER: + m_dimMax.y *= 1.25f; + m_dimMin.y *= 0.83f; + break; + case MI_REEFER: + m_dimMin.y *= 0.9f; + break; + case MI_RIO: m_dimMax.y *= 0.9f; m_dimMin.y *= 0.9f; - }else if(phys->GetModelIndex() == MI_SPEEDER){ + m_dimMax.z += 0.25f; + m_dimMin.z -= 0.2f; + break; + case MI_SQUALO: + m_dimMax.y *= 0.9f; + m_dimMin.y *= 0.9f; + break; + case MI_TROPIC: + m_dimMax.y *= 1.3f; + m_dimMin.y *= 0.82f; + m_dimMin.z -= 0.2f; + break; + case MI_SKIMMER: + m_dimMin.y = -m_dimMax.y; + m_dimMax.y *= 1.2f; + break; + case MI_COASTG: m_dimMax.y *= 1.1f; m_dimMin.y *= 0.9f; - }else if(phys->GetModelIndex() == MI_REEFER){ + m_dimMin.z -= 0.3f; + break; + case MI_DINGHY: + m_dimMax.y *= 1.3f; m_dimMin.y *= 0.9f; - }else{ - m_dimMax.y *= 0.9f; + m_dimMin.z -= 0.2f; + break; + case MI_MARQUIS: + m_dimMax.y *= 1.3f; m_dimMin.y *= 0.9f; + break; + case MI_JETMAX: + m_dimMin.y *= 0.9f; + break; } } @@ -92,22 +222,17 @@ void cBuoyancy::SimpleCalcBuoyancy(void) { float x, y; - int ix, i; tWaterLevel waterPosition; // Floater is divided into 3x3 parts. Process and sum each of them - ix = 0; for(x = m_dimMin.x; x <= m_dimMax.x; x += m_step.x){ - i = ix; for(y = m_dimMin.y; y <= m_dimMax.y; y += m_step.y){ CVector waterLevel(x, y, 0.0f); FindWaterLevel(m_positionZ, &waterLevel, &waterPosition); - fVolMultiplier = m_isBoat ? fBoatVolumeDistribution[i] : 1.0f; + fVolMultiplier = 1.0f; if(waterPosition != FLOATER_ABOVE_WATER) SimpleSumBuoyancyData(waterLevel, waterPosition); - i += 3; } - ix++; } m_volumeUnderWater /= (m_dimMax.z - m_dimMin.z)*sq(m_numSteps+1.0f); @@ -129,10 +254,6 @@ cBuoyancy::SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition) if(m_isBoat){ fThisVolume *= fVolMultiplier; - if(fThisVolume < 0.5f) - fThisVolume = 2.0f*sq(fThisVolume); - if(fThisVolume < 1.0f) - fThisVolume = sq(fThisVolume); fThisVolume = sq(fThisVolume); } @@ -173,6 +294,26 @@ cBuoyancy::FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel } } +// Same as above but also get normal +void +cBuoyancy::FindWaterLevelNorm(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition, CVector *normal) +{ + *waterPosition = FLOATER_IN_WATER; + CVector xWaterLevel = Multiply3x3(m_matrix, *waterLevel); + CWaterLevel::GetWaterLevel(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y, m_position.z, + &waterLevel->z, true); + waterLevel->z -= xWaterLevel.z + zpos.z; // make local + if(waterLevel->z >= m_dimMin.z) + *normal = CWaterLevel::GetWaterNormal(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y); + if(waterLevel->z > m_dimMax.z){ + waterLevel->z = m_dimMax.z; + *waterPosition = FLOATER_UNDER_WATER; + }else if(waterLevel->z < m_dimMin.z){ + waterLevel->z = m_dimMin.z; + *waterPosition = FLOATER_ABOVE_WATER; + } +} + bool cBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *point, CVector *impulse) { diff --git a/src/vehicles/Floater.h b/src/vehicles/Floater.h index 1cfb46fb..91ab70ae 100644 --- a/src/vehicles/Floater.h +++ b/src/vehicles/Floater.h @@ -36,10 +36,12 @@ public: CVector m_impulsePoint; bool ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVector *impulse); + bool ProcessBuoyancyBoat(CVehicle *phys, float buoyancy, CVector *point, CVector *impulse, bool bNoTurnForce); void PreCalcSetup(CPhysical *phys, float buoyancy); void SimpleCalcBuoyancy(void); float SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition); void FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition); + void FindWaterLevelNorm(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition, CVector *normal); bool CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point); }; extern cBuoyancy mod_Buoyancy; From c4cd210ae0a39fbfbc3f12b0379c210c40ea4750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 2 Jul 2020 16:01:42 +0300 Subject: [PATCH 15/85] Disable VC_PED_PORTS, better cancellable car enter, weapon and cops fixes --- src/control/Garages.cpp | 2 +- src/core/config.h | 2 +- src/peds/Ped.cpp | 52 ++++++++++++++++++++--------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index e37df8d4..f7d62368 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -390,7 +390,7 @@ void CGarage::Update() bTakeMoney = true; FindPlayerPed()->m_pWanted->Reset(); CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE); - FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; + FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false; #ifdef FIX_BUGS bool bChangedColour = false; #else diff --git a/src/core/config.h b/src/core/config.h index 839fbc34..b0aeaf4a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -263,7 +263,7 @@ enum Config { // Peds #define PED_SKIN // support for skinned geometry on peds #define ANIMATE_PED_COL_MODEL -#define VC_PED_PORTS // various ports from VC's CPed, mostly subtle +// #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle // #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER //#define PEDS_REPORT_CRIMES_ON_PHONE diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2f3931d3..1c95366d 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -570,9 +570,12 @@ CPed::AddWeaponModel(int id) if (id != -1) { #ifdef PED_SKIN - if(IsClumpSkinned(GetClump())) + if (IsClumpSkinned(GetClump())) { + if (m_pWeaponModel) + RemoveWeaponModel(-1); + m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); - else + } else #endif { atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); @@ -834,7 +837,7 @@ CPed::ClearAimFlag(void) bIsAimingGun = false; bIsRestoringGun = true; m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM; -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS m_lookTimer = 0; #endif } @@ -2243,11 +2246,6 @@ CPed::CalculateNewVelocity(void) CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE); CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); #ifdef VC_PED_PORTS - if(!fightAssoc) - fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED); - - // There is one more anim in VC. - if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) { #else if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) { @@ -2486,7 +2484,7 @@ CPed::RestorePreviousObjective(void) return; if (m_objective != OBJECTIVE_LEAVE_VEHICLE && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS && m_nPedState != PED_CARJACK #endif ) @@ -4208,7 +4206,7 @@ CPed::ClearObjective(void) if (m_nPedState == PED_DRIVING && m_pMyVehicle) { if (m_pMyVehicle->pDriver != this) { -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS if(!IsPlayer()) #endif bWanderPathAfterExitingCar = true; @@ -5850,7 +5848,7 @@ CPed::SetChat(CEntity *chatWith, uint32 time) m_nPedState = PED_CHAT; SetMoveState(PEDMOVE_STILL); -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS m_lookTimer = 0; #endif SetLookFlag(chatWith, true); @@ -10225,19 +10223,22 @@ CPed::ProcessControl(void) int vehAnim = m_pVehicleAnim->animId; + static bool cancelQuickJack = false; int16 padWalkX = pad->GetPedWalkLeftRight(); int16 padWalkY = pad->GetPedWalkUpDown(); if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { bCancelEnteringCar = true; - } else if (vehAnim == ANIM_CAR_QJACK) { - if (m_pVehicleAnim->GetTimeLeft() > 0.69f && m_pVehicleAnim->GetTimeLeft() < 0.72f) { - QuitEnteringCar(); - RestorePreviousObjective(); - } + } else if (vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) { + cancelQuickJack = true; } } + if (cancelQuickJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { + cancelQuickJack = false; + QuitEnteringCar(); + RestorePreviousObjective(); + } #endif break; } @@ -10580,7 +10581,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) { if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS || ped->m_nPedState == PED_CARJACK #endif ) @@ -10827,7 +10828,7 @@ void CPed::SetJump(void) { if (!bInVehicle && -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) && #endif (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) { @@ -11457,7 +11458,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) } } if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS || ped->m_nPedState == PED_CARJACK #endif ) @@ -11471,7 +11472,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) if (veh->IsBoat()) { if (ped->IsPlayer()) { -#if defined(FIX_BUGS) || defined(VC_PED_PORTS) +#if defined VC_PED_PORTS || defined FIX_BUGS CCarCtrl::RegisterVehicleOfInterest(veh); #endif if (veh->GetStatus() == STATUS_SIMPLE) { @@ -11526,7 +11527,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) } } // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below. -#ifndef VC_PED_PORTS +#if !defined VC_PED_PORTS && !defined FIX_BUGS else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) { if (ped->m_nPedState == PED_CARJACK) { veh->AddPassenger(ped, 0); @@ -12042,7 +12043,7 @@ CPed::ReplaceWeaponWhenExitingVehicle(void) // If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car. if (IsPlayer() && weaponType == WEAPONTYPE_UZI) { - if (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { + if (/*IsPlayer() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) { SetCurrentWeapon(m_storedWeapon); m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; } @@ -13799,7 +13800,7 @@ void CPed::SetSeekBoatPosition(CVehicle *boat) { if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver -#ifdef VC_PED_PORTS +#if defined VC_PED_PORTS || defined FIX_BUGS || !IsPedInControl() #endif ) @@ -14566,8 +14567,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) m_vecDamageNormal = intersectionPoint.normal; } } - // VC code is working perfectly, but we don't want mega jumps to damage us significantly :shrug: -#if 0 // #ifdef VC_PED_PORTS +#ifdef VC_PED_PORTS float upperSpeedLimit = 0.33f; float lowerSpeedLimit = -0.25f; float speed = m_vecMoveSpeed.Magnitude2D(); @@ -14575,7 +14575,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) upperSpeedLimit *= 2.0f; lowerSpeedLimit *= 1.5f; } - if (!m_ped_flagA2) { + if (!bWasStanding) { if ((speed <= upperSpeedLimit /* || (bfFlagsL >> 5) & 1 */) && m_vecMoveSpeed.z >= lowerSpeedLimit || m_pCollidingEntity == collidingEnt) { From bf2624692c6b04c25275ddb35b7da1cf1e6a9953 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Fri, 3 Jul 2020 00:04:49 +0200 Subject: [PATCH 16/85] Fix displaying stats --- src/core/Stats.cpp | 4 ++-- src/core/Stats.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 99274e04..9afd8ac3 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -16,8 +16,8 @@ int32 CStats::PedsKilledOfThisType[NUM_PEDTYPES]; int32 CStats::TimesDied; int32 CStats::TimesArrested; int32 CStats::KillsSinceLastCheckpoint; -int32 CStats::DistanceTravelledInVehicle; -int32 CStats::DistanceTravelledOnFoot; +float CStats::DistanceTravelledInVehicle; +float CStats::DistanceTravelledOnFoot; int32 CStats::ProgressMade; int32 CStats::TotalProgressInGame; int32 CStats::CarsExploded; diff --git a/src/core/Stats.h b/src/core/Stats.h index ae3c0cb4..5dfcf803 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -21,8 +21,8 @@ public: static int32 TimesDied; static int32 TimesArrested; static int32 KillsSinceLastCheckpoint; - static int32 DistanceTravelledInVehicle; - static int32 DistanceTravelledOnFoot; + static float DistanceTravelledInVehicle; + static float DistanceTravelledOnFoot; static int32 CarsExploded; static int32 PeopleKilledByPlayer; static int32 ProgressMade; From 01b15fe8071a4c18404c76b9063946548c480a11 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 3 Jul 2020 01:28:41 +0300 Subject: [PATCH 17/85] reenabled script logging --- src/core/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config.h b/src/core/config.h index b0aeaf4a..9d9577ff 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -241,7 +241,7 @@ enum Config { # define MISSION_REPLAY // mobile feature #endif //#define SIMPLIER_MISSIONS // apply simplifications from mobile -//#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT +#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log #ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT From ed036df3ce0253fe639a441c22a58ecc0f9a116a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 3 Jul 2020 05:40:22 +0300 Subject: [PATCH 18/85] Re-enable console for debugging frontend --- src/core/Frontend.cpp | 6 +++--- src/skel/glfw/glfw.cpp | 6 ++++++ src/skel/win/win.cpp | 3 +-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 3400d10f..bd03500e 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1218,7 +1218,7 @@ CMenuManager::Draw() } } } else { - debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); + debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options is borked"); } @@ -4778,7 +4778,7 @@ CMenuManager::ProcessButtonPresses(void) goBack = true; } } else { - debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options are borked"); } @@ -5003,7 +5003,7 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); } else { - debug("screen:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); assert(0 && "Custom frontend options are borked"); } diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 0728f6c2..5e0c178c 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1366,6 +1366,12 @@ WinMain(HINSTANCE instance, RwInt32 argc; RwChar** argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); + + // TODO: make this an option somewhere + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); #else int main(int argc, char *argv[]) diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 484c6fe8..e1fb5b7f 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1929,13 +1929,12 @@ WinMain(HINSTANCE instance, StaticPatcher::Apply(); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); -/* + // TODO: make this an option somewhere AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); -*/ /* * Initialize the platform independent data. From 48ebbb72924bf5afbf7518bd1534521e1aa43bcc Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 3 Jul 2020 11:08:19 +0300 Subject: [PATCH 19/85] ice cream attractor + bike respray --- src/control/Garages.cpp | 4 +-- src/control/Script.cpp | 65 ++++++++++++++++++++++++++++++++++----- src/peds/Ped.cpp | 49 +++++++++++++++++++++++++---- src/peds/PedAttractor.cpp | 12 ++++---- 4 files changed, 109 insertions(+), 21 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 88654141..7175d393 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -347,7 +347,7 @@ void CGarage::Update() FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; } else { - CGarages::TriggerMessage("GA_3", -1, 4000, -1); // No more freebies. $1000 to respray! + CGarages::TriggerMessage("GA_3", -1, 4000, -1); // No more freebies. $100 to respray! m_eGarageState = GS_OPENEDCONTAINSCAR; DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1); } @@ -1096,7 +1096,7 @@ bool CGarage::IsStaticPlayerCarEntirelyInside() { if (!FindPlayerVehicle()) return false; - if (!FindPlayerVehicle()->IsCar()) + if (!FindPlayerVehicle()->IsCar() && !FindPlayerVehicle()->IsBike()) return false; if (FindPlayerPed()->GetPedState() != PED_DRIVING) return false; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 46f9c722..d16fcfd2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1636,7 +1636,8 @@ static void PrintToLog(const char* format, ...) va_end(va); #if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2 - fwrite(tmp, 1, strlen(tmp), dbg_log); + if (dbg_log) + fwrite(tmp, 1, strlen(tmp), dbg_log); #endif } @@ -13605,10 +13606,14 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) ScriptParams[0] = 0; if (pPed->m_objective == OBJECTIVE_NONE && !pPed->bHasAlreadyUsedAttractor) { C2dEffect* pEffect = (C2dEffect*)GetPedAttractorManager()->GetEffectForIceCreamVan(pVehicle, pPed->GetPosition()); // has to be casted, because inner methods are const - if ((pPed->GetPosition() - pEffect->pos).MagnitudeSqr() < SQR(20.0f)) { - if (GetPedAttractorManager()->HasEmptySlot(pEffect) && GetPedAttractorManager()->IsApproachable(pEffect, pVehicle->GetMatrix(), 0, pPed)) { - if (GetPedAttractorManager()->RegisterPedWithAttractor(pPed, pEffect, pVehicle->GetMatrix())) - ScriptParams[0] = 1; + if (pEffect) { + CVector pos; + CPedAttractorManager::ComputeEffectPos(pEffect, pVehicle->GetMatrix(), pos); + if ((pPed->GetPosition() - pos).MagnitudeSqr() < SQR(20.0f)) { + if (GetPedAttractorManager()->HasEmptySlot(pEffect) && GetPedAttractorManager()->IsApproachable(pEffect, pVehicle->GetMatrix(), 0, pPed)) { + if (GetPedAttractorManager()->RegisterPedWithAttractor(pPed, pEffect, pVehicle->GetMatrix())) + ScriptParams[0] = 1; + } } } } @@ -13735,11 +13740,57 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; } case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA: + { CollectParameters(&m_nIp, 7); - debug("GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA not implemented\n"); // TODO(MIAMI) - ScriptParams[0] = -1; + int ped_handle = -1; + CVector pos = FindPlayerCoors(); + float x1 = *(float*)&ScriptParams[0]; + float y1 = *(float*)&ScriptParams[1]; + float x2 = *(float*)&ScriptParams[2]; + float y2 = *(float*)&ScriptParams[3]; + int i = CPools::GetPedPool()->GetSize(); + while (--i && ped_handle == -1) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (!pPed) + continue; + if (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed)) + continue; + if (pPed->CharCreatedBy != RANDOM_CHAR) + continue; + if (!pPed->IsPedInControl()) + continue; + if (pPed->bRemoveFromWorld) + continue; + if (pPed->bFadeOut) + continue; + if (pPed->m_nWaitState != WAITSTATE_FALSE) + continue; + if (pPed->bHasAlreadyUsedAttractor) + continue; + if (pPed->m_attractor) + continue; + if (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[4], ScriptParams[5], ScriptParams[6])) + continue; + if (pPed->bIsLeader || pPed->m_leader) + continue; + if (!pPed->IsWithinArea(x1, y1, x2, y2)) + continue; + if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) + continue; + if (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z) + continue; + ped_handle = CPools::GetPedPool()->GetIndex(pPed); + CTheScripts::LastRandomPedId = ped_handle; + pPed->CharCreatedBy = MISSION_CHAR; + pPed->bRespondsToThreats = false; + ++CPopulation::ms_nTotalMissionPeds; + if (m_bIsMissionScript) + CTheScripts::MissionCleanup.AddEntityToList(ped_handle, CLEANUP_CHAR); + } + ScriptParams[0] = ped_handle; StoreParameters(&m_nIp, 1); return 0; + } //case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE: case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA: CollectParameters(&m_nIp, 4); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2fe2ce02..bfaf6ea4 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -405,6 +405,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bReachedAttractorHeadingTarget = false; bTurnedAroundOnAttractor = false; + bHasAlreadyUsedAttractor = false; bCarPassenger = false; bMiamiViceCop = false; bMoneyHasBeenGivenByScript = false; @@ -8170,6 +8171,10 @@ CPed::Wait(void) animAssoc->blendDelta = -4.0f; animAssoc->flags |= ASSOC_DELETEFADEDOUT; } + if (m_attractor && m_objective == OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN) { + GetPedAttractorManager()->BroadcastDeparture(this, m_attractor); + bBoughtIceCream = true; + } ClearWaitState(); } #ifdef VC_PED_PORTS @@ -15111,6 +15116,38 @@ CPed::ProcessObjective(void) } } break; + case OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN: + { + SetIdle(); + CVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect()); + if (m_attractor && m_nWaitState != WAITSTATE_PLAYANIM_CHAT && pIceCreamVan && pIceCreamVan->pDriver && pIceCreamVan->pDriver->IsPlayer()) { + int time = 5000; + SetWaitState(WAITSTATE_PLAYANIM_CHAT, &time); + break; + } + if (!m_attractor) + break; + CVehicle* pVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect()); + if (!pVan) + break; + if (0.01f * CTimer::GetTimeStep() * 5.0f < pVan->m_fDistanceTravelled) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + break; + } + if (!pVan->pDriver || !pVan->pDriver->IsPlayer() || pVan->pDriver->GetPedState() == PED_ARRESTED || pVan->pDriver->GetPedState() == PED_DEAD) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + break; + } + if (!pVan->m_bSirenOrAlarm) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; // ??? + } + if (pVan->GetStatus() == STATUS_WRECKED) { + GetPedAttractorManager()->DeRegisterPed(this, m_attractor); + return; // ??? + } + break; + } #endif } if (bObjectiveCompleted @@ -18761,28 +18798,28 @@ CPed::SetObjective(eObjective newObj, CVector dest) m_nextRoutePointPos = dest; m_vecSeekPos = m_nextRoutePointPos; m_distanceToCountSeekDone = 0.5f; - if (m_objective == OBJECTIVE_GOTO_ATM_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_ATM_ON_FOOT) { m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); } - if (m_objective == OBJECTIVE_GOTO_SEAT_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_SEAT_ON_FOOT) { m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); } - if (m_objective == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT) { m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); } - if (m_objective == OBJECTIVE_GOTO_PIZZA_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_PIZZA_ON_FOOT) { m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); } - if (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_SHELTER_ON_FOOT) { bIsRunning = true; m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); } - if (m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) { + if (newObj == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) { bIsRunning = true; m_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone(); m_acceptableHeadingOffset = m_attractor->GetAcceptableHeading(); diff --git a/src/peds/PedAttractor.cpp b/src/peds/PedAttractor.cpp index 659a522b..db5f9e52 100644 --- a/src/peds/PedAttractor.cpp +++ b/src/peds/PedAttractor.cpp @@ -70,17 +70,17 @@ const C2dEffect* CVehicleToEffect::ChooseEffect(const CVector& pos) const if (!m_pVehicle) return nil; if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetRight()) > 0.0f) { - if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f) - return &m_effects[0]; - else - return &m_effects[2]; - } - else { if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f) return &m_effects[1]; else return &m_effects[3]; } + else { + if (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f) + return &m_effects[0]; + else + return &m_effects[2]; + } } bool CVehicleToEffect::HasThisEffect(C2dEffect* pEffect) const From 85e899c1a5a925734c456d86cbe2fdd9c0c07538 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 3 Jul 2020 15:15:42 +0300 Subject: [PATCH 20/85] fixed typo --- src/control/Script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 9b3dc1be..e8075e2b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -348,8 +348,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CAR_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_DRIVING_STYLE, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_MISSION, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_0, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_1, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_2, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), From 9bb8b39956033d197ba7dd721fec5964e8784a0a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 3 Jul 2020 15:17:02 +0300 Subject: [PATCH 21/85] fixed typo --- src/control/Script.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 46f9c722..0663814d 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -352,8 +352,8 @@ const tScriptCommandData commands[] = { REGISTER_COMMAND(COMMAND_SET_CAR_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_DRIVING_STYLE, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SET_CAR_MISSION, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), - REGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), + REGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_0, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_1, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), REGISTER_COMMAND(COMMAND_SPECIAL_2, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, ""), @@ -16180,4 +16180,4 @@ CTheScripts::SwitchToMission(int32 mission) CTheScripts::bAlreadyRunningAMissionScript = true; CGameLogic::ClearShortCut(); } -#endif \ No newline at end of file +#endif From 49a8dd74594af6ec216f7c2d1703289649c465dc Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 3 Jul 2020 15:21:11 +0300 Subject: [PATCH 22/85] fixed typo --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 0663814d..fb8f95fd 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -12129,7 +12129,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CollectParameters(&m_nIp, 1); CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); - UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE); + UpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT); return 0; } case COMMAND_IS_CHAR_IN_ANY_HELI: From 15548758ac825e61648fd6adc2fba96256875fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 3 Jul 2020 16:51:33 +0300 Subject: [PATCH 23/85] Bettah car enter canceling, fix CFO crash, ped objs. renaming --- src/control/CarAI.cpp | 4 +- src/control/Garages.cpp | 2 +- src/control/Phones.cpp | 2 +- src/control/SceneEdit.cpp | 8 +- src/control/Script.cpp | 14 +-- src/core/Cam.cpp | 2 +- src/core/Frontend.cpp | 1 - src/core/PlayerInfo.cpp | 2 +- src/core/re3.cpp | 3 +- src/extras/frontendoption.cpp | 5 +- src/peds/CivilianPed.cpp | 10 +- src/peds/EmergencyPed.cpp | 4 +- src/peds/Ped.cpp | 185 +++++++++++++++++++--------------- src/peds/Ped.h | 24 ++--- src/peds/PlayerPed.cpp | 2 +- src/vehicles/Automobile.cpp | 4 +- src/vehicles/Vehicle.cpp | 4 +- 17 files changed, 150 insertions(+), 126 deletions(-) diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 41dcaa59..ab44510d 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -509,14 +509,14 @@ void CCarAI::AddFiretruckOccupants(CVehicle* pVehicle) void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle) { if (pVehicle->pDriver){ - pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); if (pVehicle->GetModelIndex() == MI_AMBULAN) pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE); } int timer = 100; for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){ if (pVehicle->pPassengers[i]) { - pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); } } } diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index f7d62368..2b7c31c8 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1175,7 +1175,7 @@ bool CGarage::IsStaticPlayerCarEntirelyInside() return false; if (FindPlayerPed()->GetPedState() != PED_DRIVING) return false; - if (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_VEHICLE) + if (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_CAR) return false; CVehicle* pVehicle = FindPlayerVehicle(); if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 || diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 14e9dc45..ad29d4fb 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -39,7 +39,7 @@ CPed* crimeReporters[NUMPHONES] = {}; bool isPhoneAvailable(int m_phoneId) { - return crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_IDLE || + return crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_WAIT_ON_FOOT || crimeReporters[m_phoneId]->m_nLastPedState != PED_SEEK_POS && (crimeReporters[m_phoneId]->m_nPedState != PED_MAKE_CALL && crimeReporters[m_phoneId]->m_nPedState != PED_FACE_PHONE && crimeReporters[m_phoneId]->m_nPedState != PED_SEEK_POS); } diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index be8c5519..154fe603 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -631,7 +631,7 @@ void CSceneEdit::ProcessCommand(void) SelectActor(); if (m_bActorSelected) { if (pActors[m_nActor]->bInVehicle) { - pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_VEHICLE); + pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_CAR); Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_GET_OUT_CAR; Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; } @@ -695,7 +695,7 @@ void CSceneEdit::ProcessCommand(void) case MOVIE_WAIT: SelectActor(); if (m_bActorSelected) { - pActors[m_nActor]->SetObjective(OBJECTIVE_IDLE); + pActors[m_nActor]->SetObjective(OBJECTIVE_WAIT_ON_FOOT); Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_WAIT; Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; } @@ -876,7 +876,7 @@ void CSceneEdit::PlayBack(void) case MOVIE_GET_OUT_CAR: m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; if (pActors[m_nActor]->bInVehicle) - pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_VEHICLE); + pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_CAR); else ++m_nCurrentMovieCommand; break; @@ -895,7 +895,7 @@ void CSceneEdit::PlayBack(void) break; case MOVIE_WAIT: m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; - pActors[m_nActor]->SetObjective(OBJECTIVE_IDLE); + pActors[m_nActor]->SetObjective(OBJECTIVE_WAIT_ON_FOOT); ++m_nCurrentMovieCommand; break; case MOVIE_POSITION_CAMERA: diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 9b3dc1be..8d5cc128 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3326,7 +3326,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); script_assert(ped); ped->bScriptObjectiveCompleted = false; - ped->SetObjective(OBJECTIVE_IDLE); + ped->SetObjective(OBJECTIVE_WAIT_ON_FOOT); return 0; } case COMMAND_GET_CHAR_COORDINATES: @@ -5128,7 +5128,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); script_assert(pPed); pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_IDLE); + pPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT); return 0; } case COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE: @@ -5620,7 +5620,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) script_assert(pPed); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]); pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); return 0; } case COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER: @@ -7823,7 +7823,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) script_assert(pPed); CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); pPed->bScriptObjectiveCompleted = false; - pPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, pTargetPed); + pPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed); pPed->SetFormation((eFormation)ScriptParams[2]); return 0; } @@ -10870,13 +10870,13 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) script_assert(pVehicle); if (pVehicle->pDriver) { pVehicle->pDriver->bScriptObjectiveCompleted = false; - pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); } for (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) { if (pVehicle->pPassengers[i]) { pVehicle->pPassengers[i]->bScriptObjectiveCompleted = false; - pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle); } } return 0; @@ -13100,7 +13100,7 @@ void CTheScripts::CleanUpThisPed(CPed* pPed) } else { if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { - pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pPed->m_pMyVehicle); + pPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle); pPed->bWanderPathAfterExitingCar = true; } } diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 3e5a82a9..fcffce9b 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -5060,7 +5060,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, // This is not working on cars as SA // Because III/VC doesn't have any buttons tied to LeftStick if you're not in Classic Configuration, using Dodo or using GInput/Pad, so :shrug: if (Abs(pad->GetSteeringUpDown()) > 120.0f) { - if (car->pDriver && car->pDriver->m_objective != OBJECTIVE_LEAVE_VEHICLE) { + if (car->pDriver && car->pDriver->m_objective != OBJECTIVE_LEAVE_CAR) { yMovement += Abs(pad->GetSteeringUpDown()) * (FOV / 80.0f * 3.f / 70.f) * pad->GetSteeringUpDown() * 0.007f * 0.007f * 0.5; } } diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index bd03500e..841f6bbb 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -3068,7 +3068,6 @@ CMenuManager::InitialiseChangedLanguageSettings() } #ifdef CUSTOM_FRONTEND_OPTIONS - RemoveCustomFrontendOptions(); CustomFrontendOptionsPopulate(); #endif } diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 128b22b4..69c1fe49 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -409,7 +409,7 @@ CPlayerInfo::Process(void) if (veh->m_vehType != VEHICLE_TYPE_BIKE || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) { if (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) { if (veh->m_vecMoveSpeed.Magnitude() < 0.17f && CTimer::GetTimeScale() >= 0.5f && !veh->bIsInWater) { - m_pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + m_pPed->SetObjective(OBJECTIVE_LEAVE_CAR, veh); } } } else { diff --git a/src/core/re3.cpp b/src/core/re3.cpp index a2edcdee..7aa6800e 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -75,7 +75,6 @@ mysrand(unsigned int seed) void ReloadFrontendOptions(void) { - RemoveCustomFrontendOptions(); CustomFrontendOptionsPopulate(); } @@ -137,6 +136,8 @@ void ToggleFreeCam(int8 action) void CustomFrontendOptionsPopulate(void) { + RemoveCustomFrontendOptions(); // if exist + #ifdef MORE_LANGUAGES FrontendOptionSetPosition(MENUPAGE_LANGUAGE_SETTINGS); FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, LangPolSelect, nil); diff --git a/src/extras/frontendoption.cpp b/src/extras/frontendoption.cpp index bfeca848..51814f35 100644 --- a/src/extras/frontendoption.cpp +++ b/src/extras/frontendoption.cpp @@ -43,10 +43,13 @@ GetNumberOfMenuOptions(int screen) return Rows; } -// Used before reloading in InitialiseChangedLanguageSettings and debugmenu +// Used before populating options, but effective in InitialiseChangedLanguageSettings and debugmenu void RemoveCustomFrontendOptions() { + if (numCustomFrontendOptions == 0) + return; + for (int i = 0; i < MENUPAGES; i++) { for (int j = 0; j < NUM_MENUROWS; j++) { if (aScreens[i].m_aEntries[j].m_Action == MENUACTION_TRIGGERFUNC) { diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index b1b6ca82..7c569257 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -263,7 +263,7 @@ CCivilianPed::ProcessControl(void) if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) { m_pNextPathNode = nil; #ifdef PEDS_REPORT_CRIMES_ON_PHONE - } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) { + } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE) { if (!isPhoneAvailable(m_phoneId)) { RestorePreviousState(); if (crimeReporters[m_phoneId] == this) @@ -287,7 +287,7 @@ CCivilianPed::ProcessControl(void) } #endif } else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { - if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION) { + if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { if (m_moved.Magnitude() == 0.0f) { if (m_pedInObjective->m_nMoveState == PEDMOVE_STILL) m_fRotationDest = m_pedInObjective->m_fRotationCur; @@ -377,13 +377,13 @@ CCivilianPed::ProcessControl(void) } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; m_pMyVehicle->pDriver->m_fHealth = 125.0f; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } else { CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; @@ -396,7 +396,7 @@ CCivilianPed::ProcessControl(void) } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index cdaee657..083941b8 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -188,12 +188,12 @@ CEmergencyPed::MedicAI(void) } if (InVehicle()) { - if (m_pMyVehicle->IsCar() && m_objective != OBJECTIVE_LEAVE_VEHICLE) { + if (m_pMyVehicle->IsCar() && m_objective != OBJECTIVE_LEAVE_CAR) { if (gAccidentManager.FindNearestAccident(m_pMyVehicle->GetPosition(), &distToEmergency) && distToEmergency < 25.0f && m_pMyVehicle->m_vecMoveSpeed.Magnitude() < 0.01f) { m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); Say(SOUND_PED_LEAVE_VEHICLE); } else if (m_pMyVehicle->pDriver == this && m_nPedState == PED_DRIVING && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE && !(CGeneral::GetRandomNumber() & 31)) { diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1c95366d..67fe7788 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2403,7 +2403,7 @@ CPed::CanSeeEntity(CEntity *entity, float threshold = CAN_SEE_ENTITY_ANGLE_THRES bool CPed::IsTemporaryObjective(eObjective objective) { - return objective == OBJECTIVE_LEAVE_VEHICLE || objective == OBJECTIVE_SET_LEADER || + return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER || #ifdef VC_PED_PORTS objective == OBJECTIVE_LEAVE_CAR_AND_DIE || #endif @@ -2436,7 +2436,7 @@ CPed::ForceStoredObjective(eObjective objective) switch (m_objective) { - case OBJECTIVE_FLEE_TILL_SAFE: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: @@ -2459,14 +2459,14 @@ CPed::SetStoredObjective(void) switch (m_objective) { - case OBJECTIVE_FLEE_TILL_SAFE: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_PED_IN_FORMATION: - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + case OBJECTIVE_LEAVE_CAR: case OBJECTIVE_ENTER_CAR_AS_PASSENGER: case OBJECTIVE_ENTER_CAR_AS_DRIVER: case OBJECTIVE_GOTO_AREA_ON_FOOT: @@ -2483,17 +2483,17 @@ CPed::RestorePreviousObjective(void) if (m_objective == OBJECTIVE_NONE) return; - if (m_objective != OBJECTIVE_LEAVE_VEHICLE && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER + if (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER #if defined VC_PED_PORTS || defined FIX_BUGS && m_nPedState != PED_CARJACK #endif ) m_pedInObjective = nil; - if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT) { + if (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { m_objective = OBJECTIVE_NONE; if (m_pMyVehicle) - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } else { m_objective = m_prevObjective; @@ -2532,14 +2532,14 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_PED_IN_FORMATION: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: case OBJECTIVE_GOTO_AREA_ANY_MEANS: - case OBJECTIVE_FIGHT_CHAR: + case OBJECTIVE_GUARD_ATTACK: if (m_pedInObjective == entity) return; break; - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_LEAVE_CAR: case OBJECTIVE_FLEE_CAR: #ifdef VC_PED_PORTS case OBJECTIVE_LEAVE_CAR_AND_DIE: @@ -2548,7 +2548,7 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_ENTER_CAR_AS_PASSENGER: case OBJECTIVE_ENTER_CAR_AS_DRIVER: case OBJECTIVE_DESTROY_CAR: - case OBJECTIVE_SOLICIT: + case OBJECTIVE_SOLICIT_VEHICLE: case OBJECTIVE_BUY_ICE_CREAM: if (m_carInObjective == entity) return; @@ -2563,7 +2563,7 @@ CPed::SetObjective(eObjective newObj, void *entity) break; } } else { - if ((newObj == OBJECTIVE_LEAVE_VEHICLE + if ((newObj == OBJECTIVE_LEAVE_CAR #ifdef VC_PED_PORTS || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE #endif @@ -2588,7 +2588,7 @@ CPed::SetObjective(eObjective newObj, void *entity) } switch (newObj) { - case OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT: + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: // In this special case, entity parameter isn't CEntity, but int. SetObjectiveTimer((uintptr)entity); @@ -2607,17 +2607,17 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FIGHT_CHAR: + case OBJECTIVE_GUARD_ATTACK: m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); break; - case OBJECTIVE_FOLLOW_PED_IN_FORMATION: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); m_pedFormation = FORMATION_REAR; break; - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_LEAVE_CAR: #ifdef VC_PED_PORTS case OBJECTIVE_LEAVE_CAR_AND_DIE: #endif @@ -2646,14 +2646,14 @@ CPed::SetObjective(eObjective newObj, void *entity) } // fall through case OBJECTIVE_DESTROY_CAR: - case OBJECTIVE_SOLICIT: + case OBJECTIVE_SOLICIT_VEHICLE: case OBJECTIVE_BUY_ICE_CREAM: m_carInObjective = (CVehicle*)entity; m_carInObjective->RegisterReference((CEntity**)&m_carInObjective); m_pSeekTarget = m_carInObjective; m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); - if (newObj == OBJECTIVE_SOLICIT) { + if (newObj == OBJECTIVE_SOLICIT_VEHICLE) { m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR && (m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) { @@ -2696,7 +2696,7 @@ CPed::SetObjective(eObjective newObj) return; if (newObj == OBJECTIVE_NONE) { - if ((m_objective == OBJECTIVE_LEAVE_VEHICLE || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER + if ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER #ifdef VC_PED_PORTS || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) && !IsPlayer() @@ -4211,7 +4211,7 @@ CPed::ClearObjective(void) #endif bWanderPathAfterExitingCar = true; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } #ifdef VC_PED_PORTS m_nLastPedState = PED_NONE; @@ -5475,12 +5475,12 @@ CPed::CollideWithPed(CPed *collideWith) if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f) && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT #ifdef VC_PED_PORTS - || m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_pedInObjective == collideWith - || collideWith->m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && collideWith->m_pedInObjective == this + || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith + || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this #endif )) { - if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { + if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { @@ -7251,7 +7251,7 @@ CPed::Seek(void) if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT && - m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT && !bDuckAndCover) { + m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) { if ((!m_pedInObjective || !m_pedInObjective->bInVehicle) && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) { @@ -7279,14 +7279,14 @@ CPed::Seek(void) float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D(); if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) { - if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION) { + if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) nextMove = m_pedInObjective->m_nMoveState; } else nextMove = PEDMOVE_WALK; - } else if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION) { + } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning) nextMove = PEDMOVE_RUN; @@ -7376,7 +7376,7 @@ CPed::Seek(void) return false; } - if ((m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { + if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { m_nPedStateTimer = 0; m_actionX = 0; m_actionY = 0; @@ -10073,7 +10073,7 @@ CPed::ProcessControl(void) bStartWanderPathOnFoot = false; } else if (m_nPedState == PED_DRIVING) { bWanderPathAfterExitingCar = true; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } @@ -10223,22 +10223,34 @@ CPed::ProcessControl(void) int vehAnim = m_pVehicleAnim->animId; - static bool cancelQuickJack = false; + static bool cancelJack = false; int16 padWalkX = pad->GetPedWalkLeftRight(); int16 padWalkY = pad->GetPedWalkUpDown(); if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { - bCancelEnteringCar = true; + + if (!m_pMyVehicle->pDriver) { + cancelJack = false; + bCancelEnteringCar = true; + } else + cancelJack = true; } else if (vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) { - cancelQuickJack = true; + cancelJack = true; + } else if (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS) { + bCancelEnteringCar = true; + cancelJack = false; } } - if (cancelQuickJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { - cancelQuickJack = false; + if (cancelJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { + cancelJack = false; QuitEnteringCar(); RestorePreviousObjective(); } + if (cancelJack && (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS)) { + cancelJack = false; + bCancelEnteringCar = true; + } #endif break; } @@ -10574,7 +10586,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) } else if (ped->m_vehEnterType == CAR_DOOR_RF && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF || (veh->pDriver != nil && - (veh->pDriver->m_objective != OBJECTIVE_LEAVE_VEHICLE + (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR #ifdef VC_PED_PORTS && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE #endif @@ -10590,7 +10602,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; PedSetInCarCB(nil, ped); - ped->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); if (!ped->IsPlayer()) ped->bFleeAfterExitingCar = true; @@ -10958,7 +10970,7 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) CPed *driver = veh->pDriver; if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { if (veh->bIsBus) { - driver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); if (driver->IsPlayer()) { veh->bIsHandbrakeOn = true; veh->SetStatus(STATUS_PLAYER_DISABLED); @@ -10969,7 +10981,7 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) if (ped->m_nPedType == PEDTYPE_COP || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) { - ped->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); } ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400; return; @@ -10993,7 +11005,7 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) } if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY) && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) { - veh->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh); veh->pDriver->Say(SOUND_PED_CAR_JACKED); #ifdef VC_PED_PORTS veh->pDriver->SetRadioStation(); @@ -11046,6 +11058,15 @@ CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) if (!ped->IsNotInWreckedVehicle()) return; +#ifdef CANCELLABLE_CAR_ENTER + if (ped->bCancelEnteringCar) { + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + ped->bCancelEnteringCar = false; + return; + } +#endif + bool isLow = !!veh->bLowVehicle; int padNo; @@ -11418,7 +11439,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) #ifdef VC_PED_PORTS // Situation of entering car as a driver while there is already a driver exiting atm. CPed *driver = veh->pDriver; - if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_VEHICLE + if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) { if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) { @@ -11519,7 +11540,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) { CPed *passenger = veh->pPassengers[i]; if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) { - passenger->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh); #ifdef VC_PED_PORTS passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds(); #endif @@ -11533,7 +11554,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) veh->AddPassenger(ped, 0); ped->m_nPedState = PED_DRIVING; ped->RestorePreviousObjective(); - ped->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); + ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh); } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) { veh->AutoPilot.m_nCruiseSpeed = 17; } @@ -11618,7 +11639,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) switch (ped->m_objective) { case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_LEAVE_CAR: case OBJECTIVE_FOLLOW_CAR_IN_CAR: case OBJECTIVE_GOTO_AREA_ANY_MEANS: case OBJECTIVE_GOTO_AREA_ON_FOOT: @@ -11887,7 +11908,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) if (veh && veh->IsBoat()) ped->ApplyMoveSpeed(); - if (ped->m_objective == OBJECTIVE_LEAVE_VEHICLE) + if (ped->m_objective == OBJECTIVE_LEAVE_CAR) ped->RestorePreviousObjective(); #ifdef VC_PED_PORTS else if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { @@ -12553,20 +12574,20 @@ CPed::ProcessObjective(void) case OBJECTIVE_NONE: case OBJECTIVE_GUARD_AREA: case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE: - case OBJECTIVE_DESTROY_OBJ: - case OBJECTIVE_23: - case OBJECTIVE_24: + case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: + case OBJECTIVE_DESTROY_OBJECT: + case OBJECTIVE_GOTO_AREA_IN_CAR: + case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET: case OBJECTIVE_SET_LEADER: break; - case OBJECTIVE_IDLE: + case OBJECTIVE_WAIT_ON_FOOT: SetIdle(); m_objective = OBJECTIVE_NONE; SetMoveState(PEDMOVE_STILL); break; - case OBJECTIVE_FLEE_TILL_SAFE: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: if (InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); bFleeAfterExitingCar = true; } else if (m_nPedState != PED_FLEE_POS) { SetFlee(GetPosition(), 10000); @@ -12608,7 +12629,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_WAIT_IN_CAR: m_nPedState = PED_DRIVING; break; - case OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT: + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: m_nPedState = PED_DRIVING; break; case OBJECTIVE_KILL_CHAR_ANY_MEANS: @@ -12618,7 +12639,7 @@ CPed::ProcessObjective(void) && m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops && !bKindaStayInSamePlace) { - SetObjective(OBJECTIVE_FLEE_TILL_SAFE); + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); break; } if (InVehicle()) { @@ -12643,7 +12664,7 @@ CPed::ProcessObjective(void) || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) { m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } break; @@ -12720,7 +12741,7 @@ CPed::ProcessObjective(void) { bool killPlayerInNoPoliceZone = false; if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); break; } @@ -12785,7 +12806,7 @@ CPed::ProcessObjective(void) } if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) { - SetObjective(OBJECTIVE_FLEE_TILL_SAFE); + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); break; } if (m_pedInObjective->m_fHealth <= 0.0f) { @@ -13076,7 +13097,7 @@ CPed::ProcessObjective(void) { if (InVehicle()) { if (m_nPedState == PED_DRIVING) - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } else if (m_nPedState != PED_FLEE_ENTITY) { int time; if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) @@ -13140,7 +13161,7 @@ CPed::ProcessObjective(void) } break; } - case OBJECTIVE_FOLLOW_PED_IN_FORMATION: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: { if (m_pedInObjective) { CVector posToGo = GetFormationPosition(); @@ -13385,7 +13406,7 @@ CPed::ProcessObjective(void) if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } break; } @@ -13429,7 +13450,7 @@ CPed::ProcessObjective(void) { if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && InVehicle()) { - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } else { distWithTarget = m_nextRoutePointPos - GetPosition(); distWithTarget.z = 0.0f; @@ -13454,7 +13475,7 @@ CPed::ProcessObjective(void) break; } - case OBJECTIVE_FIGHT_CHAR: + case OBJECTIVE_GUARD_ATTACK: { if (m_pedInObjective) { SetLookFlag(m_pedInObjective, true); @@ -13487,7 +13508,7 @@ CPed::ProcessObjective(void) SetSeek(m_nextRoutePointPos, 0.8f); } break; - case OBJECTIVE_SOLICIT: + case OBJECTIVE_SOLICIT_VEHICLE: if (m_carInObjective) { if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) { if (!bInVehicle) { @@ -13687,7 +13708,7 @@ CPed::ProcessObjective(void) break; } // fall through - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_LEAVE_CAR: if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { if (InVehicle() #ifdef VC_PED_PORTS @@ -13970,7 +13991,7 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj) } if (m_pSeekTarget == obj && obj->IsVehicle()) { if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER - || m_objective == OBJECTIVE_SOLICIT) { + || m_objective == OBJECTIVE_SOLICIT_VEHICLE) { goingToEnterCar = true; if (IsPlayer()) checkIntervalInTime = 0.0f; @@ -15312,7 +15333,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) default: break; } - if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_VEHICLE) { + if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) { RestorePreviousObjective(); return; } @@ -15669,7 +15690,7 @@ CPed::ScanForInterestingStuff(void) if (veh->IsVehicleNormal()) { if (veh->IsCar()) { if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) { - SetObjective(OBJECTIVE_SOLICIT, veh); + SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh); Say(SOUND_PED_SOLICIT); return; } @@ -15990,7 +16011,7 @@ CPed::SeekCar(void) m_fRotationCur = m_fRotationDest; if (!bVehEnterDoorIsBlocked) { vehToSeek->bIsStatic = false; - if (m_objective == OBJECTIVE_SOLICIT) { + if (m_objective == OBJECTIVE_SOLICIT_VEHICLE) { SetSolicit(1000); } else if (m_objective == OBJECTIVE_BUY_ICE_CREAM) { SetBuyIceCream(); @@ -16322,14 +16343,14 @@ CPed::UpdateFromLeader(void) if (m_leader->m_nPedState == PED_DEAD) { SetLeader(nil); - SetObjective(OBJECTIVE_FLEE_TILL_SAFE); + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); return; } if (!m_leader->bInVehicle) { if (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { if (bInVehicle) { - if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT && m_objective != OBJECTIVE_LEAVE_VEHICLE) - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + if (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR) + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); return; } @@ -16344,12 +16365,12 @@ CPed::UpdateFromLeader(void) } } if (bInVehicle || !m_leader->bInVehicle || m_leader->m_nPedState != PED_DRIVING) { - if (m_leader->m_objective != OBJECTIVE_NONE && (!m_leader->IsPlayer() || m_leader->m_objective != OBJECTIVE_IDLE) + if (m_leader->m_objective != OBJECTIVE_NONE && (!m_leader->IsPlayer() || m_leader->m_objective != OBJECTIVE_WAIT_ON_FOOT) && m_objective != m_leader->m_objective) { switch (m_leader->m_objective) { - case OBJECTIVE_IDLE: - case OBJECTIVE_FLEE_TILL_SAFE: + case OBJECTIVE_WAIT_ON_FOOT: + case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE: case OBJECTIVE_WAIT_IN_CAR: case OBJECTIVE_FOLLOW_ROUTE: SetObjective(m_leader->m_objective); @@ -16374,7 +16395,7 @@ CPed::UpdateFromLeader(void) return; } break; - case OBJECTIVE_FIGHT_CHAR: + case OBJECTIVE_GUARD_ATTACK: return; case OBJECTIVE_HAIL_TAXI: m_leader = nil; @@ -16434,7 +16455,7 @@ CPed::UpdateFromLeader(void) } } } else if (bInVehicle) { - if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT) { + if ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) { switch (m_leader->m_objective) { case OBJECTIVE_ENTER_CAR_AS_PASSENGER: @@ -16444,11 +16465,11 @@ CPed::UpdateFromLeader(void) // fall through default: - if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_VEHICLE) { + if (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) { #ifdef VC_PED_PORTS m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250; #endif - SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); + SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } break; @@ -16821,19 +16842,19 @@ CPed::SetObjective(eObjective newObj, CVector dest) break; case OBJECTIVE_GUARD_AREA: case OBJECTIVE_WAIT_IN_CAR: - case OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT: + case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: - case OBJECTIVE_FOLLOW_PED_IN_FORMATION: - case OBJECTIVE_LEAVE_VEHICLE: + case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: + case OBJECTIVE_LEAVE_CAR: case OBJECTIVE_ENTER_CAR_AS_PASSENGER: case OBJECTIVE_ENTER_CAR_AS_DRIVER: case OBJECTIVE_FOLLOW_CAR_IN_CAR: - case OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE: - case OBJECTIVE_DESTROY_OBJ: + case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE: + case OBJECTIVE_DESTROY_OBJECT: case OBJECTIVE_DESTROY_CAR: break; case OBJECTIVE_GOTO_AREA_ANY_MEANS: diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 68006e62..d600c409 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -153,34 +153,34 @@ enum eWaitState { enum eObjective : uint32 { OBJECTIVE_NONE, - OBJECTIVE_IDLE, - OBJECTIVE_FLEE_TILL_SAFE, + OBJECTIVE_WAIT_ON_FOOT, + OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE, OBJECTIVE_GUARD_SPOT, OBJECTIVE_GUARD_AREA, // not implemented OBJECTIVE_WAIT_IN_CAR, - OBJECTIVE_WAIT_IN_CAR_THEN_GETOUT, + OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT, OBJECTIVE_KILL_CHAR_ON_FOOT, OBJECTIVE_KILL_CHAR_ANY_MEANS, OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, OBJECTIVE_GOTO_CHAR_ON_FOOT, - OBJECTIVE_FOLLOW_PED_IN_FORMATION, - OBJECTIVE_LEAVE_VEHICLE, + OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, + OBJECTIVE_LEAVE_CAR, OBJECTIVE_ENTER_CAR_AS_PASSENGER, OBJECTIVE_ENTER_CAR_AS_DRIVER, - OBJECTIVE_FOLLOW_CAR_IN_CAR, // seems not implemented so far - OBJECTIVE_FIRE_AT_OBJ_FROM_VEHICLE, // not implemented - OBJECTIVE_DESTROY_OBJ, // not implemented + OBJECTIVE_FOLLOW_CAR_IN_CAR, // not implemented + OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE, // not implemented + OBJECTIVE_DESTROY_OBJECT, // not implemented OBJECTIVE_DESTROY_CAR, OBJECTIVE_GOTO_AREA_ANY_MEANS, OBJECTIVE_GOTO_AREA_ON_FOOT, OBJECTIVE_RUN_TO_AREA, - OBJECTIVE_23, // not implemented - OBJECTIVE_24, // not implemented - OBJECTIVE_FIGHT_CHAR, + OBJECTIVE_GOTO_AREA_IN_CAR, // not implemented + OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, // not implemented + OBJECTIVE_GUARD_ATTACK, OBJECTIVE_SET_LEADER, OBJECTIVE_FOLLOW_ROUTE, - OBJECTIVE_SOLICIT, + OBJECTIVE_SOLICIT_VEHICLE, OBJECTIVE_HAIL_TAXI, OBJECTIVE_CATCH_TRAIN, OBJECTIVE_BUY_ICE_CREAM, diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 6613ea1b..fa865aec 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1288,7 +1288,7 @@ CPlayerPed::ProcessControl(void) SetDead(); return; } - if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_VEHICLE) { + if (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_CAR) { if (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) { CAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_ROLLDOOR); if (!rollDoorAssoc) { diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index eb1bad97..f89dd552 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -283,7 +283,7 @@ CAutomobile::ProcessControl(void) if(!pDriver->IsPlayer() && !(pDriver->m_leader && pDriver->m_leader->bInVehicle) && pDriver->CharCreatedBy != MISSION_CHAR) - pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this); } }else bDriverLastFrame = false; @@ -295,7 +295,7 @@ CAutomobile::ProcessControl(void) if(!pPassengers[i]->IsPlayer() && !(pPassengers[i]->m_leader && pPassengers[i]->m_leader->bInVehicle) && pPassengers[i]->CharCreatedBy != MISSION_CHAR) - pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, this); } CRubbish::StirUp(this); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index e21ad07c..9aa90845 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -669,12 +669,12 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage if (pDriver) { SetStatus(STATUS_ABANDONED); pDriver->bFleeAfterExitingCar = true; - pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this); } for (int i = 0; i < m_nNumMaxPassengers; i++) { if (pPassengers[i]) { pPassengers[i]->bFleeAfterExitingCar = true; - pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, this); } } break; From 716740f918baef80be00ce2bd0b2dcfdd7d13a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 4 Jul 2020 15:31:28 +0300 Subject: [PATCH 24/85] Peds & fixes --- src/audio/soundlist.h | 2 +- src/objects/CutsceneObject.cpp | 2 +- src/peds/CivilianPed.cpp | 24 +- src/peds/CopPed.cpp | 1 + src/peds/CopPed.h | 1 + src/peds/Ped.cpp | 391 +++++++++++++++------------------ src/peds/Ped.h | 13 +- src/peds/PedChat.cpp | 10 + src/peds/PedDebug.cpp | 9 +- src/vehicles/Vehicle.cpp | 2 +- 10 files changed, 220 insertions(+), 235 deletions(-) diff --git a/src/audio/soundlist.h b/src/audio/soundlist.h index 3db5b666..05a0d7c3 100644 --- a/src/audio/soundlist.h +++ b/src/audio/soundlist.h @@ -113,7 +113,7 @@ enum eSound : uint16 SOUND_PED_BURNING, SOUND_PED_PLAYER_REACTTOCOP, SOUND_PED_ARREST_COP, - SOUND_111, + SOUND_PED_MIAMIVICE_EXITING_CAR, SOUND_PED_COP_HELIPILOTPHRASE, SOUND_PED_PULLOUTWEAPON, SOUND_PED_HELI_PLAYER_FOUND, diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp index bf39bd03..adfec37c 100644 --- a/src/objects/CutsceneObject.cpp +++ b/src/objects/CutsceneObject.cpp @@ -93,7 +93,7 @@ CCutsceneObject::SetupLighting(void) }else{ CVector coors = GetPosition(); float lighting = CPointLights::GenerateLightsAffectingObject(&coors); - if(!bHasBlip && lighting != 1.0f){ + if(lighting != 1.0f){ SetAmbientAndDirectionalColours(lighting); return true; } diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index cec45e1b..51c11775 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -170,9 +170,13 @@ CCivilianPed::CivilianAI(void) } } +// --MIAMI: Done except comments void CCivilianPed::ProcessControl(void) { + if (CharCreatedBy == TODO_CHAR) + return; + CPed::ProcessControl(); if (bWasPostponed) @@ -198,7 +202,8 @@ CCivilianPed::ProcessControl(void) // fall through case PED_SEEK_POS: if (Seek()) { - if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) && m_pNextPathNode) { + if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA || + IsUseAttractorObjective(m_objective)) && m_pNextPathNode) { m_pNextPathNode = nil; } else if (bRunningToPhone) { @@ -207,10 +212,10 @@ CCivilianPed::ProcessControl(void) m_phoneId = -1; } else { gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_REPORTING_CRIME; - m_nPedState = PED_FACE_PHONE; + SetPedState(PED_FACE_PHONE); } } else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { - if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { + if (m_pedInObjective && m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) { if (m_moved.Magnitude() == 0.0f) { if (m_pedInObjective->m_nMoveState == PEDMOVE_STILL) m_fRotationDest = m_pedInObjective->m_fRotationCur; @@ -218,7 +223,8 @@ CCivilianPed::ProcessControl(void) } else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT && m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) { SetMoveState(m_pedInObjective->m_nMoveState); - } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || IsUseAttractorObjective(m_objective)) { + } else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA || + IsUseAttractorObjective(m_objective)) { SetIdle(); } else { RestorePreviousState(); @@ -228,7 +234,7 @@ CCivilianPed::ProcessControl(void) break; case PED_FACE_PHONE: if (FacePhone()) - m_nPedState = PED_MAKE_CALL; + SetPedState(PED_MAKE_CALL); break; case PED_MAKE_CALL: if (MakePhonecall()) @@ -284,6 +290,8 @@ CCivilianPed::ProcessControl(void) GetPosition().x - m_pMyVehicle->GetPosition().x, GetPosition().y - m_pMyVehicle->GetPosition().y, 0.0f); DMAudio.PlayOneShot(m_pMyVehicle->m_audioEntityId, SOUND_CAR_JERK, 0.0f); + m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_BEFORESEX); + Say(SOUND_PED_PLAYER_BEFORESEX); int playerSexFrequency = CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency; if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= 10 && playerSexFrequency > 250) { @@ -300,13 +308,17 @@ CCivilianPed::ProcessControl(void) } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; + ClearLeader(); SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX); } } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; m_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f; + ClearLeader(); SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + m_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX); } } else { CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; @@ -319,6 +331,7 @@ CCivilianPed::ProcessControl(void) } else { bWanderPathAfterExitingCar = true; CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil; + ClearLeader(); SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); } } @@ -340,6 +353,7 @@ CCivilianPed::ProcessControl(void) CivilianAI(); if (CharCreatedBy == RANDOM_CHAR) { + // TODO(Miami): EnterVacantNearbyCars(); UseNearbyAttractors(); } diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index d2daea42..f5c45e0d 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -86,6 +86,7 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_fAbseilPos = 0.0f; m_bBeatingSuspect = false; m_pPointGunAt = nil; + field_624 = 0; } CCopPed::~CCopPed() diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index e4ea072b..07b09ffd 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -25,6 +25,7 @@ public: bool m_bZoneDisabled; float m_fAbseilPos; eCopType m_nCopType; + int32 field_624; int8 field_628; CCopPed(eCopType, int32 modifier = 0); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2fe2ce02..807fd53e 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -401,8 +401,6 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagI80 = false; #endif - m_gangFlags = 0xFF; - bReachedAttractorHeadingTarget = false; bTurnedAroundOnAttractor = false; bCarPassenger = false; @@ -412,22 +410,26 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIsDrowning = false; bDrownsInWater = true; -#ifdef VC_PED_PORTS bHeadStuckInCollision = false; -#endif + b156_8 = false; bIsPlayerFriend = true; bDeadPedInFrontOfCar = false; + + m_gangFlags = 0xFF; + bStayInCarOnJack = false; bDontFight = false; bDoomAim = true; bCanBeShotInVehicle = true; + bPushedAlongByCar = false; b157_40 = false; bIgnoreThreatsBehindObjects = false; bNeverEverTargetThisPed = false; b158_10 = false; bBoughtIceCream = false; + b158_40 = false; if ((CGeneral::GetRandomNumber() & 3) == 0) bHasACamera = true; @@ -477,6 +479,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) #ifdef PED_SKIN m_pWeaponModel = nil; #endif + m_delayedSoundID = -1; + m_delayedSoundTimer = 0; CPopulation::UpdatePedCount((ePedType)m_nPedType, false); } @@ -2674,6 +2678,7 @@ CPed::SetModelIndex(uint32 mi) #endif } +// --MIAMI: Done void CPed::RemoveLighting(bool reset) { @@ -2686,6 +2691,7 @@ CPed::RemoveLighting(bool reset) DeActivateDirectional(); } +// --MIAMI: Done bool CPed::SetupLighting(void) { @@ -2703,7 +2709,7 @@ CPed::SetupLighting(void) } else { // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0. float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition()); - if (!bHasBlip && lightMult != 1.0f) { + if (lightMult != 1.0f) { SetAmbientAndDirectionalColours(lightMult); return true; } @@ -2711,6 +2717,7 @@ CPed::SetupLighting(void) return false; } +// --MIAMI: Done void CPed::Teleport(CVector pos) { @@ -2724,6 +2731,7 @@ CPed::Teleport(CVector pos) CWorld::Add(this); } +// --MIAMI: Done void CPed::CalculateNewOrientation(void) { @@ -3067,47 +3075,52 @@ CPed::RestorePreviousObjective(void) bObjectiveCompleted = false; } +// --MIAMI: Done void CPed::SetLeader(CEntity *leader) { m_leader = (CPed*)leader; - if(m_leader) - m_leader->RegisterReference((CEntity **)&m_leader); + if (m_leader) { + m_leader->bIsLeader = true; + m_leader->RegisterReference((CEntity**)&m_leader); + } } -// TODO(Miami) +// --MIAMI: Done except comments void CPed::SetObjective(eObjective newObj, void *entity) { if (DyingOrDead()) return; - if (m_prevObjective == newObj) { - // Why? - if (m_prevObjective != OBJECTIVE_NONE) - return; - } + if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE) + return; if (entity == this) return; + if (m_attachedTo && newObj != OBJECTIVE_KILL_CHAR_ON_FOOT && newObj != OBJECTIVE_KILL_CHAR_ANY_MEANS && newObj != OBJECTIVE_DESTROY_OBJECT && newObj != OBJECTIVE_DESTROY_CAR) + return; + if (m_objective == newObj) { switch (newObj) { case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: + case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING: + case OBJECTIVE_HASSLE_CHAR: case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: case OBJECTIVE_GOTO_AREA_ANY_MEANS: case OBJECTIVE_GUARD_ATTACK: + case OBJECTIVE_KILL_CHAR_ON_BOAT: + case OBJECTIVE_SOLICIT_FOOT: if (m_pedInObjective == entity) return; break; case OBJECTIVE_LEAVE_CAR: case OBJECTIVE_FLEE_CAR: -#ifdef VC_PED_PORTS case OBJECTIVE_LEAVE_CAR_AND_DIE: -#endif return; case OBJECTIVE_ENTER_CAR_AS_PASSENGER: case OBJECTIVE_ENTER_CAR_AS_DRIVER: @@ -3116,6 +3129,10 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_BUY_ICE_CREAM: if (m_carInObjective == entity) return; + + if (newObj == OBJECTIVE_BUY_ICE_CREAM && bBoughtIceCream) + return; + break; case OBJECTIVE_SET_LEADER: if (m_leader == entity) @@ -3129,17 +3146,14 @@ CPed::SetObjective(eObjective newObj, void *entity) break; } } else { - if ((newObj == OBJECTIVE_LEAVE_CAR -#ifdef VC_PED_PORTS - || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE -#endif - ) && !bInVehicle) + if ((newObj == OBJECTIVE_LEAVE_CAR || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE || newObj == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) + && !bInVehicle) return; } + bObjectiveCompleted = false; ClearPointGunAt(); m_objectiveTimer = 0; - bObjectiveCompleted = false; if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) { if (m_objective != newObj) { if (IsTemporaryObjective(newObj)) @@ -3153,6 +3167,13 @@ CPed::SetObjective(eObjective newObj, void *entity) } switch (newObj) { + case OBJECTIVE_WAIT_ON_FOOT_FOR_COP: + m_pedInObjective = (CPed*)entity; + m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); + SetIdle(); + // TODO(Miami) + // SetLook(m_pedInObjective); + break; case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT: // In this special case, entity parameter isn't CEntity, but int. @@ -3161,10 +3182,15 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_MUG_CHAR: + case OBJECTIVE_KILL_CHAR_ON_BOAT: m_pNextPathNode = nil; bUsePedNodeSeek = false; - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + + // TODO(Miami): Clean up old references + + // m_pLookTarget = (CEntity*)entity; // duplicate m_pedInObjective = (CPed*)entity; + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); m_pLookTarget = (CEntity*)entity; m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); @@ -3175,6 +3201,8 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING: case OBJECTIVE_HASSLE_CHAR: case OBJECTIVE_GUARD_ATTACK: + // TODO(Miami): Clean up old references + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); @@ -3185,13 +3213,11 @@ CPed::SetObjective(eObjective newObj, void *entity) m_pedFormation = FORMATION_REAR; break; case OBJECTIVE_LEAVE_CAR: -#ifdef VC_PED_PORTS case OBJECTIVE_LEAVE_CAR_AND_DIE: -#endif case OBJECTIVE_FLEE_CAR: m_carInObjective = (CVehicle*)entity; m_carInObjective->RegisterReference((CEntity **)&m_carInObjective); - if (!m_carInObjective->bIsBus || m_leaveCarTimer) + if (!m_carInObjective->bIsBus || m_leaveCarTimer != 0) break; for (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) { @@ -3202,12 +3228,19 @@ CPed::SetObjective(eObjective newObj, void *entity) } break; + case OBJECTIVE_DESTROY_OBJECT: + // TODO(Miami): Clean up old references + + m_pPointGunAt = (CPed*)entity; + if (entity) + ((CEntity*)entity)->RegisterReference((CEntity**) &m_pPointGunAt); + break; case OBJECTIVE_ENTER_CAR_AS_PASSENGER: case OBJECTIVE_ENTER_CAR_AS_DRIVER: if (m_nMoveState == PEDMOVE_STILL) SetMoveState(PEDMOVE_RUN); - if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) { + if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer() && m_pCurrentPhysSurface != entity) { RestorePreviousObjective(); break; } @@ -3237,6 +3270,10 @@ CPed::SetObjective(eObjective newObj, void *entity) m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); break; + case OBJECTIVE_SOLICIT_FOOT: + m_pedInObjective = (CPed*)entity; + m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); + break; default: break; } @@ -3371,6 +3408,7 @@ CPed::IsGangMember(void) return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9; } +// --MIAMI: Done void CPed::InformMyGangOfAttack(CEntity *attacker) { @@ -3616,6 +3654,7 @@ CPed::Chat(void) } } +// --MIAMI: Done void CPed::CheckAroundForPossibleCollisions(void) { @@ -4861,7 +4900,7 @@ CPed::RestorePreviousState(void) case PED_WANDER_PATH: SetPedState(PED_WANDER_PATH); bIsRunning = false; - if (!bFindNewNodeAfterStateRestore) { + if (bFindNewNodeAfterStateRestore) { if (m_pNextPathNode) { CVector nextNode = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); CVector diff = nextNode - GetPosition(); @@ -8291,7 +8330,7 @@ CPed::Seek(void) m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) { if ((!m_pedInObjective || !m_pedInObjective->bInVehicle) - && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) { + && (CTimer::GetFrameCounter() + m_randomSeed + 60) % 32 == 0) { CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil, false, true, false, false, false, false); @@ -8390,8 +8429,8 @@ CPed::Seek(void) CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY); if (moveDist.Magnitude() < 0.5f) { m_nPedStateTimer = 0; - m_actionX = 0; - m_actionY = 0; + m_actionX = 0.f; + m_actionY = 0.f; } } @@ -8433,8 +8472,8 @@ CPed::Seek(void) if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { m_nPedStateTimer = 0; - m_actionX = 0; - m_actionY = 0; + m_actionX = 0.f; + m_actionY = 0.f; } if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA || @@ -8451,6 +8490,7 @@ CPed::Seek(void) return true; } +// --MIAMI: Done CVector* CPed::SeekFollowingPath(void) { @@ -9441,7 +9481,6 @@ CPed::IsPedDoingDriveByShooting(void) return false; } - // --MIAMI: Done bool CPed::IsPedShootable(void) @@ -10370,12 +10409,16 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) } } +// --MIAMI: Done? void CPed::ProcessControl(void) { CColPoint foundCol; CEntity *foundEnt = nil; + if (CTimer::GetFrameCounter() + m_randomSeed % 32 == 0) + PruneReferences(); + int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); if (!bFadeOut) { if (alpha < 255) { @@ -10391,6 +10434,7 @@ CPed::ProcessControl(void) CVisibilityPlugins::SetClumpAlpha(GetClump(), alpha); bIsShooting = false; + b158_40 = false; BuildPedLists(); bIsInWater = false; bIsDrowning = false; @@ -10426,6 +10470,7 @@ CPed::ProcessControl(void) if (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) { int16 camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode; if (camMode != CCam::MODE_SNIPER + && camMode != CCam::MODE_CAMERA && camMode != CCam::MODE_ROCKETLAUNCHER && camMode != CCam::MODE_M16_1STPERSON && camMode != CCam::MODE_1STPERSON @@ -10461,13 +10506,11 @@ CPed::ProcessControl(void) if (ServiceTalkingWhenDead()) ServiceTalking(); -#ifdef VC_PED_PORTS if (bIsInWater) { bIsStanding = false; bWasStanding = false; CPhysical::ProcessControl(); } -#endif return; } @@ -10490,14 +10533,13 @@ CPed::ProcessControl(void) if (m_fHealth <= 1.0f && m_nPedState <= PED_STATES_NO_AI && !bIsInTheAir && !bIsLanding) SetDie(); + if (bIsStanding) + bPushedAlongByCar = false; + bCollidedWithMyVehicle = false; CEntity *collidingEnt = m_pDamageEntity; -#ifndef VC_PED_PORTS - if (!bUsesCollision || m_fDamageImpulse <= 0.0f || m_nPedState == PED_DIE || !collidingEnt) { -#else - if (!bUsesCollision || ((!collidingEnt || m_fDamageImpulse <= 0.0f) && (!IsPlayer() || !bIsStuck)) || m_nPedState == PED_DIE) { -#endif + if (!bUsesCollision || ((!collidingEnt || m_fDamageImpulse <= 0.0f) && (!IsPlayer() || !bIsStuck)) || m_nPedState == PED_DIE) { bHitSomethingLastFrame = false; if (m_nPedStateTimer <= 500 && bIsInTheAir) { if (m_nPedStateTimer) @@ -10516,11 +10558,7 @@ CPed::ProcessControl(void) } */ -#ifndef VC_PED_PORTS - } else { -#else } else if (collidingEnt) { -#endif switch (collidingEnt->GetType()) { case ENTITY_TYPE_BUILDING: @@ -10570,6 +10608,9 @@ CPed::ProcessControl(void) if (CanPedJumpThis(collidingEnt)) { SetJump(); } else if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { + if (m_nPedType == PEDTYPE_COP && m_nWaitState != WAITSTATE_LOOK_ABOUT) + ((CCopPed*)this)->field_624++; + SetWaitState(WAITSTATE_LOOK_ABOUT, nil); } else { SetWaitState(WAITSTATE_PLAYANIM_TAXI, nil); @@ -10579,6 +10620,8 @@ CPed::ProcessControl(void) Say(SOUND_PED_TAXI_CALL); } } else { + // TODO(Miami): CleanUpOldReference + m_pLookTarget = m_pedInObjective; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); @@ -10608,10 +10651,10 @@ CPed::ProcessControl(void) m_collidingEntityWhileFleeing = collidingEnt; m_collidingEntityWhileFleeing->RegisterReference((CEntity **) &m_collidingEntityWhileFleeing); - uint8 currentDir = floorf((PI + m_fRotationCur) / DEGTORAD(45.0f)); - uint8 nextDir; - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, currentDir, &nextDir); - + if (m_nWaitState != WAITSTATE_HITWALL) + SetWaitState(WAITSTATE_TURN180, nil); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 5000; + Flee(); } else { if (neededTurn < DEGTORAD(60.0f)) { CVector posToHead = m_vecDamageNormal * 4.0f; @@ -10625,9 +10668,17 @@ CPed::ProcessControl(void) if (m_nPedState != PED_SEEK_POS && m_nPedState != PED_SEEK_CAR) { if (m_nPedState == PED_WANDER_PATH) { m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId]; + CVector bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); angleToFace = CGeneral::GetRadianAngleBetweenPoints( - m_pNextPathNode->GetX(), m_pNextPathNode->GetY(), + bestCoords.x, bestCoords.y, GetPosition().x, GetPosition().y); + + } else if (m_nPedState == PED_FOLLOW_PATH) { + CVector bestCoords = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition(); + angleToFace = CGeneral::GetRadianAngleBetweenPoints( + bestCoords.x, bestCoords.y, + GetPosition().x, GetPosition().y); + } else { if (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f || ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) { @@ -10637,6 +10688,7 @@ CPed::ProcessControl(void) } else { posToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX(); posToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY(); + posToHead.z = ThePaths.m_pathNodes[closestNodeId].GetZ(); } angleToFace = CGeneral::GetRadianAngleBetweenPoints( posToHead.x, posToHead.y, @@ -10733,7 +10785,7 @@ CPed::ProcessControl(void) if (collidingVeh == m_pMyVehicle) bCollidedWithMyVehicle = true; -#ifdef VC_PED_PORTS + float oldHealth = m_fHealth; bool playerSufferSound = false; @@ -10743,7 +10795,8 @@ CPed::ProcessControl(void) || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA - || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)) { + || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER + || IsUseAttractorObjective(m_objective))) { if (collidingVeh != m_pCurrentPhysSurface || IsPlayer()) { if (!bVehEnterDoorIsBlocked) { @@ -10788,10 +10841,11 @@ CPed::ProcessControl(void) SetLookTimer(1300); eWeaponType weaponType = GetWeapon()->m_eWeaponType; + uint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot; if (weaponType == WEAPONTYPE_UNARMED - || weaponType == WEAPONTYPE_BASEBALLBAT - || weaponType == WEAPONTYPE_COLT45 - || weaponType == WEAPONTYPE_UZI) { + || weaponSlot == 3 + || weaponSlot == 5 + || weaponSlot == 1) { bShakeFist = true; } } else { @@ -10897,142 +10951,12 @@ CPed::ProcessControl(void) KillPedWithCar(collidingVeh, m_fDamageImpulse); } - /* VC specific if (m_pCollidingEntity != collidingEnt) bPushedAlongByCar = true; - */ } if (m_fHealth < oldHealth && playerSufferSound) Say(SOUND_PED_HIT); -#else - if (collidingVehSpeedSqr <= 1.0f / 400.0f) { - if (!IsPedInControl() - || IsPlayer() - && m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT - && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER - && m_objective != OBJECTIVE_RUN_TO_AREA) { - if (IsPlayer() && !bIsInTheAir) { - - if (IsPedInControl() - && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f - && !bIsLooking - && CTimer::GetTimeInMilliseconds() > m_lookTimer - && collidingVeh->pDriver) { - - ((CPlayerPed*)this)->AnnoyPlayerPed(false); - SetLookFlag(collidingVeh, true); - SetLookTimer(1300); - - eWeaponType weaponType = GetWeapon()->m_eWeaponType; - if (weaponType == WEAPONTYPE_UNARMED - || weaponType == WEAPONTYPE_BASEBALLBAT - || weaponType == WEAPONTYPE_COLT45 - || weaponType == WEAPONTYPE_UZI) { - bShakeFist = true; - } - } else { - SetLookFlag(collidingVeh, true); - SetLookTimer(500); - } - } - - } else if (!bVehEnterDoorIsBlocked) { - if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { - - SetDirectionToWalkAroundObject(collidingVeh); - - } else if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer - || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { - - CPed::SetDirectionToWalkAroundObject(collidingVeh); - CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; - - } else if (m_fleeFrom != collidingVeh) { - SetFlee(collidingVeh, 4000); - bUsePedNodeSeek = false; - SetMoveState(PEDMOVE_WALK); - } - } - } else { - DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, m_fDamageImpulse); - if (IsPlayer()) { - CColModel *collidingCol = CModelInfo::GetModelInfo(collidingVeh->GetModelIndex())->GetColModel(); - CVector colMinVec = collidingCol->boundingBox.min; - CVector colMaxVec = collidingCol->boundingBox.max; - - CVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition(); - - // TLVC = To look vehicle center - - float angleToVehFront = collidingVeh->GetForward().Heading(); - float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); - angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - - // I don't know why do we use that - float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); - - CVector vehDist = GetPosition() - collidingVeh->GetPosition(); - vehDist.Normalise(); - - float vehRightVecAndSpeedDotProd; - - if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { - if (angleDiffFromLookingFrontTLVC <= 0.0f) { - vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - // vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right? - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - - // Car's right faces towards us and isn't coming directly to us - if (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); - - if (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) { - if (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f - && DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) { - SetEvasiveStep(collidingVeh, 1); - } - } - } - } else { - vehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed); - } - - if (vehRightVecAndSpeedDotProd <= 0.1f) { - if (m_nPedState != PED_FIGHT) { - SetLookFlag(collidingVeh, true); - SetLookTimer(700); - } - } else { - bIsStanding = false; - CVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed; - int dir = GetLocalDirection(collidingEntMoveDir); - SetFall(1000, (AnimationId)(dir + ANIM_KO_SKID_FRONT), false); - CPed *driver = collidingVeh->pDriver; - - float damage; - if (driver && driver->IsPlayer()) { - damage = vehRightVecAndSpeedDotProd * 1000.0f; - } else if (collidingVeh->GetModelIndex() == MI_TRAIN) { - damage = 50.0f; - } else { - damage = 20.0f; - } - - InflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir); - Say(SOUND_PED_DAMAGE); - } - } else { - KillPedWithCar(collidingVeh, m_fDamageImpulse); - } - } -#endif break; } case ENTITY_TYPE_PED: @@ -11048,11 +10972,12 @@ CPed::ProcessControl(void) player->AnnoyPlayerPed(false); player->SetLookFlag(this, true); player->SetLookTimer(1300); - eWeaponType weapon = player->GetWeapon()->m_eWeaponType; - if (weapon == WEAPONTYPE_UNARMED - || weapon == WEAPONTYPE_BASEBALLBAT - || weapon == WEAPONTYPE_COLT45 - || weapon == WEAPONTYPE_UZI) { + eWeaponType weaponType = player->GetWeapon()->m_eWeaponType; + uint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot; + if (weaponType == WEAPONTYPE_UNARMED + || weaponSlot == 3 + || weaponSlot == 5 + || weaponSlot == 1) { player->bShakeFist = true; } } @@ -11067,12 +10992,7 @@ CPed::ProcessControl(void) } } CVector forceDir; - if (!bIsInTheAir && m_nPedState != PED_JUMP -#ifdef VC_PED_PORTS - && m_fDamageImpulse > 0.0f -#endif - ) { - + if (!bIsInTheAir && m_nPedState != PED_JUMP && m_fDamageImpulse > 0.0f) { forceDir = m_vecDamageNormal; forceDir.z = 0.0f; if (!bIsStanding) { @@ -11088,7 +11008,7 @@ CPed::ProcessControl(void) || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL) #endif ) { - if (m_nPedStateTimer <= 1000 && m_nPedStateTimer) { + if (m_nPedStateTimer <= 1000 && m_nPedStateTimer != 0) { forceDir = GetPosition() - m_vecHitLastPos; } else { m_nPedStateTimer = 0; @@ -11284,15 +11204,15 @@ CPed::ProcessControl(void) } else if (m_nPedState == PED_DRIVING) { bWanderPathAfterExitingCar = true; SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); + bStartWanderPathOnFoot = false; } } - if (!bIsStanding && m_vecMoveSpeed.z > 0.25f) { + if (!bIsStanding && m_vecMoveSpeed.z > 0.25) { float airResistance = Pow(0.95f, CTimer::GetTimeStep()); m_vecMoveSpeed *= airResistance; } -#ifdef VC_PED_PORTS if (IsPlayer() || !bIsStanding || m_vecMoveSpeed.x != 0.0f || m_vecMoveSpeed.y != 0.0f || m_vecMoveSpeed.z != 0.0f || (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) || m_vecAnimMoveDelta.x != 0.0f || m_vecAnimMoveDelta.y != 0.0f @@ -11314,9 +11234,7 @@ CPed::ProcessControl(void) m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); } -#else - CPhysical::ProcessControl(); -#endif + if (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) { RequestDelayedWeapon(); PlayFootSteps(); @@ -11333,14 +11251,12 @@ CPed::ProcessControl(void) bHeadStuckInCollision = false; } } -#ifdef VC_PED_PORTS if (bHeadStuckInCollision) { CVector posToCheck = GetPosition(); posToCheck.z += 0.9f; if (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false)) bHeadStuckInCollision = false; } -#endif ProcessObjective(); if (!bIsAimingGun) { if (bIsRestoringGun) @@ -11378,8 +11294,11 @@ CPed::ProcessControl(void) Look(); break; case PED_WANDER_RANGE: + // III has these in here(and they were unused): + /* WanderRange(); CheckAroundForPossibleCollisions(); + */ break; case PED_WANDER_PATH: WanderPath(); @@ -11398,8 +11317,13 @@ CPed::ProcessControl(void) case PED_CPR: case PED_SOLICIT: case PED_STEP_AWAY: + case PED_SUN_BATHE: + case PED_FLASH: + case PED_JOG: case PED_UNKNOWN: case PED_STATES_NO_AI: + case PED_ABSEIL: + case PED_SIT: case PED_JUMP: case PED_STAGGER: case PED_DIVE_AWAY: @@ -11410,8 +11334,8 @@ CPed::ProcessControl(void) case PED_OPEN_DOOR: case PED_DEAD: case PED_DRAG_FROM_CAR: - case PED_EXIT_CAR: case PED_STEAL_CAR: + case PED_EXIT_CAR: break; case PED_ENTER_CAR: case PED_CARJACK: @@ -11450,6 +11374,7 @@ CPed::ProcessControl(void) break; case PED_FLEE_ENTITY: if (!m_fleeFrom) { + b157_10 = false; SetIdle(); break; } @@ -11498,13 +11423,19 @@ CPed::ProcessControl(void) break; if (CTimer::GetTimeInMilliseconds() <= m_fleeTimer) { - if (m_fleeFrom) { - ms_vec2DFleePosition = m_fleeFrom->GetPosition(); + if (m_pFire) { + if (m_fleeFrom) { + ms_vec2DFleePosition = m_fleeFrom->GetPosition(); + } else { + ms_vec2DFleePosition.x = m_fleeFromPosX; + ms_vec2DFleePosition.y = m_fleeFromPosY; + } + Flee(); } else { - ms_vec2DFleePosition.x = m_fleeFromPosX; - ms_vec2DFleePosition.y = m_fleeFromPosY; + m_nLastPedState = PED_NONE; + SetWanderPath(0); + SetWaitState(WAITSTATE_FINISH_FLEE, 0); } - Flee(); } else { if (m_pFire) m_pFire->Extinguish(); @@ -11590,7 +11521,7 @@ CPed::ProcessControl(void) Die(); break; case PED_HANDS_UP: - if (m_pedStats->m_temper <= 50) { + if (m_pedStats->m_flags & STAT_GUN_PANIC) { if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSCOWER)) { CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER); Say(SOUND_PED_HANDS_COWER); @@ -11600,7 +11531,8 @@ CPed::ProcessControl(void) Say(SOUND_PED_HANDS_UP); } break; - default: break; + default: + break; } SetMoveAnim(); if (bPedIsBleeding || m_bleedCounter != 0) { @@ -11628,9 +11560,19 @@ CPed::ProcessControl(void) ServiceTalking(); if (bInVehicle && !m_pMyVehicle) bInVehicle = false; -#ifndef VC_PED_PORTS - m_pCurrentPhysSurface = nil; -#endif + + if (b156_8) { + if (m_pMyVehicle && m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->IsPlayer()) { + Say(SOUND_PED_FLEE_SPRINT); + } + } + + if (m_delayedSoundID >= 0 && CTimer::GetTimeInMilliseconds() > m_delayedSoundTimer) { + Say(m_delayedSoundID); + m_delayedSoundID = -1; + m_delayedSoundTimer = 0; + } + if (bFannyMagnetCheat && m_nPedType == PEDTYPE_CIVFEMALE && m_pedStats->m_sexiness > 40 && !m_leader) { SetLeader(FindPlayerPed()); @@ -13054,14 +12996,17 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) } ped->bInVehicle = false; - if (veh && veh->IsCar() && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) { + if (veh && (veh->IsCar() || veh->IsBike()) && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) { ped->PositionPedOutOfCollision(); } if (ped->m_nPedState == PED_EXIT_CAR) { - if (ped->m_nPedType == PEDTYPE_COP) + if (ped->m_nPedType == PEDTYPE_COP) { ped->SetIdle(); - else + if (((CCopPed*)ped)->m_nCopType == COP_MIAMIVICE && ped->m_pMyVehicle && ped->m_pMyVehicle->pDriver == ped) { + DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_PED_MIAMIVICE_EXITING_CAR, 0.f); + } + } else ped->RestorePreviousState(); veh = ped->m_pMyVehicle; @@ -14880,7 +14825,6 @@ CPed::ProcessObjective(void) #endif if (m_pMyVehicle->IsBoat()) SetExitBoat(m_pMyVehicle); - else SetExitCar(m_pMyVehicle, 0); } @@ -14888,6 +14832,15 @@ CPed::ProcessObjective(void) RestorePreviousObjective(); } } + if (b156_8) { + if (CTheScripts::IsPlayerOnAMission()) { + CVehicle *playerVeh = FindPlayerVehicle(); + if (playerVeh && playerVeh->IsPassenger(this)) { + if (m_leaveCarTimer != 0) + m_leaveCarTimer = 0; + } + } + } break; case OBJECTIVE_AIM_GUN_AT: if (m_pedInObjective) { @@ -19190,7 +19143,7 @@ CPed::SetCarJack_AllClear(CVehicle* car, uint32 doorNode, uint32 doorFlag) if (m_nPedType == PEDTYPE_COP) Say(SOUND_PED_ARREST_COP); else if (car->m_nDoorLock == CARLOCK_UNLOCKED) - Say(SOUND_PED_CAR_JACKING); + Say(SOUND_PED_CAR_JACKING, 1000); CVector carEnterPos; carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType); diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 457036d3..d5062ee1 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -459,9 +459,7 @@ public: //uint32 b156_4 uint32 b156_8 : 1; uint32 bIsPlayerFriend : 1; -#ifdef VC_PED_PORTS uint32 bHeadStuckInCollision : 1; -#endif uint32 bDeadPedInFrontOfCar : 1; uint32 bStayInCarOnJack : 1; @@ -469,8 +467,8 @@ public: uint32 bDoomAim : 1; uint32 bCanBeShotInVehicle : 1; //uint32 b157_8 - //uint32 b157_10 - //uint32 b157_20 + uint32 b157_10 : 1; + uint32 bPushedAlongByCar : 1; uint32 b157_40 : 1; uint32 bIgnoreThreatsBehindObjects : 1; @@ -480,7 +478,7 @@ public: //uint32 b158_8 uint32 b158_10 : 1; uint32 bBoughtIceCream : 1; - //uint32 b158_40 + uint32 b158_40 : 1; //uint32 b158_80 // our own flags @@ -631,8 +629,8 @@ public: uint32 m_threatFlags; uint32 m_threatCheck; uint32 m_lastThreatCheck; - uint32 m_sayType; - uint32 m_sayTimer; + uint32 m_delayedSoundID; + uint32 m_delayedSoundTimer; uint32 m_lastSoundStart; uint32 m_soundStart; uint16 m_lastQueuedSound; @@ -664,6 +662,7 @@ public: void AimGun(void); void KillPedWithCar(CVehicle *veh, float impulse); void Say(uint16 audio); + void Say(uint16 audio, int32 time); void SetLookFlag(CEntity* target, bool keepTryingToLook, bool cancelPrevious = false); void SetLookFlag(float direction, bool keepTryingToLook, bool cancelPrevious = false); void SetLookTimer(int time); diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp index ee639a50..4480a8cd 100644 --- a/src/peds/PedChat.cpp +++ b/src/peds/PedChat.cpp @@ -155,4 +155,14 @@ CPed::Say(uint16 audio) m_queuedSound = audioToPlay; } } +} + +// --MIAMI: Done +void +CPed::Say(uint16 audio, int32 time) +{ + if (m_delayedSoundID == -1) { + m_delayedSoundID = audio; + m_delayedSoundTimer = CTimer::GetTimeInMilliseconds() + time; + } } \ No newline at end of file diff --git a/src/peds/PedDebug.cpp b/src/peds/PedDebug.cpp index 1c22963e..c3298461 100644 --- a/src/peds/PedDebug.cpp +++ b/src/peds/PedDebug.cpp @@ -82,8 +82,14 @@ static char StateText[][18] = { "Investigate", "Step away", "On Fire", + "Sun Bathe", + "Flash", + "Jog", + "Answer Mobile", "Unknown", "STATES_NO_AI", + "Abseil", + "Sit", "Jump", "Fall", "GetUp", @@ -106,6 +112,7 @@ static char StateText[][18] = { "Exit Car", "Hands Up", "Arrested", + "Deploying Stinger" }; static char PersonalityTypeText[][18] = { @@ -283,7 +290,7 @@ CPed::DebugRenderOnePedText(void) CFont::SetJustifyOff(); CFont::SetColor(CRGBA(255, 255, 0, 255)); CFont::SetBackGroundOnlyTextOn(); - CFont::SetFontStyle(0); + CFont::SetFontStyle(1); AsciiToUnicode(StateText[m_nPedState], gUString); CFont::PrintString(screenCoords.x, screenCoords.y, gUString); AsciiToUnicode(ObjectiveText[m_objective], gUString); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 360b843b..e26fd99f 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -232,7 +232,7 @@ CVehicle::SetupLighting(void) }else{ CVector coors = GetPosition(); float lighting = CPointLights::GenerateLightsAffectingObject(&coors); - if(!bHasBlip && lighting != 1.0f){ + if(lighting != 1.0f){ SetAmbientAndDirectionalColours(lighting); return true; } From 1cea84d2b1673bfd86e1698c27c381e1488c77cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 4 Jul 2020 16:00:41 +0300 Subject: [PATCH 25/85] Remove console and fix sth --- src/peds/Ped.cpp | 2 +- src/skel/glfw/glfw.cpp | 3 +++ src/skel/win/win.cpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 67fe7788..7a1bc3fc 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -4359,7 +4359,7 @@ CPed::RestorePreviousState(void) case PED_WANDER_PATH: m_nPedState = PED_WANDER_PATH; bIsRunning = false; - if (!bFindNewNodeAfterStateRestore) { + if (bFindNewNodeAfterStateRestore) { if (m_pNextPathNode) { CVector diff = m_pNextPathNode->GetPosition() - GetPosition(); if (diff.MagnitudeSqr() < sq(7.0f)) { diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 5e0c178c..21aace7a 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -1367,11 +1367,14 @@ WinMain(HINSTANCE instance, RwChar** argv; SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); +#if 0 // TODO: make this an option somewhere AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); +#endif + #else int main(int argc, char *argv[]) diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index e1fb5b7f..52941d7d 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1929,12 +1929,13 @@ WinMain(HINSTANCE instance, StaticPatcher::Apply(); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); - +#if 0 // TODO: make this an option somewhere AllocConsole(); freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); +#endif /* * Initialize the platform independent data. From ceb1defc4e220037ad1b17eb2b8a497c1385de7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 4 Jul 2020 23:50:43 +0300 Subject: [PATCH 26/85] fixes from master, menu helper text --- src/control/Garages.cpp | 2 +- src/core/Frontend.cpp | 203 +++++++++++++++++----------------------- src/core/Frontend.h | 2 +- src/core/MenuScreens.h | 4 +- src/core/Radar.cpp | 36 +++---- src/core/Radar.h | 10 +- src/core/Wanted.cpp | 2 +- src/core/config.h | 2 +- src/core/re3.cpp | 12 +-- src/peds/Ped.cpp | 34 ++++++- 10 files changed, 142 insertions(+), 165 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 7175d393..66f1851d 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -400,7 +400,7 @@ void CGarage::Update() FindPlayerPed()->m_pWanted->Suspend(); } CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE); - FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; + FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false; #ifdef FIX_BUGS bool bChangedColour = false; #else diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 19e8e8f3..f6845920 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -38,6 +38,9 @@ #include "Messages.h" #include "FileLoader.h" +// TODO(Miami): Remove that!! That was my map implementation for III, instead use MAP_ENHACEMENTS on some places +#define CUSTOM_MAP + // TODO(Miami): This is -3 on VC but still -1 on AudioManager?!? What the hell? #define INVALID_AUDIO_PROVIDER -1 @@ -52,7 +55,6 @@ CRGBA HEADER_COLOR(255, 150, 255, 255); CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); CRGBA SLIDERON_COLOR(97, 194, 247, 255); CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); -CRGBA MAPINFOBOX_COLOR(255, 150, 225, 150); #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -117,9 +119,10 @@ MenuTrapezoid menuBg(CGeneral::GetRandomNumber() % 40 + 65, CGeneral::GetRandomN MenuTrapezoid menuOptionHighlight(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); -// TODO(Miami): TEMPORARY +#ifdef CUSTOM_MAP bool bMapLoaded = false; bool bMapMouseShownOnce = false; +#endif #ifndef MASTER bool CMenuManager::m_PrefsMarketing = false; @@ -664,11 +667,25 @@ CMenuManager::CheckSliderMovement(int value) } void -CMenuManager::DisplayHelperText() +CMenuManager::DisplayHelperText(char *text) { + if (m_nMenuFadeAlpha != 255) + return; + // there was a unused static bool static PauseModeTime LastFlash = 0; - int32 alpha; + int32 alpha = 255; + + CFont::SetRightJustifyOn(); + CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetDropShadowPosition(0); + + if (text) { + CFont::SetColor(CRGBA(255, 255, 255, 255)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get(text)); + return; + } if (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) { if (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 10) { @@ -682,41 +699,67 @@ CMenuManager::DisplayHelperText() alpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha; } - CFont::SetCentreOn(); - CFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE)); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - + CFont::SetColor(CRGBA(255, 255, 255, alpha)); // TODO: name this cases? switch (m_nHelperTextMsgId) { - case 0: - { - int action = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action; - if (action != MENUACTION_CHANGEMENU && action != MENUACTION_KEYBOARDCTRLS && action != MENUACTION_RESTOREDEF) { - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_MIG")); - } - break; - } case 1: - CFont::SetColor(CRGBA(255, 255, 255, 255)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_APP")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_APP")); break; case 2: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_HRD")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_HRD")); break; case 3: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSO")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_RSO")); break; case 4: - CFont::SetColor(CRGBA(255, 255, 255, alpha)); - CFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), TheText.Get("FET_RSC")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_STS")); + break; + case 5: + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), TheText.Get("FET_RSC")); break; default: + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NO) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MUSICVOLUME || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SFXVOLUME) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_KEYBOARDCTRLS) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SCREENRES) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_bGameNotLoaded ? TheText.Get("FET_MIG") : TheText.Get("FEH_NA")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_AUDIOHW || + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SPEAKERCONF) { + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESTOREDEF) + return; + + if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MP3VOLUMEBOOST) { + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + return; + } + + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), + m_nCurrScreen != MENUPAGE_STATS ? TheText.Get("FET_MIG") : TheText.Get("FEH_SSA")); + break; } - CFont::SetRightJustifyOff(); } // --MIAMI: Done @@ -880,28 +923,6 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) wchar unicodeTemp[64]; char asciiTemp[32]; -#ifdef MENU_MAP - if (m_nCurrScreen == MENUPAGE_MAP) { - // Back button - wchar *backTx = TheText.Get("FEDS_TB"); - CFont::SetDropShadowPosition(1); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); - CFont::SetRightJustifyOff(); - CFont::SetCentreOn(); - CFont::PrintString(MENU_X(60.0f), SCREEN_SCALE_FROM_BOTTOM(120.0f), backTx); - CFont::SetDropShadowPosition(0); - if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { - m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_nCurrOption = m_nPrevOption = 0; - } else { - m_nHoverOption = HOVEROPTION_RANDOM_ITEM; - m_nCurrOption = m_nPrevOption = 1; - } - return; - } -#endif - bool weHaveLabel = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; uint8 section = 0; // 0: highlight trapezoid 1: texts @@ -1356,8 +1377,6 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) section++; } - // TODO(Miami) - /* switch (m_nCurrScreen) { case MENUPAGE_STATS: case MENUPAGE_CONTROLLER_PC: @@ -1371,7 +1390,6 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) DisplayHelperText("FEA_NAH"); break; } - */ if (m_nCurrScreen == MENUPAGE_DELETING_IN_PROGRESS) { SmallMessageScreen("FEDL_WR"); @@ -4344,8 +4362,7 @@ CMenuManager::ProcessButtonPresses(void) case MENUACTION_YES: case MENUACTION_NO: { - // TODO(Miami): TEMP -#ifdef MENU_MAP +#ifdef CUSTOM_MAP if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) { bMapLoaded = false; } @@ -4411,12 +4428,11 @@ CMenuManager::ProcessButtonPresses(void) if (m_nDisplayVideoMode != m_nPrefsVideoMode) { m_nPrefsVideoMode = m_nDisplayVideoMode; _psSelectScreenVM(m_nPrefsVideoMode); - SetHelperText(0); // TODO(Miami): Remove that DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); DMAudio.Service(); CentreMousePointer(); m_bShowMouse = true; - // m_nCurrOption = 5; // Why? + // m_nCurrOption = 5; // Why? TODO(Miami) m_nOptionHighlightTransitionBlend = 0; SaveSettings(); } @@ -4426,7 +4442,6 @@ CMenuManager::ProcessButtonPresses(void) if (m_nSelectedScreenMode != m_nPrefsWindowed) { m_nPrefsWindowed = m_nSelectedScreenMode; _psSelectScreenVM(m_nPrefsVideoMode); // apply same resolution - SetHelperText(0); SaveSettings(); } break; @@ -4435,13 +4450,11 @@ CMenuManager::ProcessButtonPresses(void) { int selectedProvider = m_nPrefsAudio3DProviderIndex; if (selectedProvider != INVALID_AUDIO_PROVIDER) { + if (selectedProvider == -1) + selectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); - if (selectedProvider == m_nPrefsAudio3DProviderIndex) { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SetHelperText(0); - } else { - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0); - SetHelperText(4); + if (selectedProvider != m_nPrefsAudio3DProviderIndex) { + SetHelperText(5); } SaveSettings(); } @@ -5163,7 +5176,7 @@ CMenuManager::DrawQuitGameScreen(void) m_AllowNavigation = false; } -#ifdef MENU_MAP +#ifdef CUSTOM_MAP #define ZOOM(x, y, in) \ do { \ @@ -5177,15 +5190,17 @@ CMenuManager::DrawQuitGameScreen(void) break; \ \ m_fMapSize *= z2; \ - } while(0) \ + } while(0) + +#endif void CMenuManager::PrintMap(void) { - CFont::SetJustifyOn(); m_bMenuMapActive = true; CRadar::InitFrontEndMap(); +#ifdef CUSTOM_MAP // Just entered to map if (!bMapLoaded) { m_fMapSize = SCREEN_HEIGHT * 2.0f; @@ -5207,15 +5222,11 @@ CMenuManager::PrintMap(void) return; } } +#endif // Because m_fMapSize is half of the map length, and map consists of 3x3 tiles. float halfTile = m_fMapSize / 3.0f; - // Darken background a bit - CSprite2d::DrawRect(CRect(0, 0, - SCREEN_WIDTH, SCREEN_HEIGHT), - CRGBA(0, 0, 0, FadeIn(128))); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); if (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) { @@ -5265,6 +5276,7 @@ CMenuManager::PrintMap(void) CRadar::DrawBlips(); +#ifdef CUSTOM_MAP CVector2D mapPoint; mapPoint.x = m_nMousePosX; mapPoint.y = m_nMousePosY; @@ -5338,56 +5350,15 @@ CMenuManager::PrintMap(void) if (m_fMapCenterY - m_fMapSize > SCREEN_HEIGHT / 2) m_fMapCenterY = SCREEN_HEIGHT / 2 + m_fMapSize; - +#endif m_bMenuMapActive = false; - // CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); // From VC - // CFont::SetRightJustifyWrap(10.0f); - - CSprite2d::DrawRect(CRect(MENU_X(14.0f), SCREEN_STRETCH_FROM_BOTTOM(95.0f), - SCREEN_STRETCH_FROM_RIGHT(11.0f), SCREEN_STRETCH_FROM_BOTTOM(59.0f)), - CRGBA(MAPINFOBOX_COLOR.r, MAPINFOBOX_COLOR.g, MAPINFOBOX_COLOR.b, MAPINFOBOX_COLOR.a)); - - CFont::SetScale(MENU_X(0.4f), MENU_Y(0.7f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - - float nextX = MENU_X(30.0f), nextY = 95.0f; - wchar *text; -#ifdef MORE_LANGUAGES -#define TEXT_PIECE(key,extraSpace) \ - text = TheText.Get(key);\ - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), text);\ - if (CFont::IsJapanese())\ - nextX += CFont::GetStringWidth_Jap(text) + MENU_X(extraSpace);\ - else\ - nextX += CFont::GetStringWidth(text, true) + MENU_X(extraSpace); -#else -#define TEXT_PIECE(key,extraSpace) \ - text = TheText.Get(key); CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), text); nextX += CFont::GetStringWidth(text, true) + MENU_X(extraSpace); -#endif - - TEXT_PIECE("FEC_MWF", 3.0f); - TEXT_PIECE("FEC_PGU", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - TEXT_PIECE("FEC_ZIN", 20.0f); - TEXT_PIECE("FEC_MWB", 3.0f); - TEXT_PIECE("FEC_PGD", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEC_ZOT")); nextX = MENU_X(30.0f); nextY -= 11.0f; - TEXT_PIECE("FEC_UPA", 2.0f); - TEXT_PIECE("FEC_DWA", 2.0f); - TEXT_PIECE("FEC_LFA", 2.0f); - TEXT_PIECE("FEC_RFA", 2.0f); - TEXT_PIECE("FEC_MSL", 1.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEC_MOV")); nextX = MENU_X(30.0f); nextY -= 11.0f; - TEXT_PIECE("FEC_MSR", 2.0f); - TEXT_PIECE("FEC_IBT", 1.0f); - CFont::PrintString(nextX, SCREEN_SCALE_FROM_BOTTOM(nextY), TheText.Get("FEC_TAR")); -#undef TEXT_PIECE + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(5.0f)); + CFont::SetRightJustifyWrap(SCREEN_SCALE_X(10.0f)); + DisplayHelperText("FEH_MPH"); } +#ifdef CUSTOM_MAP #undef ZOOM #endif diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 4655c971..577e36db 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -613,7 +613,7 @@ public: void CheckCodesForControls(int); bool CheckHover(int x1, int x2, int y1, int y2); void CheckSliderMovement(int); - void DisplayHelperText(); + void DisplayHelperText(char*); int DisplaySlider(float, float, float, float, float, float, float); void DoSettingsBeforeStartingAGame(); void DrawStandardMenus(bool); diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index cae65316..a7e1796d 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -79,11 +79,9 @@ CMenuScreen aScreens[] = { MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, MENUALIGN_CENTER, }, - // TODO(Miami): This is still my implementation // MENUPAGE_MAP = 6 { "FEH_MAP", MENUPAGE_NONE, 2, - MENUACTION_UNK110, "", SAVESLOT_NONE, 0, 0, 0, 0, // to prevent cross/enter to go back - MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0, + MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 70, 380, MENUALIGN_CENTER, }, // MENUPAGE_NEW_GAME_RELOAD = 7 diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 475ca4d3..3b581dea 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -121,11 +121,11 @@ static_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), "CRadar: not #define RADAR_MIN_SPEED (0.3f) #define RADAR_MAX_SPEED (0.9f) -#ifdef MENU_MAP CRGBA CRadar::ArrowBlipColour1; CRGBA CRadar::ArrowBlipColour2; uint16 CRadar::MapLegendCounter; int16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; +#ifdef MAP_ENHANCEMENTS int CRadar::TargetMarkerId = -1; CVector CRadar::TargetMarkerPos; #endif @@ -263,10 +263,9 @@ int LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D & uint8 CRadar::CalculateBlipAlpha(float dist) { -#ifdef MENU_MAP if (FrontEndMenuManager.m_bMenuMapActive) return 255; -#endif + if (dist <= 1.0f) return 255; @@ -486,9 +485,7 @@ void CRadar::DrawBlips() CVector2D in = CVector2D(0.0f, 0.0f); TransformRadarPointToScreenSpace(out, in); -#ifdef MENU_MAP if (!FrontEndMenuManager.m_bMenuMapActive) { -#endif float angle; if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN) angle = PI + FindPlayerHeading(); @@ -508,9 +505,7 @@ void CRadar::DrawBlips() LimitRadarPoint(in); TransformRadarPointToScreenSpace(out, in); DrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255); -#ifdef MENU_MAP } -#endif CEntity *blipEntity = nil; for(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) { @@ -743,14 +738,12 @@ void CRadar::DrawBlips() break; } } -#ifdef MENU_MAP if (FrontEndMenuManager.m_bMenuMapActive) { CVector2D in, out; TransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift()); TransformRadarPointToScreenSpace(out, in); DrawYouAreHereSprite(out.x, out.y); } -#endif } } @@ -898,7 +891,7 @@ void CRadar::DrawRadarSection(int32 x, int32 y) void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) { RadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha)); -#ifdef MENU_MAP + if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; for (int i = 0; i < NUM_MAP_LEGENDS; i++) { @@ -910,7 +903,6 @@ void CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha) MapLegendCounter++; } } -#endif } void CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha) @@ -1046,10 +1038,10 @@ float CRadar::LimitRadarPoint(CVector2D &point) float dist, invdist; dist = point.Magnitude(); -#ifdef MENU_MAP + if (FrontEndMenuManager.m_bMenuMapActive) return dist; -#endif + if (dist > 1.0f) { invdist = 1.0f / dist; point.x *= invdist; @@ -1130,7 +1122,7 @@ void CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size) INITSAVEBUF WriteSaveHeader(buf, 'R', 'D', 'R', '\0', *size - SAVE_HEADER_SIZE); -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS if (TargetMarkerId != -1) { ClearBlip(TargetMarkerId); TargetMarkerId = -1; @@ -1276,7 +1268,8 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, CSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha)); break; } -#ifdef MENU_MAP + + // TODO(Miami): Map // VC uses -1 for coords and -2 for entities but meh, I don't want to edit DrawBlips if (FrontEndMenuManager.m_bMenuMapActive) { bool alreadyThere = false; @@ -1290,7 +1283,6 @@ void CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, ArrowBlipColour1 = CRGBA(red, green, blue, alpha); } } -#endif } void CRadar::Shutdown() @@ -1402,13 +1394,10 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D // Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0) void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in) { -#ifdef MENU_MAP if (FrontEndMenuManager.m_bMenuMapActive) { out.x = (FrontEndMenuManager.m_fMapCenterX - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * FrontEndMenuManager.m_fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH; out.y = (FrontEndMenuManager.m_fMapCenterY - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * FrontEndMenuManager.m_fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH; - } else -#endif - { + } else { #ifdef FIX_BUGS out.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT); #else @@ -1462,10 +1451,7 @@ void CRadar::CalculateCachedSinCos() { if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED -#ifdef MENU_MAP - || FrontEndMenuManager.m_bMenuMapActive -#endif - ) { + || FrontEndMenuManager.m_bMenuMapActive ) { cachedSin = 0.0f; cachedCos = 1.0f; } else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) { @@ -1486,7 +1472,6 @@ CRadar::CalculateCachedSinCos() } } -#ifdef MENU_MAP void CRadar::InitFrontEndMap() { @@ -1530,6 +1515,7 @@ CRadar::DrawYouAreHereSprite(float x, float y) MapLegendList[MapLegendCounter++] = RADAR_SPRITE_CENTRE; } +#ifdef MAP_ENHANCEMENTS void CRadar::ToggleTargetMarker(float x, float y) { diff --git a/src/core/Radar.h b/src/core/Radar.h index 95b74b84..a36faaea 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -21,6 +21,8 @@ #define COORDBLIP_MARKER_COLOR_B 242 #define COORDBLIP_MARKER_COLOR_A 255 +#define NUM_MAP_LEGENDS 75 + #define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit #define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f) #define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f) @@ -48,10 +50,8 @@ enum eBlipDisplay enum eRadarSprite { -#ifdef MENU_MAP RADAR_SPRITE_ENTITY_BLIP = -2, RADAR_SPRITE_COORD_BLIP = -1, -#endif RADAR_SPRITE_NONE = 0, RADAR_SPRITE_CENTRE, RADAR_SPRITE_MAP_HERE, @@ -173,17 +173,19 @@ public: static CSprite2d *RadarSprites[RADAR_SPRITE_COUNT]; static float cachedCos; static float cachedSin; -#ifdef MENU_MAP -#define NUM_MAP_LEGENDS 75 static CRGBA ArrowBlipColour1; static CRGBA ArrowBlipColour2; static int16 MapLegendList[NUM_MAP_LEGENDS]; static uint16 MapLegendCounter; + +#ifdef MAP_ENHANCEMENTS static int TargetMarkerId; static CVector TargetMarkerPos; +#endif static void InitFrontEndMap(); static void DrawYouAreHereSprite(float, float); +#ifdef MAP_ENHANCEMENTS static void ToggleTargetMarker(float, float); #endif static uint8 CalculateBlipAlpha(float dist); diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index 83407c56..c70a3ab5 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -182,7 +182,7 @@ CWanted::RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool po void CWanted::RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare) { -#ifdef FIX_BUGS +#ifdef FIX_SIGNIFICANT_BUGS if(!AddCrimeToQ(type, id, coors, true, policeDoesntCare)) #else if(!AddCrimeToQ(type, id, coors, false, policeDoesntCare)) diff --git a/src/core/config.h b/src/core/config.h index 5459c336..798e6bb2 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -242,7 +242,7 @@ enum Config { //# define PS2_MENU_USEALLPAGEICONS #else //# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. -# define MENU_MAP // VC-like menu map. Make sure you have new menu.txd +# define MAP_ENHANCEMENTS // Adding waypoint etc. # define SCROLLABLE_STATS_PAGE // only draggable by mouse atm # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON diff --git a/src/core/re3.cpp b/src/core/re3.cpp index d49eff50..7058c812 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -77,7 +77,6 @@ mysrand(unsigned int seed) void ReloadFrontendOptions(void) { - RemoveCustomFrontendOptions(); CustomFrontendOptionsPopulate(); } @@ -139,6 +138,8 @@ void ToggleFreeCam(int8 action) void CustomFrontendOptionsPopulate(void) { + RemoveCustomFrontendOptions(); // if exist + #ifdef MORE_LANGUAGES FrontendOptionSetPosition(MENUPAGE_LANGUAGE_SETTINGS); FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, LangPolSelect, nil); @@ -152,11 +153,6 @@ CustomFrontendOptionsPopulate(void) FrontendOptionAddSelect(TheText.Get("SCRFOR"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil); #endif -#ifdef MENU_MAP - FrontendOptionSetPosition(MENUPAGE_PAUSE_MENU, 2); - FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP); -#endif - #ifdef FREE_CAM static const wchar *text = (wchar*)L"TOGGLE FREE CAM"; FrontendOptionSetPosition(MENUPAGE_CONTROLLER_PC, 1); @@ -252,7 +248,7 @@ FixCar(void) } } -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS static void TeleportToWaypoint(void) { @@ -499,7 +495,7 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil); DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); -#ifdef MENU_MAP +#ifdef MAP_ENHANCEMENTS DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); #endif DebugMenuAddCmd("Debug", "Switch car collision", SwitchCarCollision); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index a3672186..3c3fd46a 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -11356,19 +11356,34 @@ CPed::ProcessControl(void) int vehAnim = m_pVehicleAnim->animId; + static bool cancelJack = false; int16 padWalkX = pad->GetPedWalkLeftRight(); int16 padWalkY = pad->GetPedWalkUpDown(); if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { if (vehAnim == ANIM_CAR_OPEN_LHS || vehAnim == ANIM_CAR_OPEN_RHS || vehAnim == ANIM_COACH_OPEN_L || vehAnim == ANIM_COACH_OPEN_R || vehAnim == ANIM_VAN_OPEN_L || vehAnim == ANIM_VAN_OPEN) { + + if (!m_pMyVehicle->pDriver) { + cancelJack = false; + bCancelEnteringCar = true; + } else + cancelJack = true; + } else if (vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) { + cancelJack = true; + } else if (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS) { bCancelEnteringCar = true; - } else if (vehAnim == ANIM_CAR_QJACK) { - if (m_pVehicleAnim->GetTimeLeft() > 0.69f && m_pVehicleAnim->GetTimeLeft() < 0.72f) { - QuitEnteringCar(); - RestorePreviousObjective(); - } + cancelJack = false; } } + if (cancelJack && vehAnim == ANIM_CAR_QJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) { + cancelJack = false; + QuitEnteringCar(); + RestorePreviousObjective(); + } + if (cancelJack && (vehAnim == ANIM_CAR_PULLOUT_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_LHS || vehAnim == ANIM_CAR_PULLOUT_LOW_RHS || vehAnim == ANIM_CAR_PULLOUT_RHS)) { + cancelJack = false; + bCancelEnteringCar = true; + } #endif break; } @@ -12163,6 +12178,15 @@ CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) if (!ped->IsNotInWreckedVehicle()) return; +#ifdef CANCELLABLE_CAR_ENTER + if (ped->bCancelEnteringCar) { + ped->QuitEnteringCar(); + ped->RestorePreviousObjective(); + ped->bCancelEnteringCar = false; + return; + } +#endif + bool isLow = !!veh->bLowVehicle; int padNo; From 70fa4ab79c331bd20b872ca4bc578248d5f42971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 6 Jul 2020 16:38:00 +0300 Subject: [PATCH 27/85] Frontend: Stats, Briefs, gta_vc.set, slider ranges, fixes --- src/core/Cam.cpp | 2 +- src/core/Camera.cpp | 4 +- src/core/ControllerConfig.cpp | 15 +- src/core/ControllerConfig.h | 1 + src/core/Frontend.cpp | 428 ++++++++++++++++++---------------- src/core/Frontend.h | 39 ++-- src/core/config.h | 1 - src/skel/glfw/glfw.cpp | 8 +- src/skel/win/win.cpp | 8 +- 9 files changed, 270 insertions(+), 236 deletions(-) diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index df36270a..3b11e16f 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -39,7 +39,7 @@ extern float fRangePlayerRadius; extern float fCloseNearClipLimit; #ifdef FREE_CAM -bool CCamera::bFreeCam; +bool CCamera::bFreeCam = false; int nPreviousMode = -1; #endif diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index d558e3ad..900c1b64 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -193,8 +193,8 @@ CCamera::Init(void) m_bMusicFading = false; m_fTimeToFadeMusic = 0.0f; m_fFLOATingFadeMusic = 0.0f; - m_fMouseAccelHorzntl = 0.003f; - m_fMouseAccelVertical = 0.0025f; + m_fMouseAccelVertical = 0.003f; + m_fMouseAccelHorzntl = 0.0025f; } if(FrontEndMenuManager.m_bWantToRestart) m_fTimeToFadeMusic = 0.0f; diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index c3e4e872..2febefdd 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -202,6 +202,8 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (GO_BACK, rsDOWN, KEYBOARD); SetControllerKeyAssociatedWithAction (GO_BACK, 'S', OPTIONAL_EXTRA); + + SetControllerKeyAssociatedWithAction (NETWORK_TALK, 'T', KEYBOARD); SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsPADEND, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_LOOKBEHIND, rsCAPSLK, OPTIONAL_EXTRA); @@ -436,6 +438,7 @@ void CControllerConfigManager::InitialiseControllerActionNameArray() SETACTIONNAME(PED_SPRINT); SETACTIONNAME(PED_CYCLE_TARGET_LEFT); SETACTIONNAME(PED_CYCLE_TARGET_RIGHT); + SETACTIONNAME(PED_LOCK_TARGET); // duplicate SETACTIONNAME(PED_CENTER_CAMERA_BEHIND_PLAYER); SETACTIONNAME(VEHICLE_LOOKBEHIND); SETACTIONNAME(PED_DUCK); @@ -1808,23 +1811,23 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio { switch (action) { - case CAMERA_CHANGE_VIEW_ALL_SITUATIONS: case PED_FIREWEAPON: case GO_LEFT: case GO_RIGHT: + case CAMERA_CHANGE_VIEW_ALL_SITUATIONS: case NETWORK_TALK: - case SWITCH_DEBUG_CAM_ON: case TOGGLE_DPAD: + case SWITCH_DEBUG_CAM_ON: case TAKE_SCREEN_SHOT: case SHOW_MOUSE_POINTER_TOGGLE: return ACTIONTYPE_COMMON; break; - case PED_LOOKBEHIND: - case PED_CYCLE_WEAPON_LEFT: case PED_CYCLE_WEAPON_RIGHT: + case PED_CYCLE_WEAPON_LEFT: case PED_JUMPING: case PED_SPRINT: + case PED_LOOKBEHIND: case PED_DUCK: case PED_ANSWER_PHONE: case PED_CYCLE_TARGET_LEFT: @@ -1853,13 +1856,13 @@ e_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerActio return ACTIONTYPE_VEHICLE_3RDPERSON; break; - case PED_LOCK_TARGET: case GO_FORWARD: case GO_BACK: case PED_1RST_PERSON_LOOK_LEFT: case PED_1RST_PERSON_LOOK_RIGHT: - case PED_1RST_PERSON_LOOK_DOWN: + case PED_LOCK_TARGET: case PED_1RST_PERSON_LOOK_UP: + case PED_1RST_PERSON_LOOK_DOWN: return ACTIONTYPE_1RST3RDPERSON; break; diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 5f0b6862..05c37c22 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -61,6 +61,7 @@ enum e_ControllerAction SWITCH_DEBUG_CAM_ON, TAKE_SCREEN_SHOT, SHOW_MOUSE_POINTER_TOGGLE, + UNKNOWN_ACTION, MAX_CONTROLLERACTIONS, }; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index f6845920..80e3fbc8 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -55,6 +55,7 @@ CRGBA HEADER_COLOR(255, 150, 255, 255); CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255); CRGBA SLIDERON_COLOR(97, 194, 247, 255); CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); +CRGBA LIST_BACKGROUND_COLOR(49, 101, 148, 255); #define TIDY_UP_PBP // ProcessButtonPresses #define MAX_VISIBLE_LIST_ROW 30 @@ -68,11 +69,7 @@ CRGBA SLIDEROFF_COLOR(27, 89, 130, 255); #define FEET_IN_METER 3.33f #endif -#ifdef SCROLLABLE_STATS_PAGE -#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS) -#else #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) -#endif #ifdef TRIANGLE_BACK_BUTTON #define GetBackJustUp GetTriangleJustUp @@ -97,8 +94,6 @@ int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #endif -uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings - // Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) #ifdef PS2_LIKE_MENU const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); @@ -391,7 +386,7 @@ CMenuManager::CMenuManager() m_PrefsSfxVolume = 49; m_PrefsMusicVolume = 49; m_PrefsRadioStation = 0; - field_2C = 1; + m_PrefsStereoMono = 1; m_PrefsBrightness = 256; m_PrefsLOD = 1.2f; m_KeyPressedCode = -1; @@ -634,31 +629,31 @@ CMenuManager::CheckSliderMovement(int value) { switch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) { case MENUACTION_BRIGHTNESS: - m_PrefsBrightness += value * (512/16); - m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 511); + m_PrefsBrightness += value * 24.19f; + m_PrefsBrightness = clamp(m_PrefsBrightness, 0, 384); break; case MENUACTION_DRAWDIST: if(value > 0) - m_PrefsLOD += ((1.8f - 0.8f) / 16.0f); + m_PrefsLOD += ((1.8f - 0.925f) / 16.0f); else - m_PrefsLOD -= ((1.8f - 0.8f) / 16.0f); - m_PrefsLOD = clamp(m_PrefsLOD, 0.8f, 1.8f); + m_PrefsLOD -= ((1.8f - 0.925f) / 16.0f); + m_PrefsLOD = clamp(m_PrefsLOD, 0.925f, 1.8f); CRenderer::ms_lodDistScale = m_PrefsLOD; break; case MENUACTION_MUSICVOLUME: - m_PrefsMusicVolume += value * (128/16); - m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 127); + m_PrefsMusicVolume += value * (128/32); + m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 65); + printf("%d\n", m_PrefsMusicVolume); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: - m_PrefsSfxVolume += value * (128/16); - m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 127); + m_PrefsSfxVolume += value * (128/32); + m_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 65); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); break; case MENUACTION_MOUSESENS: TheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f; // ??? TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; break; default: return; @@ -666,6 +661,7 @@ CMenuManager::CheckSliderMovement(int value) SaveSettings(); } +// --MIAMI: Done void CMenuManager::DisplayHelperText(char *text) { @@ -798,10 +794,10 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR void CMenuManager::DoSettingsBeforeStartingAGame() { - CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) m_PrefsVsync = m_PrefsVsyncDisp; - +#endif DMAudio.DestroyAllGameCreatedEntities(); DMAudio.Service(); m_bShutDownFrontEndRequested = true; @@ -838,7 +834,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(38.0f), MENU_Y(85.0f), MENU_X_LEFT_ALIGNED(615.0f), MENU_Y(75.0f), MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(320.0f), - MENU_X_LEFT_ALIGNED(605.0f), MENU_Y(330.0f), CRGBA(49, 101, 148, FadeIn(130))); + MENU_X_LEFT_ALIGNED(605.0f), MENU_Y(330.0f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(130))); break; /* // TODO(Miami) @@ -859,10 +855,10 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) PREPARE_MENU_HEADER CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); } // Label @@ -1078,6 +1074,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) break; case MENUACTION_HUD: rightText = TheText.Get(m_PrefsShowHud ? "FEM_ON" : "FEM_OFF"); + break; #ifdef LEGACY_MENU_OPTIONS case MENUACTION_SETDBGFLAG: rightText = TheText.Get(CTheScripts::IsDebugOn() ? "FEM_ON" : "FEM_OFF"); @@ -1181,16 +1178,20 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) if (drawCurrScreen && i == m_nCurrOption && itemsAreSelectable && section == 0) { int leftXMax, rightXMin; - CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + + // FIX: Let's don't scale those so GetStringWidth will give unscaled width, which will be handy to other calculations below that's done without scaling in mind. + // CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE)); + CFont::SetScale(BIGTEXT_X_SCALE, BIGTEXT_Y_SCALE); + wchar *curOptionName = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName); float curOptionWidth = CFont::GetStringWidth(curOptionName, true); if (CFont::Details.centre) { leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth / 2.f); - rightXMin = Min(SCREEN_WIDTH, curOptionWidth / 2.f + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth / 2.f + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); } else if (!CFont::Details.rightJustify) { leftXMax = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; - rightXMin = Min(SCREEN_WIDTH, curOptionWidth + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); + rightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X); } else { leftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth); rightXMin = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X; @@ -1850,25 +1851,25 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_UNK_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENU_UNK_WIDTH)); - PREPARE_MENU_HEADER - switch (m_ControlMethod) { case CONTROL_STANDARD: + PREPARE_MENU_HEADER CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); break; case CONTROL_CLASSIC: + PREPARE_MENU_HEADER CFont::SetColor(CRGBA(30, 30, 30, FadeIn(255))); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X + 7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get("FET_CTI")); - PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), + CFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255))); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get("FET_CTI")); break; default: @@ -2485,9 +2486,9 @@ CMenuManager::DrawBackground(bool transitionCall) if (m_nCurrScreen != MENUPAGE_OUTRO) if (m_menuTransitionProgress == 255) { - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255)); } else { - m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(27.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); + m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255))); } if (m_ShowEmptyBindingError) { @@ -2532,7 +2533,7 @@ CMenuManager::DrawPlayerSetupScreen() PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); + CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -2935,7 +2936,7 @@ CMenuManager::FadeIn(int alpha) } void -CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) +CMenuManager::FilterOutColorMarkersFromString(wchar *str) { int newIdx = 0; wchar copy[256], *c; @@ -2944,16 +2945,6 @@ CMenuManager::FilterOutColorMarkersFromString(wchar *str, CRGBA &newColor) for (c = copy; *c != '\0'; c++) { if (*c == '~') { c++; - switch (*c) { - case 'b': newColor = CRGBA(40, 40, 255, 255); break; - case 'g': newColor = CRGBA(40, 235, 40, 255); break; - // There is no case for "h", is that a mistake? - case 'l': newColor = CRGBA(0, 0, 0, 255); break; - case 'p': newColor = CRGBA(255, 0, 255, 255); break; - case 'r': newColor = CRGBA(255, 0, 0, 255); break; - case 'w': newColor = CRGBA(255, 255, 255, 255); break; - case 'y': newColor = CRGBA(255, 255, 0, 255); break; - } while (*c != '~') c++; } else { str[newIdx++] = *c; @@ -3094,28 +3085,32 @@ CMenuManager::LoadAllTextures() CTimer::Update(); } +// --MIAMI: Done void CMenuManager::LoadSettings() { CFileMgr::SetDirMyDocuments(); - int fileHandle = CFileMgr::OpenFile("gta3.set", "r"); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "r"); int32 prevLang = m_PrefsLanguage; -#ifdef GTA3_1_1_PATCH - CMBlur::BlurOn = (_dwOperatingSystemVersion != OS_WIN98); -#else - CMBlur::BlurOn = true; -#endif MousePointerStateHelper.bInvertVertically = true; + CMBlur::BlurOn = false; // 50 is silly - char Ver[50]; + char headerText[50]; + int someVersion = 0; + bool fileIsValid = true; if (fileHandle) { - CFileMgr::Read(fileHandle, Ver, 29); + CFileMgr::Read(fileHandle, headerText, 29); - if (strncmp(Ver, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1)) { + if (strncmp(headerText, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1) == 0) { + fileIsValid = false; + } else { CFileMgr::Seek(fileHandle, 0, 0); + CFileMgr::Read(fileHandle, (char*)&someVersion, sizeof(someVersion)); + } + if (fileIsValid && someVersion >= 3) { ControlsManager.LoadSettings(fileHandle); #ifdef IMPROVED_VIDEOMODE CFileMgr::Read(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); @@ -3139,41 +3134,52 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, gString, 20); CFileMgr::Read(fileHandle, gString, 4); CFileMgr::Read(fileHandle, gString, 4); +#ifdef FREE_CAM + CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#else + CFileMgr::Read(fileHandle, gString, 1); +#endif + +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else CFileMgr::Read(fileHandle, gString, 1); CFileMgr::Read(fileHandle, gString, 1); - CFileMgr::Read(fileHandle, gString, 1); +#endif CFileMgr::Read(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); CFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); - CFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelVertical, 4); CFileMgr::Read(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); CFileMgr::Read(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsSfxVolume, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsRadioStation, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsSpeakers, 1); CFileMgr::Read(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsDMA, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, 4); + CFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 2); + CFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); CFileMgr::Read(fileHandle, (char*)&m_PrefsShowSubtitles, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsUseWideScreen, 1); - CFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsFrameLimiter, 1); CFileMgr::Read(fileHandle, (char*)&m_nDisplayVideoMode, 1); - CFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1); CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); -#ifdef FREE_CAM - CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Read(fileHandle, (char*)&m_PrefsShowLegends, 1); } } CFileMgr::CloseFile(fileHandle); CFileMgr::SetDir(""); + CCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD; +#ifdef LEGACY_MENU_OPTIONS m_PrefsVsync = m_PrefsVsyncDisp; +#endif CRenderer::ms_lodDistScale = m_PrefsLOD; if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) @@ -3212,15 +3218,18 @@ CMenuManager::LoadSettings() } } +// --MIAMI: Done void CMenuManager::SaveSettings() { static char RubbishString[48] = "stuffmorestuffevenmorestuff etc"; + static int SomeVersion = 3; CFileMgr::SetDirMyDocuments(); - int fileHandle = CFileMgr::OpenFile("gta3.set", "w+"); + int fileHandle = CFileMgr::OpenFile("gta_vc.set", "w+"); if (fileHandle) { + CFileMgr::Write(fileHandle, (char*)&SomeVersion, sizeof(SomeVersion)); ControlsManager.SaveSettings(fileHandle); #ifdef IMPROVED_VIDEOMODE CFileMgr::Write(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth)); @@ -3234,34 +3243,42 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, RubbishString, 20); CFileMgr::Write(fileHandle, RubbishString, 4); CFileMgr::Write(fileHandle, RubbishString, 4); +#ifdef FREE_CAM + CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#else + CFileMgr::Write(fileHandle, RubbishString, 1); +#endif + +#ifdef LEGACY_MENU_OPTIONS + CFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1); + CFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1); +#else CFileMgr::Write(fileHandle, RubbishString, 1); CFileMgr::Write(fileHandle, RubbishString, 1); - CFileMgr::Write(fileHandle, RubbishString, 1); +#endif CFileMgr::Write(fileHandle, (char*)&TheCamera.m_bHeadBob, 1); CFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4); - CFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelVertical, 4); CFileMgr::Write(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1); CFileMgr::Write(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsSfxVolume, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsMusicVolume, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsRadioStation, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsSpeakers, 1); CFileMgr::Write(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsDMA, 1); - CFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 2); CFileMgr::Write(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD)); CFileMgr::Write(fileHandle, (char*)&m_PrefsShowSubtitles, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsUseWideScreen, 1); - CFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsFrameLimiter, 1); CFileMgr::Write(fileHandle, (char*)&m_nPrefsVideoMode, 1); - CFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1); CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); -#ifdef FREE_CAM - CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); -#endif + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowHud, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsRadarMode, 1); + CFileMgr::Write(fileHandle, (char*)&m_PrefsShowLegends, 1); } m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; @@ -3318,17 +3335,22 @@ CMenuManager::SmallMessageScreen(const char* text) CFont::PrintString(SCREEN_WIDTH / 2.f, y, TheText.Get(text)); } +// --MIAMI: Done, but FilterOutColorMarkersFromString is actually in CFont void CMenuManager::PrintBriefs() { - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); - CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); CFont::SetRightJustifyOff(); - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE)); + CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(80.0f)); + CFont::SetDropShadowPosition(0); - float nextY = BRIEFS_TOP_MARGIN; - CRGBA newColor; + float nextY = BRIEFS_BOTTOM_MARGIN; for (int i = 4; i >= 0; i--) { + if (nextY < BRIEFS_TOP_MARGIN) + break; + tPreviousBrief &brief = CMessages::PreviousBriefs[i]; if (brief.m_pText) { CMessages::InsertNumberInString(brief.m_pText, @@ -3337,127 +3359,125 @@ CMenuManager::PrintBriefs() brief.m_nNumber[4], brief.m_nNumber[5], gUString); CMessages::InsertStringInString(gUString, brief.m_pString); CMessages::InsertPlayerControlKeysInString(gUString); - newColor = TEXT_COLOR; - FilterOutColorMarkersFromString(gUString, newColor); + FilterOutColorMarkersFromString(gUString); -#ifdef PS2_LIKE_MENU - // This PS2 code was always here, but unused - bool rgSame = newColor.r == TEXT_COLOR.r && newColor.g == TEXT_COLOR.g; - bool bSame = rgSame && newColor.b == TEXT_COLOR.b; - bool colorNotChanged = bSame; /* && newColor.a == TEXT_COLOR.a; */ - - if (!colorNotChanged) { - newColor.r /= 2; - newColor.g /= 2; - newColor.b /= 2; - } - CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // But this is from PS2 - CFont::SetDropShadowPosition(1); -#endif - -#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU) - newColor.a = FadeIn(255); - CFont::SetColor(newColor); -#endif - CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString); - nextY += MENU_Y(BRIEFS_LINE_HEIGHT); + nextY -= CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString) * BRIEFS_LINE_HEIGHT + BRIEFS_LINE_SPACING; + CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), MENU_Y(nextY), gUString); } } - -#ifdef PS2_LIKE_MENU - CFont::SetDropShadowPosition(0); -#endif } +// --MIAMI: Done void CMenuManager::PrintStats() { - int rowNum = ConstructStatLine(99999); -#ifdef GTA3_1_1_PATCH - CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); -#endif - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why - float nextYChange, y, alphaMult; - - // Scroll stats with mouse -#ifdef SCROLLABLE_STATS_PAGE + static uint8 pirateCheck = 0; static float scrollY = 0; - static PauseModeTime lastChange = m_LastScreenSwitch; - if (CPad::GetPad(0)->GetLeftMouse()) { - scrollY += (m_nMouseOldPosY - m_nMousePosY); - lastChange = CTimer::GetTimeInMillisecondsPauseMode(); - } else { - scrollY += MENU_Y(STATS_SLIDE_Y_PER_SECOND) / 1000.0f * (CTimer::GetTimeInMillisecondsPauseMode() - lastChange); - lastChange = CTimer::GetTimeInMillisecondsPauseMode(); - } -#else - // MENU_Y(30.0f) per second - float scrollY = MENU_Y(STATS_SLIDE_Y_PER_SECOND) * (CTimer::GetTimeInMillisecondsPauseMode() - m_LastScreenSwitch) / 1000.0f; -#endif - for (int row = 0; row < rowNum; ++row) { - // Put just got hidden text at the top back to the bottom, in circular fashion - for (y = MENU_Y(STATS_ROW_HEIGHT - 1) * row + SCREEN_HEIGHT - scrollY; MENU_Y(STATS_PUT_BACK_TO_BOTTOM_Y) > y; y += nextYChange) { - nextYChange = (MENU_Y(STATS_ROW_HEIGHT) + rowNum) * MENU_Y(STATS_ROW_HEIGHT - 1); + int rowNum = ConstructStatLine(99999); + CSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(142.0f), + MENU_X_LEFT_ALIGNED(543.0f), MENU_Y(142.f), + MENU_X_LEFT_ALIGNED(107.0f), MENU_Y(316.f), + MENU_X_LEFT_ALIGNED(531.f), MENU_Y(299.f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(130))); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetPropOn(); + CFont::SetDropShadowPosition(0); + + if (pirateCheck == 0) + // if not pirated game + pirateCheck = 46; + // else + // pirateCheck = 45; + + if (m_PrefsLanguage == LANGUAGE_AMERICAN) + CFont::SetScale(MENU_X(0.43f), MENU_Y(0.75f)); + else + CFont::SetScale(MENU_X(0.37f), MENU_Y(0.75f)); + + static PauseModeTime lastCheck = 0; + + if (CTimer::GetTimeInMillisecondsPauseMode() - lastCheck > 40) { + + if (m_StatsScrollSpeed > 0.f) { + if (m_StatsScrollDirection == 0) + scrollY -= MENU_Y(100.f) / m_StatsScrollSpeed; + else + scrollY += MENU_Y(100.f) / m_StatsScrollSpeed; } + lastCheck = CTimer::GetTimeInMillisecondsPauseMode(); + } + + if (pirateCheck == 45) + return; + + float nextYChange, y, alpha; + + float totalHeight = (rowNum + 7) * STATS_ROW_HEIGHT; + for (int row = 0; row < rowNum; ++row) { + // Put faded away text at the top back to the bottom, in circular fashion + for (y = MENU_Y(STATS_ROW_HEIGHT) * row + MENU_Y(100.f) - scrollY; MENU_Y(STATS_FADING_AREA_LENGTH) > y; y += nextYChange) { + nextYChange = MENU_Y(totalHeight); + } + + // Put faded away text at the bottom back to the top + while (SCREEN_SCALE_FROM_BOTTOM(STATS_FADING_AREA_LENGTH) < y) { + y -= MENU_Y(totalHeight); + } + alpha = 0.f; // If it's still on screen - if (y > 0.0f && SCREEN_HEIGHT > y) { + if (y > MENU_Y(STATS_VISIBLE_START_Y) && y < MENU_Y(STATS_VISIBLE_END_Y)) { ConstructStatLine(row); - // But about to dim from top - if (y - MENU_Y(STATS_BOTTOM_MARGIN) < MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH)) { - if ((y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) - alphaMult = 0.0f; - else - alphaMult = (y - MENU_Y(STATS_BOTTOM_MARGIN)) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); + // But about to dim from bottom + if (y < MENU_Y(STATS_BOTTOM_Y)) { + if (y > MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = (MENU_Y(STATS_BOTTOM_Y) - y) * 5.f; + } - // About to dim from bottom - } else if (y > SCREEN_SCALE_FROM_BOTTOM(STATS_TOP_DIMMING_AREA_LENGTH) - MENU_Y(STATS_BOTTOM_DIMMING_AREA_LENGTH)) { - if ((SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH) < 0.0f) - alphaMult = 0.0f; - else - alphaMult = (SCREEN_SCALE_FROM_BOTTOM(STATS_BOTTOM_DIMMING_AREA_LENGTH) - y) / MENU_Y(STATS_TOP_DIMMING_AREA_LENGTH); - } else - alphaMult = 1.0f; + // About to dim from top + if (y > MENU_Y(STATS_TOP_Y)) { + if (y < MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH)) + alpha = (y - MENU_Y(STATS_TOP_Y)) * 5.f; + } - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255.0f * alphaMult))); + // Content + if (y >= MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH) && y <= MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH)) + alpha = 255.0f; + + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(Min(255.f, alpha)))); CFont::SetRightJustifyOff(); - CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_X_MARGIN), y - MENU_Y(STATS_BOTTOM_MARGIN - STATS_TOP_MARGIN), gUString); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_LEFT_MARGIN), y, gUString); CFont::SetRightJustifyOn(); - CFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_X_MARGIN), y - MENU_Y(STATS_BOTTOM_MARGIN - STATS_TOP_MARGIN), gUString2); + CFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_RIGHT_MARGIN), y, gUString2); } } - // Game doesn't do that, but it's better - float nextX = MENU_X_LEFT_ALIGNED(STATS_RATING_X); + CFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255))); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetCentreOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(MENU_X(0.65f), MENU_Y(1.05f)); + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X), MENU_Y(STATS_RATING_Y_1), TheText.Get("CRIMRA")); - CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetCentreOff(); CFont::SetRightJustifyOff(); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), TheText.Get("CRIMRA")); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - nextX += MENU_X(10.0f) + CFont::GetStringWidth_Jap(TheText.Get("CRIMRA")); - else -#endif - nextX += MENU_X(10.0f) + CFont::GetStringWidth(TheText.Get("CRIMRA"), true); - UnicodeStrcpy(gUString, CStats::FindCriminalRatingString()); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), gUString); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - nextX += MENU_X(6.0f) + CFont::GetStringWidth_Jap(gUString); - else -#endif - nextX += MENU_X(6.0f) + CFont::GetStringWidth(gUString, true); - sprintf(gString, "%d", CStats::FindCriminalRatingNumber()); - AsciiToUnicode(gString, gUString); - CFont::PrintString(nextX, MENU_Y(STATS_RATING_Y), gUString); - // ::Draw already does that. - /* - PREPARE_MENU_HEADER - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); - */ - CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); + // FIX: Game does that in a weird way, alignment and spacing is now ok + + sprintf(gString, "(%d)", CStats::FindCriminalRatingNumber()); + AsciiToUnicode(gString, gUString); + + UnicodeStrcpy(gUString2, CStats::FindCriminalRatingString()); + UnicodeStrcat(gUString2, gUString); + + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetScale(MENU_X(0.5f), MENU_Y(0.9f)); + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); + CFont::SetDropShadowPosition(0); + + CFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X) - CFont::GetStringWidth(gUString2, true) / 2.f, MENU_Y(STATS_RATING_Y_2), gUString2); } // --MIAMI: Done @@ -4083,13 +4103,11 @@ CMenuManager::ProcessButtonPresses(void) case HOVEROPTION_INCREASE_MOUSESENS: TheCamera.m_fMouseAccelHorzntl += (1.0f / 3000); TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; case HOVEROPTION_DECREASE_MOUSESENS: TheCamera.m_fMouseAccelHorzntl -= (1.0f / 3000); TheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f / 3200, 1.0f / 200); - TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl; SaveSettings(); break; } @@ -4416,9 +4434,11 @@ CMenuManager::ProcessButtonPresses(void) SwitchToNewScreen(MENUPAGE_OUTRO); break; case MENUACTION_RESUME: +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) { m_PrefsVsync = m_PrefsVsyncDisp; } +#endif RequestFrontEndShutDown(); break; case MENUACTION_DONTCANCEL: @@ -4480,42 +4500,41 @@ CMenuManager::ProcessButtonPresses(void) break; case MENUACTION_RESTOREDEF: if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - m_PrefsSfxVolume = 102; + m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); + DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); + m_PrefsSfxVolume = 49; + m_PrefsMusicVolume = 49; + m_PrefsRadioStation = EMOTION; + m_PrefsMP3BoostVolume = 0; + m_PrefsStereoMono = 1; m_PrefsSpeakers = 0; - m_PrefsMusicVolume = 102; - m_PrefsStereoMono = 0; - m_PrefsRadioStation = WILDSTYLE; - DMAudio.SetMusicMasterVolume(102); + // DMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume); // TODO(Miami) + DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); DMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume); DMAudio.SetRadioInCar(m_PrefsRadioStation); DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); SaveSettings(); } else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) { - m_PrefsFrameLimiter = true; m_PrefsBrightness = 256; - m_PrefsVsyncDisp = true; m_PrefsLOD = 1.2f; +#ifdef LEGACY_MENU_OPTIONS m_PrefsVsync = true; - CRenderer::ms_lodDistScale = 1.2f; - m_PrefsUseWideScreen = false; - m_PrefsShowSubtitles = true; - m_nDisplayVideoMode = m_nPrefsVideoMode; -#ifdef GTA3_1_1_PATCH - if (_dwOperatingSystemVersion == OS_WIN98) { - CMBlur::BlurOn = false; - CMBlur::MotionBlurClose(); - } - else { - CMBlur::BlurOn = true; - CMBlur::MotionBlurOpen(Scene.camera); - } -#else - CMBlur::BlurOn = true; #endif + CRenderer::ms_lodDistScale = m_PrefsLOD; + m_PrefsShowSubtitles = false; + m_PrefsUseWideScreen = false; + m_PrefsShowLegends = true; + m_PrefsVsyncDisp = true; + m_PrefsFrameLimiter = true; + m_PrefsRadarMode = 0; + m_PrefsShowHud = true; + m_nDisplayVideoMode = m_nPrefsVideoMode; + CMBlur::BlurOn = false; SaveSettings(); } else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) { ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); + MousePointerStateHelper.GetMouseSetUp(); ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); #if !defined RW_GL3 if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { @@ -4531,11 +4550,12 @@ CMenuManager::ProcessButtonPresses(void) ControlsManager.InitDefaultControlConfigJoyPad(count); } #endif - m_ControlMethod = CONTROL_STANDARD; - MousePointerStateHelper.bInvertVertically = false; + MousePointerStateHelper.bInvertVertically = true; + TheCamera.m_bHeadBob = false; TheCamera.m_fMouseAccelHorzntl = 0.0025f; CVehicle::m_bDisableMouseSteering = true; - TheCamera.m_bHeadBob = false; + m_ControlMethod = CONTROL_STANDARD; + TheCamera.m_bUseMouse3rdPerson = true; SaveSettings(); } SetHelperText(2); @@ -4583,9 +4603,11 @@ CMenuManager::ProcessButtonPresses(void) if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) { #endif if (!m_bGameNotLoaded) { +#ifdef LEGACY_MENU_OPTIONS if (m_PrefsVsyncDisp != m_PrefsVsync) { m_PrefsVsync = m_PrefsVsyncDisp; } +#endif RequestFrontEndShutDown(); } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 577e36db..48f62dbc 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -66,20 +66,23 @@ #define PLAYERSETUP_LIST_BODY_TOP 47 #define PLAYERSETUP_ROW_HEIGHT 9 -#define STATS_SLIDE_Y_PER_SECOND 30.0f -#define STATS_ROW_HEIGHT 20.0f -#define STATS_ROW_X_MARGIN 50.0f -#define STATS_BOTTOM_MARGIN 135.0f -#define STATS_TOP_MARGIN 40.0f -#define STATS_TOP_DIMMING_AREA_LENGTH (93.0f - STATS_TOP_MARGIN) -#define STATS_BOTTOM_DIMMING_AREA_LENGTH 55.0f -#define STATS_PUT_BACK_TO_BOTTOM_Y 50.0f -#define STATS_RATING_X 24.0f -#define STATS_RATING_Y 20.0f +#define STATS_ROW_HEIGHT 17.0f +#define STATS_ROW_LEFT_MARGIN 110.0f +#define STATS_ROW_RIGHT_MARGIN 113.0f +#define STATS_TOP_Y 135.0f // Just faded in +#define STATS_BOTTOM_Y 300.0f // Starts to fade out after that +#define STATS_FADING_AREA_LENGTH 50.0f +#define STATS_VISIBLE_START_Y (STATS_TOP_Y - 10.f) +#define STATS_VISIBLE_END_Y (STATS_BOTTOM_Y + 21.f) +#define STATS_RATING_X 320.0f +#define STATS_RATING_Y_1 85.0f +#define STATS_RATING_Y_2 110.0f -#define BRIEFS_TOP_MARGIN 40.0f -#define BRIEFS_LINE_X 50.0f -#define BRIEFS_LINE_HEIGHT 60.0f +#define BRIEFS_TOP_MARGIN 140.0f +#define BRIEFS_BOTTOM_MARGIN 280.0f +#define BRIEFS_LINE_X 100.0f +#define BRIEFS_LINE_HEIGHT 20.0f +#define BRIEFS_LINE_SPACING 10.0f #define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f #define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f @@ -477,10 +480,10 @@ public: int8 m_nPrefsAudio3DProviderIndex; int8 m_PrefsSpeakers; int8 m_PrefsDMA; - uint8 m_PrefsSfxVolume; - uint8 m_PrefsMusicVolume; + int8 m_PrefsSfxVolume; + int8 m_PrefsMusicVolume; uint8 m_PrefsRadioStation; - uint8 field_2C; + uint8 m_PrefsStereoMono; // unused except restore settings int32 m_nCurrOption; bool m_bQuitGameNoCD; bool m_bMenuMapActive; @@ -595,8 +598,6 @@ public: }; bool GetIsMenuActive() {return !!m_bMenuActive;} - static uint8 m_PrefsStereoMono; - #ifndef MASTER static bool m_PrefsMarketing; static bool m_PrefsDisableTutorials; @@ -625,7 +626,7 @@ public: void DrawBackground(bool transitionCall); void DrawPlayerSetupScreen(); int FadeIn(int alpha); - void FilterOutColorMarkersFromString(wchar*, CRGBA &); + void FilterOutColorMarkersFromString(wchar*); int GetStartOptionsCntrlConfigScreens(); void InitialiseChangedLanguageSettings(); void LoadAllTextures(); diff --git a/src/core/config.h b/src/core/config.h index 798e6bb2..5ee9d918 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -243,7 +243,6 @@ enum Config { #else //# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc. # define MAP_ENHANCEMENTS // Adding waypoint etc. -# define SCROLLABLE_STATS_PAGE // only draggable by mouse atm # define TRIANGLE_BACK_BUTTON //# define CIRCLE_BACK_BUTTON //#define CUSTOM_FRONTEND_OPTIONS diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 5a2d2667..d01e05b5 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -178,7 +178,11 @@ psCameraBeginUpdate(RwCamera *camera) void psCameraShowRaster(RwCamera *camera) { - if (FrontEndMenuManager.m_PrefsVsync) +#ifdef LEGACY_MENU_OPTIONS + if (FrontEndMenuManager.m_PrefsVsync || FrontEndMenuManager.m_bMenuActive) +#else + if (FrontEndMenuManager.m_PrefsFrameLimiter || FrontEndMenuManager.m_bMenuActive) +#endif RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC); else RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT); @@ -1488,7 +1492,7 @@ main(int argc, char *argv[]) { CFileMgr::SetDirMyDocuments(); - int32 gta3set = CFileMgr::OpenFile("gta3.set", "r"); + int32 gta3set = CFileMgr::OpenFile("gta_vc.set", "r"); if ( gta3set ) { diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 77475ca5..e70a1054 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -223,7 +223,11 @@ psCameraBeginUpdate(RwCamera *camera) void psCameraShowRaster(RwCamera *camera) { - if (FrontEndMenuManager.m_PrefsVsync) +#ifdef LEGACY_MENU_OPTIONS + if (FrontEndMenuManager.m_PrefsVsync || FrontEndMenuManager.m_bMenuActive) +#else + if (FrontEndMenuManager.m_PrefsFrameLimiter || FrontEndMenuManager.m_bMenuActive) +#endif RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC); else RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT); @@ -2073,7 +2077,7 @@ WinMain(HINSTANCE instance, { CFileMgr::SetDirMyDocuments(); - int32 gta3set = CFileMgr::OpenFile("gta3.set", "r"); + int32 gta3set = CFileMgr::OpenFile("gta_vc.set", "r"); if ( gta3set ) { From c483a044b587691f70fd7e8cb5348c59a8509d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 6 Jul 2020 19:26:06 +0300 Subject: [PATCH 28/85] Noskillx's PR + fix .set loading --- src/audio/DMAudio.cpp | 66 +++++++++++++++++++++++++++++------ src/audio/DMAudio.h | 3 ++ src/control/Garages.cpp | 1 + src/control/Pickups.cpp | 4 +-- src/core/ControllerConfig.cpp | 7 ++-- src/core/Frontend.cpp | 48 ++++++++++--------------- src/core/Game.cpp | 11 +++--- src/core/MenuScreens.h | 2 +- src/core/Stats.cpp | 20 ----------- src/core/Stats.h | 4 --- 10 files changed, 90 insertions(+), 76 deletions(-) diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 7581114d..6859cba3 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -112,25 +112,69 @@ cDMAudio::Get3DProviderName(uint8 id) return AudioManager.Get3DProviderName(id); } +// TODO(Miami): Content of this moved to cSampleManager or cAudioManager int8 cDMAudio::AutoDetect3DProviders(void) { + if (!AudioManager.IsAudioInitialised()) + return -1; + + int eax = -1, eax2 = -1, eax3 = -1, ds3dh = -1, ds3ds = -1; + for ( int32 i = 0; i < GetNum3DProvidersAvailable(); i++ ) { - wchar buff[64]; - - char *name = Get3DProviderName(i); - AsciiToUnicode(name, buff); - char *providername = UnicodeToAscii(buff); + char *providername = Get3DProviderName(i); strupr(providername); -#if defined(AUDIO_MSS) - if ( !strcmp(providername, "MILES FAST 2D POSITIONAL AUDIO") ) - return i; -#elif defined(AUDIO_OAL) - if ( !strcmp(providername, "OPENAL SOFT") ) - return i; + +#if defined(AUDIO_OAL) + if (!strcmp(providername, "OPENAL SOFT")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) + return i; + } +#else + if (!strcmp(providername, "CREATIVE LABS EAX 3 (TM)")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) { + eax3 = i; + } + } + + if (!strcmp(providername, "CREATIVE LABS EAX 2 (TM)")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) + eax2 = i; + } + + if (!strcmp(providername, "CREATIVE LABS EAX (TM)")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) + eax = i; + } + + if (!strcmp(providername, "DIRECTSOUND3D HARDWARE SUPPORT")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) + ds3dh = i; + } + + if (!strcmp(providername, "DIRECTSOUND3D SOFTWARE EMULATION")) { + SetCurrent3DProvider(i); + if (GetCurrent3DProviderIndex() == i) + ds3ds = i; + } #endif } + if (eax3 != -1) + return eax3; + if (eax2 != -1) + return eax2; + if (eax != -1) + return eax; + if (ds3dh != -1) + return ds3dh; + if (ds3ds != -1) + return ds3ds; return -1; } diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index bb1454c9..e7d3a23b 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -7,6 +7,9 @@ #define AEHANDLE_IS_FAILED(h) ((h)<0) #define AEHANDLE_IS_OK(h) ((h)>=0) +#define NO_AUDIO_PROVIDER -3 +#define AUDIO_PROVIDER_NOT_DETERMINED -99 + class cAudioScriptObject; class CEntity; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 66f1851d..6b4ceb80 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1386,6 +1386,7 @@ bool CGarages::IsCarSprayable(CVehicle * pVehicle) case MI_BARRACKS: case MI_DODO: case MI_COACH: + case MI_FBIRANCH: return false; default: break; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 95abe2c5..6576be7f 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -269,12 +269,12 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) return true; case PICKUP_COLLECTABLE1: CWorld::Players[playerId].m_nCollectedPackages++; - CWorld::Players[playerId].m_nMoney += 1000; + CWorld::Players[playerId].m_nMoney += 100; if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) { printf("All collectables have been picked up\n"); CGarages::TriggerMessage("CO_ALL", -1, 5000, -1); - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000; + CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 100000; } else CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 2febefdd..d194cebb 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -131,6 +131,7 @@ void CControllerConfigManager::SaveSettings(int32 file) void CControllerConfigManager::LoadSettings(int32 file) { bool bValid = true; + int nVersion = 0; if (file) { @@ -139,11 +140,13 @@ void CControllerConfigManager::LoadSettings(int32 file) if (!strncmp(buff, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1)) bValid = false; - else + else { CFileMgr::Seek(file, 0, 0); + CFileMgr::Read(file, (char*)&nVersion, sizeof(nVersion)); + } } - if (bValid) + if (bValid && nVersion >= 3) { ControlsManager.MakeControllerActionsBlank(); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 80e3fbc8..ef8b3a15 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -41,9 +41,6 @@ // TODO(Miami): Remove that!! That was my map implementation for III, instead use MAP_ENHACEMENTS on some places #define CUSTOM_MAP -// TODO(Miami): This is -3 on VC but still -1 on AudioManager?!? What the hell? -#define INVALID_AUDIO_PROVIDER -1 - // Similar story to Hud.cpp: // Game has colors inlined in code. // For easier modification we collect them here: @@ -355,7 +352,7 @@ CMenuManager::ThingsToDoBeforeLeavingPage() if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile); } else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { - if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); #ifdef TIDY_UP_PBP DMAudio.StopFrontEndTrack(); @@ -388,7 +385,7 @@ CMenuManager::CMenuManager() m_PrefsRadioStation = 0; m_PrefsStereoMono = 1; m_PrefsBrightness = 256; - m_PrefsLOD = 1.2f; + m_PrefsLOD = CRenderer::ms_lodDistScale; m_KeyPressedCode = -1; m_bFrontEnd_ReloadObrTxtGxt = false; m_PrefsMP3BoostVolume = 0; @@ -421,7 +418,7 @@ CMenuManager::CMenuManager() m_nScrollbarTopMargin = 0.0f; m_nSelectedListRow = 0; m_nSkinsTotal = 0; - m_nPrefsAudio3DProviderIndex = -99; + m_nPrefsAudio3DProviderIndex = AUDIO_PROVIDER_NOT_DETERMINED; m_bGameNotLoaded = true; m_nMousePosX = m_nMouseTempPosX; m_nMousePosY = m_nMouseTempPosY; @@ -643,7 +640,6 @@ CMenuManager::CheckSliderMovement(int value) case MENUACTION_MUSICVOLUME: m_PrefsMusicVolume += value * (128/32); m_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 65); - printf("%d\n", m_PrefsMusicVolume); DMAudio.SetMusicMasterVolume(m_PrefsMusicVolume); break; case MENUACTION_SFXVOLUME: @@ -721,7 +717,7 @@ CMenuManager::DisplayHelperText(char *text) aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SFXVOLUME) { CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), - m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); return; } @@ -738,7 +734,7 @@ CMenuManager::DisplayHelperText(char *text) aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SPEAKERCONF) { CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), - m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); return; } @@ -747,7 +743,7 @@ CMenuManager::DisplayHelperText(char *text) if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MP3VOLUMEBOOST) { CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(10.f), SCREEN_SCALE_FROM_BOTTOM(18.f), - m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); + m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get("FEH_NA") : TheText.Get("FET_MIG")); return; } @@ -979,7 +975,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName); } - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) { + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) { if (strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEO_AUD", 8) == 0) { CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); } @@ -1045,7 +1041,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) case MENUACTION_MUSICVOLUME: case MENUACTION_SFXVOLUME: - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) rightText = TheText.Get("FEA_NAH"); break; @@ -1112,7 +1108,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) break; #endif case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) rightText = TheText.Get("FEA_NAH"); else if (m_nPrefsAudio3DProviderIndex == -1) rightText = TheText.Get("FEA_ADP"); @@ -1130,7 +1126,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) } break; case MENUACTION_SPEAKERCONF: { - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) rightText = TheText.Get("FEA_NAH"); else { switch (m_PrefsSpeakers) { @@ -1305,7 +1301,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) } if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) { if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0 - && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { + && m_nCurrScreen == MENUPAGE_SOUND_SETTINGS && m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex(); SetHelperText(3); @@ -1338,11 +1334,11 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, 99.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); break; case MENUACTION_MUSICVOLUME: - if(m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) + if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) ProcessSlider(m_PrefsMusicVolume / 64.0f, 70.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); break; case MENUACTION_SFXVOLUME: - if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) ProcessSlider(m_PrefsSfxVolume / 64.0f, 99.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, MENU_X_LEFT_ALIGNED(170.0f), SCREEN_WIDTH); break; case MENUACTION_MOUSESENS: @@ -1387,7 +1383,7 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) DisplayHelperText(nil); break; case MENUPAGE_OPTIONS: - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LOADRADIO) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LOADRADIO) DisplayHelperText("FEA_NAH"); break; } @@ -3182,7 +3178,7 @@ CMenuManager::LoadSettings() #endif CRenderer::ms_lodDistScale = m_PrefsLOD; - if (m_nPrefsAudio3DProviderIndex == INVALID_AUDIO_PROVIDER) + if (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) m_nPrefsAudio3DProviderIndex = -2; m_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex; @@ -4469,7 +4465,7 @@ CMenuManager::ProcessButtonPresses(void) case MENUACTION_AUDIOHW: { int selectedProvider = m_nPrefsAudio3DProviderIndex; - if (selectedProvider != INVALID_AUDIO_PROVIDER) { + if (selectedProvider != NO_AUDIO_PROVIDER) { if (selectedProvider == -1) selectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); m_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex); @@ -4482,7 +4478,7 @@ CMenuManager::ProcessButtonPresses(void) } case MENUACTION_SPEAKERCONF: #ifndef TIDY_UP_PBP - if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { if (--m_PrefsSpeakers < 0) m_PrefsSpeakers = 2; DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -4770,14 +4766,14 @@ CMenuManager::ProcessButtonPresses(void) break; #endif case MENUACTION_AUDIOHW: - if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { m_nPrefsAudio3DProviderIndex += changeValueBy; m_nPrefsAudio3DProviderIndex = clamp(m_nPrefsAudio3DProviderIndex, 0, DMAudio.GetNum3DProvidersAvailable() - 1); } DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); break; case MENUACTION_SPEAKERCONF: - if (m_nPrefsAudio3DProviderIndex != INVALID_AUDIO_PROVIDER) { + if (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) { m_PrefsSpeakers -= changeValueBy; m_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2); DMAudio.SetSpeakerConfig(m_PrefsSpeakers); @@ -5451,13 +5447,9 @@ CMenuManager::ConstructStatLine(int rowIdx) if (CStats::Record4x4Mayhem > 0) { STAT_LINE("FEST_RM", &CStats::Record4x4Mayhem, false, nil); } - if (CStats::LongestFlightInDodo > 0) { - STAT_LINE("FEST_LF", &CStats::LongestFlightInDodo, false, nil); - } if (CStats::TimeTakenDefuseMission > 0) { STAT_LINE("FEST_BD", &CStats::TimeTakenDefuseMission, false, nil); } - STAT_LINE("CAR_CRU", &CStats::CarsCrushed, false, nil); if (CStats::HighestScores[0] > 0) { STAT_LINE("FEST_BB", nil, false, nil); @@ -5485,7 +5477,6 @@ CMenuManager::ConstructStatLine(int rowIdx) float fTemp; STAT_LINE("FEST_DF", &(fTemp = CStats::DistanceTravelledOnFoot * MILES_IN_METER), true, nil); STAT_LINE("FEST_DC", &(fTemp = CStats::DistanceTravelledInVehicle * MILES_IN_METER), true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); STAT_LINE("MXCARD", &(fTemp = CStats::MaximumJumpDistance * FEET_IN_METER), true, nil); STAT_LINE("MXCARJ", &(fTemp = CStats::MaximumJumpHeight * FEET_IN_METER), true, nil); break; @@ -5501,7 +5492,6 @@ CMenuManager::ConstructStatLine(int rowIdx) #endif STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); STAT_LINE("FESTDCM", &CStats::DistanceTravelledInVehicle, true, nil); - STAT_LINE("MMRAIN", &CStats::mmRain, false, nil); STAT_LINE("MXCARDM", &CStats::MaximumJumpDistance, true, nil); STAT_LINE("MXCARJM", &CStats::MaximumJumpHeight, true, nil); break; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 9d8e4ce7..b21421b1 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -245,23 +245,20 @@ void CGame::ShutdownRenderWare(void) bool CGame::InitialiseOnceAfterRW(void) { TheText.Load(); - DMAudio.Initialise(); CTimer::Initialise(); CTempColModels::Initialise(); mod_HandlingManager.Initialise(); CSurfaceTable::Initialise("DATA\\SURFACE.DAT"); CPedStats::Initialise(); CTimeCycle::Initialise(); - + DMAudio.Initialise(); if ( DMAudio.GetNum3DProvidersAvailable() == 0 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1; + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = NO_AUDIO_PROVIDER; - if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -99 || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) + if ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == AUDIO_PROVIDER_NOT_DETERMINED || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 ) { FrontEndMenuManager.m_PrefsSpeakers = 0; - int8 provider = DMAudio.AutoDetect3DProviders(); - if ( provider != -1 ) - FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = provider; + FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders(); } DMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex); diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index a7e1796d..3f9631c8 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -4,7 +4,7 @@ CMenuScreen aScreens[] = { // MENUPAGE_STATS = 0 - { "FET_STA", MENUPAGE_NONE, 3, + { "FEH_STA", MENUPAGE_NONE, 3, MENUACTION_GOBACK, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT, }, diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index b8ea0943..6880fd99 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -49,7 +49,6 @@ int32 CStats::LivesSavedWithAmbulance; int32 CStats::CriminalsCaught; int32 CStats::HighestLevelAmbulanceMission; int32 CStats::FiresExtinguished; -int32 CStats::LongestFlightInDodo; int32 CStats::TimeTakenDefuseMission; int32 CStats::TotalNumberKillFrenzies; int32 CStats::TotalNumberMissions; @@ -58,8 +57,6 @@ int32 CStats::KgsOfExplosivesUsed; int32 CStats::InstantHitsFiredByPlayer; int32 CStats::InstantHitsHitByPlayer; int32 CStats::BestTimeBombDefusal; -int32 CStats::mmRain; -int32 CStats::CarsCrushed; int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; int32 CStats::BestPositions[CStats::TOTAL_BEST_POSITIONS]; @@ -83,13 +80,11 @@ void CStats::Init() KgsOfExplosivesUsed = 0; InstantHitsFiredByPlayer = 0; InstantHitsHitByPlayer = 0; - CarsCrushed = 0; HeadsPopped = 0; TimesArrested = 0; TimesDied = 0; DaysPassed = 0; NumberOfUniqueJumpsFound = 0; - mmRain = 0; MaximumJumpFlips = 0; MaximumJumpSpins = 0; MaximumJumpDistance = 0; @@ -97,7 +92,6 @@ void CStats::Init() BestStuntJump = 0; TotalNumberOfUniqueJumps = 0; Record4x4One = 0; - LongestFlightInDodo = 0; Record4x4Two = 0; PassengersDroppedOffWithTaxi = 0; Record4x4Three = 0; @@ -202,11 +196,6 @@ void CStats::AnotherFireExtinguished() ++FiresExtinguished; } -void CStats::RegisterLongestFlightInDodo(int32 time) -{ - LongestFlightInDodo = Max(LongestFlightInDodo, time); -} - void CStats::RegisterTimeTakenDefuseMission(int32 time) { TimeTakenDefuseMission = (TimeTakenDefuseMission && TimeTakenDefuseMission < time) ? TimeTakenDefuseMission : time; @@ -296,12 +285,10 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) sizeof(KgsOfExplosivesUsed) + sizeof(InstantHitsFiredByPlayer) + sizeof(InstantHitsHitByPlayer) + - sizeof(CarsCrushed) + sizeof(HeadsPopped) + sizeof(TimesArrested) + sizeof(TimesDied) + sizeof(DaysPassed) + - sizeof(mmRain) + sizeof(MaximumJumpDistance) + sizeof(MaximumJumpHeight) + sizeof(MaximumJumpFlips) + @@ -327,7 +314,6 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) sizeof(CriminalsCaught) + sizeof(HighestLevelAmbulanceMission) + sizeof(FiresExtinguished) + - sizeof(LongestFlightInDodo) + sizeof(TimeTakenDefuseMission) + sizeof(NumberKillFrenziesPassed) + sizeof(TotalNumberKillFrenzies) + @@ -351,12 +337,10 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) CopyToBuf(buf, KgsOfExplosivesUsed); CopyToBuf(buf, InstantHitsFiredByPlayer); CopyToBuf(buf, InstantHitsHitByPlayer); - CopyToBuf(buf, CarsCrushed); CopyToBuf(buf, HeadsPopped); CopyToBuf(buf, TimesArrested); CopyToBuf(buf, TimesDied); CopyToBuf(buf, DaysPassed); - CopyToBuf(buf, mmRain); CopyToBuf(buf, MaximumJumpDistance); CopyToBuf(buf, MaximumJumpHeight); CopyToBuf(buf, MaximumJumpFlips); @@ -382,7 +366,6 @@ void CStats::SaveStats(uint8 *buf, uint32 *size) CopyToBuf(buf, CriminalsCaught); CopyToBuf(buf, HighestLevelAmbulanceMission); CopyToBuf(buf, FiresExtinguished); - CopyToBuf(buf, LongestFlightInDodo); CopyToBuf(buf, TimeTakenDefuseMission); CopyToBuf(buf, NumberKillFrenziesPassed); CopyToBuf(buf, TotalNumberKillFrenzies); @@ -415,12 +398,10 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, KgsOfExplosivesUsed); CopyFromBuf(buf, InstantHitsFiredByPlayer); CopyFromBuf(buf, InstantHitsHitByPlayer); - CopyFromBuf(buf, CarsCrushed); CopyFromBuf(buf, HeadsPopped); CopyFromBuf(buf, TimesArrested); CopyFromBuf(buf, TimesDied); CopyFromBuf(buf, DaysPassed); - CopyFromBuf(buf, mmRain); CopyFromBuf(buf, MaximumJumpDistance); CopyFromBuf(buf, MaximumJumpHeight); CopyFromBuf(buf, MaximumJumpFlips); @@ -446,7 +427,6 @@ void CStats::LoadStats(uint8 *buf, uint32 size) CopyFromBuf(buf, CriminalsCaught); CopyFromBuf(buf, HighestLevelAmbulanceMission); CopyFromBuf(buf, FiresExtinguished); - CopyFromBuf(buf, LongestFlightInDodo); CopyFromBuf(buf, TimeTakenDefuseMission); CopyFromBuf(buf, NumberKillFrenziesPassed); CopyFromBuf(buf, TotalNumberKillFrenzies); diff --git a/src/core/Stats.h b/src/core/Stats.h index 8588fef1..8c786bb8 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -53,7 +53,6 @@ public: static int32 CriminalsCaught; static int32 HighestLevelAmbulanceMission; static int32 FiresExtinguished; - static int32 LongestFlightInDodo; static int32 TimeTakenDefuseMission; static int32 TotalNumberKillFrenzies; static int32 TotalNumberMissions; @@ -62,8 +61,6 @@ public: static int32 InstantHitsFiredByPlayer; static int32 InstantHitsHitByPlayer; static int32 BestTimeBombDefusal; - static int32 mmRain; - static int32 CarsCrushed; static int32 FastestTimes[TOTAL_FASTEST_TIMES]; static int32 HighestScores[TOTAL_HIGHEST_SCORES]; static int32 BestPositions[TOTAL_BEST_POSITIONS]; @@ -90,7 +87,6 @@ public: static void RegisterLevelAmbulanceMission(int32); static void AnotherFireExtinguished(); static wchar *FindCriminalRatingString(); - static void RegisterLongestFlightInDodo(int32); static void RegisterTimeTakenDefuseMission(int32); static void AnotherKillFrenzyPassed(); static void SetTotalNumberKillFrenzies(int32); From 478d4246c493a9d6210b30bd17ce35a363b0012d Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 7 Jul 2020 00:32:13 +0200 Subject: [PATCH 29/85] Miami Colors. Miami colors for MissionPassed/Failed, oddjob text 1 and 2 + fixed wrong busted/wasted color (it was pink and in the original its actually green) --- src/render/Hud.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index d4cea597..21d862af 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -38,10 +38,10 @@ CRGBA TIMER_COLOR(97, 194, 247, 255); CRGBA COUNTER_COLOR(97, 194, 247, 255); CRGBA PAGER_COLOR(32, 162, 66, 205); CRGBA RADARDISC_COLOR(255, 255, 255, 255); -CRGBA BIGMESSAGE_COLOR(85, 119, 133, 255); -CRGBA WASTEDBUSTED_COLOR(255, 150, 225, 255); -CRGBA ODDJOB_COLOR(89, 115, 150, 255); -CRGBA ODDJOB2_COLOR(156, 91, 40, 255); +CRGBA BIGMESSAGE_COLOR(255, 150, 225, 255); +CRGBA WASTEDBUSTED_COLOR(0, 207, 133, 255); +CRGBA ODDJOB_COLOR(0, 207, 133, 255); +CRGBA ODDJOB2_COLOR(97, 194, 247, 255); CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); wchar CHud::m_HelpMessage[256]; From fa1263b6a483011ec2b033dc8e80e444dc8d456e Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 7 Jul 2020 01:02:39 +0200 Subject: [PATCH 30/85] CDarkel miami hud colors. --- src/control/Darkel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index f00486e8..bbb35080 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -27,6 +27,7 @@ int32 CDarkel::KillsNeeded; int8 CDarkel::InterruptedWeapon; /* + * TODO: Collect timer/kill counter RGBA colors on top like in Hud/Frontend. * bStandardSoundAndMessages is a completely beta thing, * makes game handle sounds & messages instead of SCM (just like in GTA2) * but it's never been used in the game. Has unused sliding text when frenzy completed etc. @@ -102,7 +103,7 @@ CDarkel::DrawMessages() if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) { CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString); - CFont::SetColor(CRGBA(150, 100, 255, 255)); + CFont::SetColor(CRGBA(0, 207, 133, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString); } } @@ -110,7 +111,7 @@ CDarkel::DrawMessages() AsciiToUnicode(gString, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(144.0f), gUString); - CFont::SetColor(CRGBA(255, 128, 128, 255)); + CFont::SetColor(CRGBA(156, 91, 40, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(143.0f), gUString); break; } From 67a3c7d2ee2787b254099bf22a9c261146ce5eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 8 Jul 2020 17:26:23 +0300 Subject: [PATCH 31/85] VC fighting, Peds, many fixes including ghost bikes --- src/animation/AnimManager.cpp | 4 +- src/animation/AnimationId.h | 1 + src/audio/AudioLogic.cpp | 2 + src/audio/MusicManager.cpp | 12 +- src/control/CarAI.cpp | 8 +- src/control/CarCtrl.cpp | 6 +- src/control/RoadBlocks.cpp | 4 +- src/control/Script.cpp | 42 +- src/core/Radar.cpp | 3 +- src/core/Streaming.cpp | 6 +- src/peds/CopPed.cpp | 1 + src/peds/CopPed.h | 1 + src/peds/Ped.cpp | 1100 ++++++++++++++++++++------------- src/peds/Ped.h | 25 +- src/peds/PlayerPed.cpp | 2 + src/peds/Population.cpp | 57 +- src/render/Hud.cpp | 26 +- src/render/Hud.h | 1 + src/vehicles/Automobile.cpp | 4 +- src/vehicles/Cranes.cpp | 6 +- src/vehicles/Vehicle.cpp | 6 +- src/vehicles/Vehicle.h | 2 +- 22 files changed, 813 insertions(+), 506 deletions(-) diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 4694920a..f682964f 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -238,14 +238,14 @@ AnimAssocDesc aMeleeAnimDescs[] = { { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, { ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT }, - { ANIM_WEAPON_SPECIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, // TODO(Miami): Overload that name for melee/swing + { ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, }; AnimAssocDesc aSwingAnimDescs[] = { { ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT }, - { ANIM_WEAPON_SPECIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, // TODO(Miami): Overload that name for melee/swing + { ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, }; AnimAssocDesc aWeaponAnimDescs[] = { { ANIM_WEAPON_FIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h index ddf36b23..f2ef3dfd 100644 --- a/src/animation/AnimationId.h +++ b/src/animation/AnimationId.h @@ -234,6 +234,7 @@ enum AnimationId ANIM_MELEE_ATTACK_2ND, ANIM_MELEE_ATTACK_START, ANIM_MELEE_IDLE_FIGHTMODE, + ANIM_MELEE_ATTACK_FINISH, ANIM_THROWABLE_THROW = ANIM_WEAPON_FIRE, ANIM_THROWABLE_THROWU, ANIM_THROWABLE_START_THROW, diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 0c36cf17..871d13dc 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -5724,6 +5724,8 @@ cAudioManager::ClearMissionAudio(uint8 slot) m_sMissionAudio.m_bIsPlayed[slot] = false; m_sMissionAudio.m_bPredefinedProperties[slot] = true; m_sMissionAudio.m_nMissionAudioCounter[slot] = 0; + m_sMissionAudio.m_bIsMobile[slot] = false; + SampleManager.StopStreamedFile(slot + 1); } } diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 9fb1991e..ae2e97ac 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -714,15 +714,17 @@ cMusicManager::UsesPoliceRadio(CVehicle *veh) { switch (veh->GetModelIndex()) { - case MI_FBICAR: - case MI_POLICE: - case MI_ENFORCER: - case MI_PREDATOR: + case MI_VCNMAV: + case MI_POLMAV: + case MI_COASTG: case MI_RHINO: case MI_BARRACKS: return true; + case MI_MRWHOOP: + case MI_HUNTER: + return false; } - return false; + return veh->UsesSiren(); } void diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 7e517a83..a3fcbf9a 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -80,7 +80,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || pVehicle->AutoPilot.m_bIgnorePathfinding) { pVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_CLOSE; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) + if (pVehicle->UsesSiren()) pVehicle->m_bSirenOrAlarm = true; } BackToCruisingIfNoWantedLevel(pVehicle); @@ -136,7 +136,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || pVehicle->AutoPilot.m_bIgnorePathfinding) { pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) + if (pVehicle->UsesSiren()) pVehicle->m_bSirenOrAlarm = true; } BackToCruisingIfNoWantedLevel(pVehicle); @@ -294,7 +294,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) || pVehicle->AutoPilot.m_bIgnorePathfinding){ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_CLOSE; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) + if (pVehicle->UsesSiren()) pVehicle->m_bSirenOrAlarm = true; } }else{ @@ -540,7 +540,7 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle) return; pVehicle->bOccupantsHaveBeenGenerated = true; switch (pVehicle->GetModelIndex()){ - case MI_FBICAR: + case MI_FBIRANCH: case MI_ENFORCER: pVehicle->SetUpDriver(); for (int i = 0; i < 3; i++) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 514150a6..cd08753d 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -366,7 +366,7 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; } - if (carModel == MI_FBICAR){ + if (carModel == MI_FBIRANCH){ pVehicle->m_currentColour1 = 0; pVehicle->m_currentColour2 = 0; } @@ -874,9 +874,9 @@ CCarCtrl::ChoosePoliceCarModel(void) CStreaming::HasModelLoaded(MI_POLICE)) return ((CGeneral::GetRandomNumber() & 0xF) == 0) ? MI_ENFORCER : MI_POLICE; if (FindPlayerPed()->m_pWanted->AreFbiRequired() && - CStreaming::HasModelLoaded(MI_FBICAR) && + CStreaming::HasModelLoaded(MI_FBIRANCH) && CStreaming::HasModelLoaded(MI_FBI)) - return MI_FBICAR; + return MI_FBIRANCH; if (FindPlayerPed()->m_pWanted->AreArmyRequired() && CStreaming::HasModelLoaded(MI_RHINO) && CStreaming::HasModelLoaded(MI_BARRACKS) && diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 5d466be2..010dec3f 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -67,7 +67,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType eCopType copType = COP_STREET; switch (pVehicle->GetModelIndex()) { - case MI_FBICAR: + case MI_FBIRANCH: modelInfoId = MI_FBI; copType = COP_FBI; break; @@ -236,7 +236,7 @@ CRoadBlocks::CreateRoadBlockBetween2Points(CVector point1, CVector point2) pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0; pVehicle->AutoPilot.m_nCruiseSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0; pVehicle->bExtendedRange = true; - if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) + if (pVehicle->UsesSiren() && CGeneral::GetRandomNumber() & 1) pVehicle->m_bSirenOrAlarm = true; if (pVehicle->GetUp().z > 0.94f) { CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index c3ca25a6..9407cc06 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3806,9 +3806,8 @@ int8 CRunningScript::ProcessCommands100To199(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((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -3833,9 +3832,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); else UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -10722,12 +10720,9 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) UpdateCompareFlag(CGame::germanGame); return 0; case COMMAND_CLEAR_MISSION_AUDIO: - { CollectParameters(&m_nIp, 1); - debug("CLEAR_MISSION_AUDIO not implemented\n"); - //DMAudio.ClearMissionAudio(ScriptParams[0]); + DMAudio.ClearMissionAudio(ScriptParams[0] - 1); return 0; - } /* case COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST: CollectParameters(&m_nIp, 1); @@ -13565,12 +13560,8 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) break; case COMMAND_WANTED_STARS_ARE_FLASHING: { - static bool bShowed = false; - if (!bShowed) { - debug("WANTED_STARS_ARE_FLASHING not implemented, default to FALSE\n"); - bShowed = true; - } - UpdateCompareFlag(false); + CWanted *pWanted = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted; + UpdateCompareFlag(pWanted->m_nMinWantedLevel - pWanted->m_nWantedLevel > 0); return 0; } case COMMAND_SET_ALLOW_HURRICANES: @@ -13622,7 +13613,7 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) } case COMMAND_DISPLAY_RADAR: CollectParameters(&m_nIp, 1); - debug("DISPLAY_RADAR not implemented\n"); + CHud::m_HideRadar = ScriptParams[0] == 0; return 0; case COMMAND_REGISTER_BEST_POSITION: CollectParameters(&m_nIp, 2); @@ -14421,7 +14412,7 @@ void CRunningScript::LocateCharCommand(int32 command, uint32* pIp) CollectParameters(pIp, b3D ? 8 : 6); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); script_assert(pPed); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + CVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); switch (command) { case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D: case COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D: @@ -15181,7 +15172,7 @@ void CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp) CollectParameters(pIp, b3D ? 8 : 6); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); script_assert(pPed); - CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); + CVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition(); switch (command) { case COMMAND_IS_CHAR_STOPPED_IN_AREA_3D: case COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D: @@ -15466,7 +15457,7 @@ void CRunningScript::DoDeatharrestCheck() if (!CTheScripts::IsPlayerOnAMission()) return; CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus]; - if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest() && !CTheScripts::UpsideDownCars.AreAnyCarsUpsideDown()) + if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest()) return; #ifdef MISSION_REPLAY if (AllowMissionReplay != 0) @@ -15478,6 +15469,7 @@ void CRunningScript::DoDeatharrestCheck() while (m_nStackPointer > 1) --m_nStackPointer; m_nIp = m_anStack[--m_nStackPointer]; + CMessages::ClearSmallMessagesOnly(); *(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0; m_bDeatharrestExecuted = true; m_nWakeTime = 0; @@ -15914,22 +15906,24 @@ void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, fl bool CTheScripts::IsPedStopped(CPed* pPed) { - if (pPed->bInVehicle) + if (pPed->InVehicle()) return IsVehicleStopped(pPed->m_pMyVehicle); - return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; + return (pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL) && + !pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f; } bool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer) { CPed* pPed = pPlayer->m_pPed; - if (pPed->bInVehicle) + if (pPed->InVehicle()) return IsVehicleStopped(pPed->m_pMyVehicle); if (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP) || RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_RUN_STOP_R) || RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_LAUNCH) || RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_JUMP_GLIDE)) return false; - return pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL; + return (pPed->m_nMoveState == eMoveState::PEDMOVE_NONE || pPed->m_nMoveState == eMoveState::PEDMOVE_STILL) && + !pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f; } bool CTheScripts::IsVehicleStopped(CVehicle* pVehicle) diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 3b581dea..c359793c 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -766,7 +766,8 @@ void CRadar::DrawMap() m_radarRange = RADAR_MIN_RANGE; vec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift()); - DrawRadarMap(); + if (FrontEndMenuManager.m_PrefsRadarMode != 1) + DrawRadarMap(); } } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index d560a695..e712e3d6 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1380,11 +1380,11 @@ CStreaming::StreamVehiclesAndPeds(void) } if(FindPlayerPed()->m_pWanted->AreFbiRequired()){ - RequestModel(MI_FBICAR, STREAMFLAGS_DONT_REMOVE); + RequestModel(MI_FBIRANCH, STREAMFLAGS_DONT_REMOVE); RequestModel(MI_FBI, STREAMFLAGS_DONT_REMOVE); }else{ - SetModelIsDeletable(MI_FBICAR); - if(!HasModelLoaded(MI_FBICAR)) + SetModelIsDeletable(MI_FBIRANCH); + if(!HasModelLoaded(MI_FBIRANCH)) SetModelIsDeletable(MI_FBI); } diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index f5c45e0d..86423b0a 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -82,6 +82,7 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_bZoneDisabled = false; field_628 = -1; m_nRoadblockNode = -1; // TODO(Miami): this will be nil + m_bThrowsSpikeTrap = false; field_5FF = 0; m_fAbseilPos = 0.0f; m_bBeatingSuspect = false; diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index 07b09ffd..50d8165f 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -25,6 +25,7 @@ public: bool m_bZoneDisabled; float m_fAbseilPos; eCopType m_nCopType; + bool m_bThrowsSpikeTrap; int32 field_624; int8 field_628; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 3c3fd46a..557aafa3 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -412,7 +412,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIsDrowning = false; bDrownsInWater = true; bHeadStuckInCollision = false; - b156_8 = false; + bHeldHostageInCar = false; bIsPlayerFriend = true; bDeadPedInFrontOfCar = false; @@ -461,7 +461,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) weapon.m_nTimer = 0; } - m_lastFightMove = m_lastHitState = 0; + m_curFightMove = m_lastFightMove = FIGHTMOVE_IDLE; GiveWeapon(WEAPONTYPE_UNARMED, 0, true); m_wepAccuracy = 60; m_lastWepDam = -1; @@ -576,7 +576,7 @@ CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround) currentPedState = currentPed->m_nPedState; - if (currentPedState == PED_FALL || currentPedState == PED_GETUP || currentPedState == PED_DIE || currentPedState == PED_DEAD) { + if (currentPed->OnGroundOrGettingUp()) { if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) { if (currentPedState == PED_DEAD) { foundDead = 1; @@ -1094,13 +1094,13 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) return; } - if (currentWeapon->m_bUse2nd && ped->bIsAttacking && currentWeapon->m_AnimToPlay != ASSOCGRP_THROW) { + if (GetSecondFireAnim(currentWeapon) && ped->bIsAttacking && currentWeapon->m_AnimToPlay != ASSOCGRP_THROW) { AnimationId groundAnim = GetFireAnimGround(currentWeapon); CAnimBlendAssociation *groundAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), groundAnim); if (!groundAnimAssoc || groundAnimAssoc->blendAmount <= 0.95f && groundAnimAssoc->blendDelta <= 0.0f) { if (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK) { newAnim = CAnimManager::BlendAnimation( - ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_2ND, 8.0f); + ped->GetClump(), currentWeapon->m_AnimToPlay, GetSecondFireAnim(currentWeapon), 8.0f); } else { newAnim = CAnimManager::BlendAnimation( ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK, 8.0f); @@ -1231,7 +1231,7 @@ CPed::Attack(void) } if (!weaponAnimAssoc) { if (!!ourWeapon->m_bUse2nd) { - weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_2ND); + weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(ourWeapon)); if (weaponAnimAssoc) { animLoopStart = ourWeapon->m_fAnim2LoopStart; animLoopEnd = ourWeapon->m_fAnim2LoopEnd; @@ -1255,8 +1255,8 @@ CPed::Attack(void) if (bCrouchWhenShooting && bIsDucking && !!ourWeapon->m_bCrouchFire) { weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f); - } else if(!!ourWeapon->m_bUse2nd && CGeneral::GetRandomNumber() & 1){ - weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE_2ND, 8.0f); + } else if(GetSecondFireAnim(ourWeapon) && CGeneral::GetRandomNumber() & 1){ + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f); } else if (!CGame::nastyGame || (!ourWeapon->m_bGround2nd && !ourWeapon->m_bGround3rd) || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) { @@ -1405,7 +1405,6 @@ CPed::Attack(void) weaponAnimTime = weaponAnimAssoc->currentTime; firePos = ourWeapon->m_vecFireOffset; - //TODO(Miami): Check if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) { TransformToNode(firePos, PED_HANDR); @@ -1494,10 +1493,10 @@ CPed::Attack(void) } weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this); } else if (!!ourWeapon->m_bUse2nd) { - if (weaponAnimAssoc->animId == ANIM_WEAPON_FIRE_2ND) { + if (weaponAnimAssoc->animId == GetSecondFireAnim(ourWeapon)) { weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE, 8.0f); } else { - weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE_2ND, 8.0f); + weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f); } weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this); } else { @@ -3147,7 +3146,7 @@ CPed::SetObjective(eObjective newObj, void *entity) break; } } else { - if ((newObj == OBJECTIVE_LEAVE_CAR || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE || newObj == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) + if (newObj != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && (newObj == OBJECTIVE_LEAVE_CAR || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE) && !bInVehicle) return; } @@ -3319,7 +3318,7 @@ CPed::SetObjective(eObjective newObj) } */ - m_objective = newObj; + m_objective = OBJECTIVE_NONE; m_prevObjective = OBJECTIVE_NONE; } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) { SetObjectiveTimer(0); @@ -3436,8 +3435,7 @@ CPed::InformMyGangOfAttack(CEntity *attacker) CPed *nearPed = m_nearPeds[i]; if (nearPed && nearPed != this) { CPed *leader = nearPed->m_leader; - if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) - { + if (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) { nearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed); nearPed->SetObjectiveTimer(30000); } @@ -3973,11 +3971,11 @@ CPed::ClearAttackByRemovingAnim(void) } if (!weaponAssoc) { if(!!weapon->m_bFinish3rd) - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_SPECIAL); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFinishingAttackAnim(weapon)); } if (!weaponAssoc) { if(!!weapon->m_bUse2nd) - weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCHFIRE); + weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(weapon)); } if (!weaponAssoc) { if(!!weapon->m_bCop3rd) @@ -4212,7 +4210,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (method != WEAPONTYPE_KATANA || damagedBy != FindPlayerPed() || FindPlayerPed()->m_nPedState != PED_FIGHT - || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE1 && FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE2 + || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE1 && FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2 || CGeneral::GetRandomNumber() & 3) { if (m_nPedState == PED_FALL) { @@ -4226,8 +4224,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi dieDelta = dieDelta * 2.0f; dieSpeed = 0.5f; } - } else if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE2) { - if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != FIGHTMOVE_MELEE3) { + } else if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2) { + if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE3) { switch (direction) { case 0: dieAnim = ANIM_KO_SKID_FRONT; @@ -4752,8 +4750,8 @@ CPed::ClearObjective(void) m_objective = OBJECTIVE_NONE; m_pedInObjective = nil; m_carInObjective = nil; - if (m_nPedState == PED_DRIVING && m_pMyVehicle) { + if (m_nPedState == PED_DRIVING && m_pMyVehicle) { if (m_pMyVehicle->pDriver != this) { if(!IsPlayer()) bWanderPathAfterExitingCar = true; @@ -4875,7 +4873,7 @@ CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) void CPed::RestorePreviousState(void) { - if(!CanSetPedState() || m_nPedState == PED_FALL) + if (!CanSetPedState() || m_nPedState == PED_FALL) return; if (m_nPedState == PED_GETUP && !bGetUpAnimStarted) @@ -5415,6 +5413,7 @@ CPed::SetAttack(CEntity *victim) SetLookTimer(100); } +// --MIAMI: Done void CPed::StartFightAttack(uint8 buttonPressure) { @@ -5434,53 +5433,71 @@ CPed::StartFightAttack(uint8 buttonPressure) RestoreHeadingRate(); } - m_nPedState = PED_FIGHT; - m_fightButtonPressure = 0; - RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); - CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); - - if (animAssoc) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->blendDelta = -1000.0f; - } - - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + CAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); if (!animAssoc) animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); if (animAssoc) { - animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc->blendDelta = -1000.0f; RestoreHeadingRate(); } - SetMoveState(PEDMOVE_NONE); m_nStoredMoveState = PEDMOVE_NONE; + bool fightWithWeapon = false; + CAnimBlendAssociation *fightIdleAssoc; - CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; - - CPed *pedOnGround = nil; - if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) { - m_lastFightMove = FIGHTMOVE_GROUNDKICK; - } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) { - m_lastFightMove = FIGHTMOVE_ROUNDHOUSE; + CWeaponInfo* weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + if (GetFightIdleWithMeleeAnim(weaponInfo)) { + fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo), 1000.0f); + fightWithWeapon = true; + } else { + fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE, 1000.0f); + } } else { - m_lastFightMove = FIGHTMOVE_STDPUNCH; + fightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE, 1000.0f); + } + m_lastFightMove = FIGHTMOVE_IDLE; + m_curFightMove = IsPlayer() ? ChooseAttackPlayer(buttonPressure, fightWithWeapon) : ChooseAttackAI(buttonPressure, fightWithWeapon); + + SetPedState(PED_FIGHT); + m_fightButtonPressure = 0; + + if (m_curFightMove > FIGHTMOVE_NULL && m_curFightMove != FIGHTMOVE_IDLE) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay, + tFightMoves[m_curFightMove].animId, 8.0f); + + if (weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE || m_curFightMove < FIGHTMOVE_MELEE1) { + if (m_curFightMove == FIGHTMOVE_BACKKICK) + animAssoc->speed = 1.15f; + else + animAssoc->speed = 0.8f; + } else { + switch (GetWeapon()->m_eWeaponType) { + case WEAPONTYPE_SCREWDRIVER: + case WEAPONTYPE_KNIFE: + animAssoc->speed = 1.05f; + break; + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_BASEBALLBAT: + case WEAPONTYPE_HAMMER: + case WEAPONTYPE_KATANA: + animAssoc->speed = 0.8f; + break; + case WEAPONTYPE_CLEAVER: + case WEAPONTYPE_MACHETE: + animAssoc->speed = 0.9f; + break; + } + } + if (IsPlayer()) + animAssoc->SetCurrentTime(0.08f); + + animAssoc->SetFinishCallback(FinishFightMoveCB, this); + } else { + m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000; } - if (pedOnGround && IsPlayer()) { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - pedOnGround->GetPosition().x, pedOnGround->GetPosition().y, - GetPosition().x, GetPosition().y); - - m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(pedOnGround, true); - SetLookTimer(1500); - } - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); - animAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; m_takeAStepAfterAttack = false; bIsAttacking = true; @@ -5594,7 +5611,7 @@ CPed::GetLocalDirection(const CVector2D &posOffset) // --MIAMI: Done bool -CPed::FightStrike(CVector &touchedNodePos, bool unk = false) +CPed::FightStrike(CVector &touchedNodePos, bool fightWithWeapon) { CColModel *hisCol; CVector attackDistance; @@ -5603,8 +5620,8 @@ CPed::FightStrike(CVector &touchedNodePos, bool unk = false) CVector extendedTouchPoint; CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - float radius = tFightMoves[m_lastFightMove].strikeRadius; - if (unk) + float radius = tFightMoves[m_curFightMove].strikeRadius; + if (fightWithWeapon) radius = weaponInfo->m_fRadius; if (m_fightState == FIGHTSTATE_JUST_ATTACKED) @@ -5615,7 +5632,7 @@ CPed::FightStrike(CVector &touchedNodePos, bool unk = false) for (int i = 0; i < m_numNearPeds; i++) { int8 pedFound = 0; nearPed = m_nearPeds[i]; - if (!unk && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE) + if (!fightWithWeapon && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE) maxDistanceToBeat = nearPed->GetBoundRadius() + radius + 0.1f; else maxDistanceToBeat = nearPed->GetBoundRadius() + radius; @@ -5646,14 +5663,14 @@ CPed::FightStrike(CVector &touchedNodePos, bool unk = false) } } } - if (!pedFound && !unk) { + if (!pedFound && !fightWithWeapon) { extendedTouchPoint = touchedNodePos - GetPosition(); if (DotProduct(touchedNodePos - GetPosition(), nearPed->GetPosition() - GetPosition()) > 0.f) { - if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) { + if (m_curFightMove == FIGHTMOVE_GROUNDKICK) { extendedTouchPoint += tFightMoves[FIGHTMOVE_GROUNDKICK].extendReachMultiplier * GetForward(); } else { - extendedTouchPoint.x *= tFightMoves[m_lastFightMove].extendReachMultiplier; - extendedTouchPoint.y *= tFightMoves[m_lastFightMove].extendReachMultiplier; + extendedTouchPoint.x *= tFightMoves[m_curFightMove].extendReachMultiplier; + extendedTouchPoint.y *= tFightMoves[m_curFightMove].extendReachMultiplier; } pedFound = -1; extendedTouchPoint += GetPosition(); @@ -5667,7 +5684,7 @@ CPed::FightStrike(CVector &touchedNodePos, bool unk = false) attackDistance = hisCol->spheres[j].center; attackDistance -= extendedTouchPoint; CColSphere* hisPieces = hisCol->spheres; - float maxDistanceToBeat2 = hisPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius; + float maxDistanceToBeat2 = hisPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius; // We can beat him too if (sq(maxDistanceToBeat2) > attackDistance.MagnitudeSqr()) { @@ -5688,22 +5705,22 @@ CPed::FightStrike(CVector &touchedNodePos, bool unk = false) return false; } -// TODO(Miami) +// --MIAMI: Done void -CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece) +CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dir, int16 piece) { if (victim->IsPlayer() && victim->m_nPedState == PED_GETUP) return; CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); bool fightingWithWeapon = false; - int damageMult = tFightMoves[m_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; + int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; if (weaponInfo->m_bFightMode) { fightingWithWeapon = true; - if (m_lastFightMove >= FIGHTMOVE_MELEE1) { + if (m_curFightMove >= FIGHTMOVE_MELEE1) { damageMult = weaponInfo->m_nDamage; - if (m_lastFightMove == FIGHTMOVE_MELEE3 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER) + if (m_curFightMove == FIGHTMOVE_MELEE3 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER) damageMult *= 5; } } @@ -5716,56 +5733,83 @@ CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece) } float oldVictimHealth = victim->m_fHealth; - CVector bloodPos = 0.5f * dist + touchPoint; + CVector bloodPos = 0.5f * dir + touchPoint; CVector2D diff(GetPosition() - victim->GetPosition()); int direction = victim->GetLocalDirection(diff); - /* - // Change direction if we used kick. - if (m_lastFightMove == FIGHTMOVE_KICK) { - if (CGeneral::GetRandomNumber() & 1) { - direction++; - if (direction > 3) - direction -= 4; + bool brassKnucklePunch = false; + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) { + if (m_curFightMove == FIGHTMOVE_PUNCHHOOK || m_curFightMove == FIGHTMOVE_PUNCHJAB || m_curFightMove == FIGHTMOVE_BACKLEFT || + m_curFightMove == FIGHTMOVE_STDPUNCH || m_curFightMove == FIGHTMOVE_PUNCH) { + brassKnucklePunch = true; + damageMult *= 1.5f; } - } */ + } victim->ReactToAttack(this); - // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it. + // Mostly unused. if > 5, ANIM_HIT_BIGSTEP will be run, that's it. int unk2; - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !victim->IsPlayer()) + if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && + !victim->IsPlayer() && !fightingWithWeapon) unk2 = 101; else unk2 = damageMult; - victim->StartFightDefend(direction, tFightMoves[m_lastFightMove].hitLevel, unk2); + victim->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2); PlayHitSound(victim); m_fightState = FIGHTSTATE_JUST_ATTACKED; - RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId)->speed = 0.6f; + RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f; + if (!victim->DyingOrDead()) { - victim->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, (ePedPieceTypes)piece, direction); + if(fightingWithWeapon) + victim->InflictDamage(this, GetWeapon()->m_eWeaponType, damageMult, (ePedPieceTypes)piece, direction); + else + victim->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, (ePedPieceTypes)piece, direction); } - if (CGame::nastyGame - && tFightMoves[m_lastFightMove].hitLevel > HITLEVEL_MEDIUM - && victim->m_nPedState == PED_DIE + if (CGame::nastyGame && weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE && m_curFightMove >= FIGHTMOVE_MELEE1 && victim->GetIsOnScreen()) { - // Just for blood particle. We will restore it below. - dist /= (10.0f * dist.Magnitude()); - for(int i=0; i<4; i++) { - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dist, nil, 0.0f, 0, 0, 0, 0); + static float particleRightLen = 0.05f; + static float particleUpLen = 0.05f; + + // Just for particles. We will restore it below. + dir /= (20.0f * dir.Magnitude()); + if (m_curFightMove == FIGHTMOVE_MELEE1) { + float rightMult = -particleRightLen; + dir += particleUpLen * GetUp() + rightMult * GetRight(); + + } else if (m_curFightMove == FIGHTMOVE_MELEE2) { + float upMult = 2.0f * particleUpLen; + dir += particleRightLen * GetRight() + upMult * GetUp(); + } + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); + if (IsPlayer()) { + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); + } + if (!(CGeneral::GetRandomNumber() & 3)) { + CParticle::AddParticle(PARTICLE_TEST, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); + } + } else if (CGame::nastyGame && (tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM || fightingWithWeapon) + && victim->GetIsOnScreen()) { + + // Just for particles. We will restore it below. + dir /= (10.0f * dir.Magnitude()); + for (int i = 0; i < 4; i++) { + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0); } } eWeaponType weaponType = GetWeapon()->m_eWeaponType; if (!fightingWithWeapon) { - if (victim->m_nPedState != PED_FALL && victim->m_nPedState != PED_DIE && victim->m_nPedState != PED_DEAD) { + if (!victim->OnGround()) { float curVictimHealth = victim->m_fHealth; if (curVictimHealth > 0.0f && (curVictimHealth < 30.0f && oldVictimHealth > 30.0f || weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BRASSKNUCKLE && IsPlayer() - || victim->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) { + || victim->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN || brassKnucklePunch)) { victim->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); if (victim->m_nPedState == PED_FALL) @@ -5775,15 +5819,15 @@ CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece) } if (victim->m_nPedState == PED_DIE || !victim->bIsStanding) { - dist = victim->GetPosition() - GetPosition(); - dist.Normalise(); - dist.z = 1.0f; + dir = victim->GetPosition() - GetPosition(); + dir.Normalise(); + dir.z = 1.0f; victim->bIsStanding = false; float moveMult; if (fightingWithWeapon) { moveMult = Min(damageMult * 0.02f, 1.0f); - } else if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) { + } else if (m_curFightMove == FIGHTMOVE_GROUNDKICK) { moveMult = Min(damageMult * 0.6f, 4.0f); } else { if (victim->m_nPedState != PED_DIE || damageMult >= 20) { @@ -5793,7 +5837,7 @@ CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece) } } - victim->ApplyMoveForce(moveMult * 0.6f * dist); + victim->ApplyMoveForce(moveMult * 0.6 * dir); } if (weaponType != WEAPONTYPE_KNIFE && weaponType != WEAPONTYPE_MACHETE @@ -5811,6 +5855,334 @@ CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece) } } +// --MIAMI: Done +int32 +CPed::ChooseAttackPlayer(uint8 buttonPressure, bool fightWithWeapon) +{ + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + const float maxAttackDist = 2.7f; + float weaponAttackDist = 2.0f; + CPed *victimPed = nil; + CPed *walkUpTo = nil; + CPed *groundAttackDeadPed = nil; + CPed *groundAttackAlivePed = nil; + if (fightWithWeapon) + weaponAttackDist = weaponInfo->m_fRange; + + bool willWalkUp = false; + PedFightMoves choosenMove = FIGHTMOVE_IDLE; + int numPedsWeCanReach = 0; + if (m_takeAStepAfterAttack) + willWalkUp = true; + + float groundAttackDeadAngle, groundAttackAliveAngle, walkAngle, victimAngle, distToVictim; + + for (int i = 0; i < m_numNearPeds; ++i) { + CPed *nearPed = m_nearPeds[i]; + CVector distVec(nearPed->GetPosition() - GetPosition()); + float dist = distVec.Magnitude(); + if (dist < maxAttackDist) { + float nearPedAngle = CGeneral::LimitRadianAngle(distVec.Heading()); + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + float neededTurn = Abs(nearPedAngle - m_fRotationCur); + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (!nearPed->OnGroundOrGettingUp() && nearPed->m_nWaitState != WAITSTATE_SUN_BATHE_IDLE) { + if (!willWalkUp || neededTurn <= DEGTORAD(45.0f)) { + + if (neededTurn <= DEGTORAD(30.0f) || nearPed->m_pedInObjective == this + && (nearPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || nearPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) { + + if (dist < weaponAttackDist) { + if (!victimPed + || nearPed->m_attackTimer < victimPed->m_attackTimer && nearPed->m_attackTimer > CTimer::GetTimeInMilliseconds() - 100) { + victimPed = nearPed; + victimAngle = nearPedAngle; + distToVictim = dist; + } + ++numPedsWeCanReach; + + } else { + if (neededTurn < DEGTORAD(30.0f)) { + walkUpTo = nearPed; + walkAngle = nearPedAngle; + } + } + } + } + } else if (CGame::nastyGame && dist < 1.2f && neededTurn < DEGTORAD(55.0f)) { + if (!nearPed->DyingOrDead() || groundAttackDeadPed) { + if (!nearPed->IsPedHeadAbovePos(-0.3f)) { + groundAttackAlivePed = nearPed; + groundAttackAliveAngle = nearPedAngle; + } + } else { + groundAttackDeadPed = nearPed; + groundAttackDeadAngle = nearPedAngle; + } + ++numPedsWeCanReach; + + } else if (dist > 1.4f && dist < maxAttackDist && neededTurn < DEGTORAD(30.0f)) { + if (!walkUpTo) { + walkUpTo = nearPed; + walkAngle = nearPedAngle; + } +#ifdef FIX_BUGS + if(dist < 2.1f) +#endif + ++numPedsWeCanReach; + } + } + } + + if (victimPed) { + float adjustedAngleDiff = victimAngle - m_fRotationCur + DEGTORAD(30.0f); + if (adjustedAngleDiff < 0.0f) + adjustedAngleDiff = adjustedAngleDiff + TWOPI; + + int16 dir = floorf(adjustedAngleDiff / DEGTORAD(60.0f)); + + // Just focus on who we're fighting with, don't care peds on ground + if (numPedsWeCanReach < 2 || fightWithWeapon) { + float angleDiff = Abs(victimAngle - m_fRotationCur); + if (angleDiff > PI) + angleDiff = TWOPI - angleDiff; + + if (angleDiff < DEGTORAD(60.0f)) + dir = 0; // forward + } + int16 randVal = CGeneral::GetRandomNumber() & 3; + switch (dir) { + case 0: // forward + if (fightWithWeapon) { + if (distToVictim < 0.95f - 0.2f && m_nPedState == PED_FIGHT) { + choosenMove = FIGHTMOVE_KNEE; + } else { + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CLEAVER) { + if (distToVictim < 0.85f * weaponInfo->m_fRange) + choosenMove = FIGHTMOVE_MELEE1; + else + choosenMove = FIGHTMOVE_SHUFFLE_F; + } else { + float weaponRange = weaponInfo->m_fRange; + if (distToVictim < 0.75f * weaponRange && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER) { + if (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) { + choosenMove = FIGHTMOVE_MELEE2; + } else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) { + choosenMove = FIGHTMOVE_MELEE3; + } else { + choosenMove = FIGHTMOVE_MELEE1; + } + } else if (distToVictim < weaponRange && GetFinishingAttackAnim(weaponInfo)) { + choosenMove = FIGHTMOVE_MELEE3; + } else { + choosenMove = FIGHTMOVE_SHUFFLE_F; + } + } + } + } else if (distToVictim < 0.95f && m_nPedState == PED_FIGHT) { + choosenMove = FIGHTMOVE_KNEE; + + } else if (distToVictim < 1.4f) { + if (m_curFightMove == FIGHTMOVE_PUNCHJAB) { + choosenMove = FIGHTMOVE_PUNCH; + + } else if (m_curFightMove != FIGHTMOVE_PUNCH || randVal != 1) { + if (randVal == 2) + choosenMove = FIGHTMOVE_PUNCH; + else + choosenMove = FIGHTMOVE_PUNCHJAB; + } else { + choosenMove = FIGHTMOVE_LONGKICK; + } + } else { + choosenMove = FIGHTMOVE_LONGKICK; + } + break; + case 1: + choosenMove = FIGHTMOVE_FWDLEFT; + break; + case 2: + choosenMove = FIGHTMOVE_BACKLEFT; + break; + case 3: + choosenMove = FIGHTMOVE_BACKKICK; + break; + case 4: + choosenMove = FIGHTMOVE_BACKRIGHT; + break; + default: + choosenMove = FIGHTMOVE_FWDRIGHT; + break; + } + + // forward + if (dir == 0) { + m_fRotationDest = CGeneral::LimitRadianAngle(victimAngle); + } else { + m_fRotationDest = victimAngle - dir * DEGTORAD(60.0f); + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + } + + m_fRotationCur = m_fRotationDest; + Say(SOUND_PED_ATTACK); + + } else if (groundAttackAlivePed || groundAttackDeadPed) { + if (fightWithWeapon && weaponInfo->m_bGround2nd) { + choosenMove = FIGHTMOVE_MELEE2; + } else if (fightWithWeapon && weaponInfo->m_bGround3rd) { + choosenMove = FIGHTMOVE_MELEE3; + } else { + choosenMove = FIGHTMOVE_GROUNDKICK; + } + if (groundAttackAlivePed) + m_fRotationDest = groundAttackAliveAngle; + else + m_fRotationDest = groundAttackDeadAngle; + + m_fRotationCur = m_fRotationDest; + m_lookTimer = 0; + if (groundAttackAlivePed) + SetLookFlag(groundAttackAlivePed, 1, 0); + else + SetLookFlag(groundAttackDeadPed, 1, 0); + + SetLookTimer(1500u); + + } else if (walkUpTo) { + choosenMove = FIGHTMOVE_SHUFFLE_F; + m_fRotationCur = m_fRotationDest = walkAngle; + m_lookTimer = 0; + SetLookFlag(walkUpTo, true); + SetLookTimer(1500); + + } else if (fightWithWeapon) { + // No enemy, fight with space + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_SCREWDRIVER) { + choosenMove = FIGHTMOVE_MELEE3; + } else { + if (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) { + choosenMove = FIGHTMOVE_MELEE2; + } else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) { + choosenMove = FIGHTMOVE_MELEE3; + } else { + choosenMove = FIGHTMOVE_MELEE1; + } + } + } else { + // Max number GetRandomNumberInRange returns is max-1 +#ifdef FIX_BUGS + switch (CGeneral::GetRandomNumberInRange(0,4)) { +#else + switch (CGeneral::GetRandomNumberInRange(0,3)) { +#endif + case 0: + choosenMove = FIGHTMOVE_PUNCHJAB; + break; + case 1: + choosenMove = FIGHTMOVE_PUNCH; + break; + case 2: + choosenMove = FIGHTMOVE_LONGKICK; + break; + case 3: + choosenMove = FIGHTMOVE_KNEE; + break; + default: + break; + } + } + return choosenMove; +} + +// --MIAMI: Done +int32 +CPed::ChooseAttackAI(uint8 buttonPressure, bool fightWithWeapon) +{ + eWeaponType weapon = GetWeapon()->m_eWeaponType; + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon); + if (!fightWithWeapon && weapon != WEAPONTYPE_UNARMED && weapon != WEAPONTYPE_BRASSKNUCKLE) { + return FIGHTMOVE_PUNCH; + } + + if (!m_pedInObjective) + return FIGHTMOVE_IDLE; + if (buttonPressure == 0) + return FIGHTMOVE_IDLE; + + uint16 pedFeatures = m_pedStats->m_flags; + bool punchOnly = !!(pedFeatures & STAT_PUNCH_ONLY); + bool canRoundhouse = !!(pedFeatures & STAT_CAN_ROUNDHOUSE); + bool canKneeHead = !!(pedFeatures & STAT_CAN_KNEE_HEAD); + bool canKick = !!(pedFeatures & STAT_CAN_KICK); + bool hasShoppingBags = !!(pedFeatures & STAT_SHOPPING_BAGS); + + CVector distVec(m_pedInObjective->GetPosition() - GetPosition()); + float dist = distVec.Magnitude(); + m_fRotationDest = CGeneral::LimitRadianAngle(distVec.Heading()); + m_fRotationCur = m_fRotationDest; + + if (fightWithWeapon) { + if (m_pedInObjective->OnGroundOrGettingUp()) { + if (!CGame::nastyGame || dist >= 1.2f || m_pedInObjective->IsPlayer() + || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) { + return FIGHTMOVE_IDLE; + } + + if (weaponInfo->m_bGround2nd) + return FIGHTMOVE_MELEE2; + if (weaponInfo->m_bGround3rd) + return FIGHTMOVE_MELEE3; + + return FIGHTMOVE_GROUNDKICK; + } + if (dist < 2.f) { + if (m_curFightMove == FIGHTMOVE_MELEE1) { + if (GetSecondFireAnim(weaponInfo)) + return FIGHTMOVE_MELEE2; + } + if (m_curFightMove == FIGHTMOVE_MELEE2) { + if (GetFinishingAttackAnim(weaponInfo)) + return FIGHTMOVE_MELEE3; + } + return FIGHTMOVE_MELEE1; + } + return FIGHTMOVE_SHUFFLE_F; + } + if (!hasShoppingBags) { + if (punchOnly) { + if (dist < 1.4f) + return FIGHTMOVE_PUNCH; + } else { + if (m_pedInObjective->OnGroundOrGettingUp()) { + if (!CGame::nastyGame || dist >= 1.2f || m_pedInObjective->IsPlayer() + || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) { + + return FIGHTMOVE_IDLE; + } else { + return FIGHTMOVE_GROUNDKICK; + } + } + if (dist < 0.95f && canKneeHead) + return FIGHTMOVE_KNEE; + if (dist < 1.4f) + return FIGHTMOVE_PUNCH; + if (dist < 2.f && canKick) { + int nextMove = FIGHTMOVE_LONGKICK; + if (canRoundhouse && CGeneral::GetRandomNumber() & 1) + nextMove = FIGHTMOVE_ROUNDHOUSE; + return nextMove; + } + } + return FIGHTMOVE_SHUFFLE_F; + } + if (dist < 2.f) + return FIGHTMOVE_ROUNDHOUSE; + else + return FIGHTMOVE_SHUFFLE_F; +} + // --MIAMI: Done void CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) @@ -5877,6 +6249,7 @@ CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) bFallenDown = true; } +// --MIAMI: Done void CPed::SetFlee(CEntity *fleeFrom, int time) { @@ -5884,7 +6257,7 @@ CPed::SetFlee(CEntity *fleeFrom, int time) return; SetStoredState(); - m_nPedState = PED_FLEE_ENTITY; + SetPedState(PED_FLEE_ENTITY); bUsePedNodeSeek = true; SetMoveState(PEDMOVE_RUN); m_fleeFrom = fleeFrom; @@ -5907,6 +6280,7 @@ CPed::SetFlee(CEntity *fleeFrom, int time) } } +// --MIAMI: Done void CPed::SetFlee(CVector2D const &from, int time) { @@ -5915,7 +6289,7 @@ CPed::SetFlee(CVector2D const &from, int time) if (m_nPedState != PED_FLEE_ENTITY) { SetStoredState(); - m_nPedState = PED_FLEE_POS; + SetPedState(PED_FLEE_POS); SetMoveState(PEDMOVE_RUN); m_fleeFromPosX = from.x; m_fleeFromPosY = from.y; @@ -6179,8 +6553,8 @@ CPed::PlayHitSound(CPed *hitTo) eWeaponType weapon = GetWeapon()->m_eWeaponType; CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon); if (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE) { - if (m_lastFightMove >= FIGHTMOVE_MELEE1) { - if (m_lastFightMove == FIGHTMOVE_MELEE3) { + if (m_curFightMove >= FIGHTMOVE_MELEE1) { + if (m_curFightMove == FIGHTMOVE_MELEE3) { DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | 3); } else { DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | 3); @@ -6190,21 +6564,21 @@ CPed::PlayHitSound(CPed *hitTo) } // This is why first dimension is between FightMove 1 and 17. - if (m_lastFightMove <= FIGHTMOVE_NULL || m_lastFightMove >= FIGHTMOVE_HITFRONT) + if (m_curFightMove <= FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT) return; uint16 soundId; // And this is why second dimension is between 18 and 27. - if (hitTo->m_lastFightMove <= FIGHTMOVE_GROUNDKICK || hitTo->m_lastFightMove >= FIGHTMOVE_IDLE2NORM) { + if (hitTo->m_curFightMove <= FIGHTMOVE_GROUNDKICK || hitTo->m_curFightMove >= FIGHTMOVE_IDLE2NORM) { if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; } else { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; } } else { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_lastFightMove - FIGHTMOVE_HITFRONT]; + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; } if (soundId != NO_SND) @@ -7020,7 +7394,7 @@ CPed::EndFight(uint8 endType) if (m_nPedState != PED_FIGHT) return; - m_lastFightMove = FIGHTMOVE_NULL; + m_curFightMove = FIGHTMOVE_NULL; RestorePreviousState(); CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); if (!animAssoc) @@ -7354,30 +7728,57 @@ CPed::Fall(void) } } +// --MIAMI: Done void CPed::Fight(void) { - CAnimBlendAssociation *currentAssoc = nil, *animAssoc; - bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse; - float angleToFace, nextAngle; - bool goForward = false; - int nextFightMove; + CAnimBlendAssociation *currentAssoc, *animAssoc; + bool fightWithWeapon = false; - switch (m_lastFightMove) { + eWeaponType weapon = GetWeapon()->m_eWeaponType; + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon); + + if (weaponInfo->m_bFightMode && weapon != WEAPONTYPE_UNARMED) { + fightWithWeapon = true; + tFightMoves[FIGHTMOVE_MELEE1].startFireTime = weaponInfo->m_fAnimFrameFire; + tFightMoves[FIGHTMOVE_MELEE1].endFireTime = weaponInfo->m_fAnimLoopEnd; + tFightMoves[FIGHTMOVE_MELEE2].startFireTime = weaponInfo->m_fAnim2FrameFire; + tFightMoves[FIGHTMOVE_MELEE2].endFireTime = weaponInfo->m_fAnim2LoopEnd; + tFightMoves[FIGHTMOVE_MELEE3].startFireTime = weaponInfo->m_fAnim2FrameFire; + tFightMoves[FIGHTMOVE_MELEE3].endFireTime = weaponInfo->m_fAnim2LoopEnd; + } + + switch (m_curFightMove) { case FIGHTMOVE_NULL: return; case FIGHTMOVE_IDLE2NORM: - m_lastFightMove = FIGHTMOVE_NULL; + m_curFightMove = FIGHTMOVE_NULL; RestorePreviousState(); break; case FIGHTMOVE_IDLE: - // currentAssoc = nil; + currentAssoc = nil; break; default: - currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId); + currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); break; } + if (m_curFightMove == FIGHTMOVE_SHUFFLE_F && !currentAssoc) + currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_SH_BACK); + + if (IsPlayer() && currentAssoc && weapon == WEAPONTYPE_KATANA) { + if (m_curFightMove == FIGHTMOVE_MELEE1 || m_curFightMove == FIGHTMOVE_MELEE2) { + static float streakDelay = 0.2f; + + if (tFightMoves[m_curFightMove].startFireTime - streakDelay < currentAssoc->currentTime && + streakDelay + tFightMoves[m_curFightMove].endFireTime > currentAssoc->currentTime) { + + // TODO(Miami): AddWeaponStreak + // CSpecialFX::AddWeaponStreak(v2->m_weapons[(char)v2->m_currentWeapon].nWeaponId); + } + } + } + if (!bIsAttacking && IsPlayer()) { if (currentAssoc) { currentAssoc->blendDelta = -1000.0f; @@ -7391,291 +7792,145 @@ CPed::Fight(void) } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) { float animTime = currentAssoc->currentTime; - FightMove &curMove = tFightMoves[m_lastFightMove]; + FightMove &curMove = tFightMoves[m_curFightMove]; if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) { + if (animTime > curMove.startFireTime && animTime - currentAssoc->timeStep < curMove.startFireTime && + (IsPlayer() || weapon != WEAPONTYPE_UNARMED)) { + + DMAudio.PlayOneShot(m_audioEntityId, SOUND_MELEE_ATTACK_START, weapon << 8); + } + CVector touchingNodePos(0.0f, 0.0f, 0.0f); - switch (m_lastFightMove) { - case FIGHTMOVE_STDPUNCH: - case FIGHTMOVE_PUNCHHOOK: - case FIGHTMOVE_BODYBLOW: - TransformToNode(touchingNodePos, PED_HANDR); - break; - case FIGHTMOVE_IDLE: - case FIGHTMOVE_SHUFFLE_F: - break; + switch (m_curFightMove) { case FIGHTMOVE_KNEE: TransformToNode(touchingNodePos, PED_LOWERLEGR); break; + case FIGHTMOVE_PUNCHHOOK: case FIGHTMOVE_PUNCHJAB: TransformToNode(touchingNodePos, PED_HANDL); break; case FIGHTMOVE_LONGKICK: case FIGHTMOVE_ROUNDHOUSE: + case FIGHTMOVE_FWDLEFT: + case FIGHTMOVE_BACKRIGHT: case FIGHTMOVE_GROUNDKICK: TransformToNode(touchingNodePos, PED_FOOTR); break; + case FIGHTMOVE_FWDRIGHT: + TransformToNode(touchingNodePos, PED_HEAD); + break; + case FIGHTMOVE_BACKKICK: + case FIGHTMOVE_BACKFLIP: + TransformToNode(touchingNodePos, PED_FOOTL); + break; + case FIGHTMOVE_BACKLEFT: + TransformToNode(touchingNodePos, PED_UPPERARML); + break; + default: + TransformToNode(touchingNodePos, PED_HANDR); + break; } - if (m_lastFightMove == FIGHTMOVE_PUNCHJAB) { - touchingNodePos += 0.1f * GetForward(); - } else if (m_lastFightMove == FIGHTMOVE_PUNCHHOOK) { - touchingNodePos += 0.22f * GetForward(); - } - FightStrike(touchingNodePos); + FightStrike(touchingNodePos, fightWithWeapon); m_fightButtonPressure = 0; return; } if (curMove.hitLevel != HITLEVEL_NULL) { - if (animTime > curMove.endFireTime) { + if (animTime > curMove.endFireTime && weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE) { if (IsPlayer()) currentAssoc->speed = 1.0f; else currentAssoc->speed = 0.8f; } - if (IsPlayer() && !nPlayerInComboMove) { + if (IsPlayer() && !nPlayerInComboMove && !fightWithWeapon) { if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) { + m_lastFightMove = m_curFightMove; // Notice that it increases fight move index, because we're in combo! - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_lastFightMove].animId, 8.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength); + animAssoc->speed = 0.8f; m_fightButtonPressure = 0; nPlayerInComboMove = 1; } } - } else { - if (curMove.startFireTime > 0.0f && m_lastFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) { - if (IsPlayer()) - currentAssoc->speed = 1.3f; - else - currentAssoc->speed = 0.8f; - } } - } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + + } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && !fightWithWeapon) { EndFight(ENDFIGHT_FAST); } else if (m_fightButtonPressure != 0) { - bool canAffectMultiplePeople = true; - nextAngle = m_fRotationCur; - bool kickGround = false; - float angleForGroundKick = 0.0f; - CPed *pedOnGround = nil; + if (!IsPlayer()) + Say(SOUND_PED_ATTACK); - Say(SOUND_PED_ATTACK); + if (m_curFightMove != FIGHTMOVE_IDLE) + m_lastFightMove = m_curFightMove; - if (IsPlayer()) { - canRoundhouse = false; - punchOnly = false; - canKick = true; - nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE); - hasShoppingBags = false; - canKneeHead = true; - nPlayerInComboMove = 0; - } else { - nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_BODYBLOW : FIGHTMOVE_KNEE); - uint16 pedFeatures = m_pedStats->m_flags; - punchOnly = pedFeatures & STAT_PUNCH_ONLY; - canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE; - canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD; - canKick = pedFeatures & STAT_CAN_KICK; - hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS; - } + m_curFightMove = IsPlayer() ? ChooseAttackPlayer(m_fightButtonPressure, fightWithWeapon) : ChooseAttackAI(m_fightButtonPressure, fightWithWeapon); - // Attack isn't scripted, find the victim - if (IsPlayer() || !m_pedInObjective) { + if (m_curFightMove != FIGHTMOVE_IDLE) { - for (int i = 0; i < m_numNearPeds; i++) { + animAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay, + tFightMoves[m_curFightMove].animId, 8.0f); - CPed *nearPed = m_nearPeds[i]; - float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude(); - if (nearPedDist < 3.0f) { - float angleToFace = CGeneral::GetRadianAngleBetweenPoints( - nearPed->GetPosition().x, nearPed->GetPosition().y, - GetPosition().x, GetPosition().y); - - nextAngle = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); - - float neededTurn = Abs(nextAngle - m_fRotationCur); - if (neededTurn > PI) - neededTurn = TWOPI - neededTurn; - - PedState nearPedState = nearPed->m_nPedState; - if (nearPedState != PED_FALL && nearPedState != PED_GETUP && nearPedState != PED_DIE && nearPedState != PED_DEAD) { - - if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) { - canAffectMultiplePeople = false; - } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) { - - if (nearPedDist < 1.7f - && neededTurn < DEGTORAD(35.0f) - && (canKick || hasShoppingBags)) { - - nextFightMove = FIGHTMOVE_LONGKICK; - if (hasShoppingBags) { - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) { - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - } - canAffectMultiplePeople = false; - } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) { - canAffectMultiplePeople = false; - nextFightMove = FIGHTMOVE_LONGKICK; - } else if (neededTurn < DEGTORAD(30.0f)) { - goForward = true; - } - } else { - nextFightMove += 2; // Makes it 6 or 7 - if (punchOnly) - nextFightMove = FIGHTMOVE_PUNCHJAB; - - canAffectMultiplePeople = false; - } - } else if (!CGame::nastyGame - || nearPedDist >= 1.3f - || neededTurn >= DEGTORAD(55.0f) - || punchOnly) { - - if (nearPedDist > 0.8f - && nearPedDist < 3.0f - && neededTurn < DEGTORAD(30.0f)) { - goForward = true; - } - - } else if (nearPedState != PED_DEAD || pedOnGround) { - if (!nearPed->IsPedHeadAbovePos(-0.3f)) { - canAffectMultiplePeople = false; - nextFightMove = FIGHTMOVE_GROUNDKICK; - } - - } else { - pedOnGround = nearPed; - kickGround = true; - angleForGroundKick = nextAngle; - } - } - - if (!canAffectMultiplePeople) { - m_fRotationDest = nextAngle; - if (IsPlayer()) { - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(nearPed, true); - SetLookTimer(1500); - } - break; - } - } - } else { - // Because we're in a scripted fight with some particular ped. - canAffectMultiplePeople = false; - - float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude(); - if (hasShoppingBags) { - if (fightingPedDist >= 1.7f) - nextFightMove = FIGHTMOVE_SHUFFLE_F; + if (weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE || m_curFightMove < FIGHTMOVE_MELEE1) { + if (m_curFightMove == FIGHTMOVE_BACKKICK) + animAssoc->speed = 1.15f; else - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - - } else if (punchOnly) { - if (fightingPedDist >= 1.3f) - nextFightMove = FIGHTMOVE_SHUFFLE_F; - else - nextFightMove = FIGHTMOVE_PUNCHJAB; - - } else if (fightingPedDist >= 3.0f) { - nextFightMove = FIGHTMOVE_STDPUNCH; - + animAssoc->speed = 0.8f; } else { - angleToFace = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, - m_pedInObjective->GetPosition().y, - GetPosition().x, - GetPosition().y); - - nextAngle = CGeneral::LimitRadianAngle(angleToFace); - m_fRotationDest = nextAngle; - m_fRotationCur = m_fRotationDest; - PedState fightingPedState = m_pedInObjective->m_nPedState; - if (fightingPedState != PED_FALL && fightingPedState != PED_GETUP && fightingPedState != PED_DIE && fightingPedState != PED_DEAD) { - - if (fightingPedDist >= 0.8f || !canKneeHead) { - - if (fightingPedDist >= 1.3f) { - - if (fightingPedDist < 1.7f && canKick) { - nextFightMove = FIGHTMOVE_LONGKICK; - if (canRoundhouse && CGeneral::GetRandomNumber() & 1) - nextFightMove = FIGHTMOVE_ROUNDHOUSE; - - } else if (fightingPedDist < 2.0f && canKick) { - nextFightMove += 5; // Makes it 9 or 10 - - } else { - nextFightMove = FIGHTMOVE_SHUFFLE_F; - - } - } else { - nextFightMove += 2; // Makes it 6 or 7 - } - } - } else if (!CGame::nastyGame - || fightingPedDist >= 1.3f - || m_pedInObjective->IsPlayer() - || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) { - nextFightMove = FIGHTMOVE_IDLE; - } else { - nextFightMove = FIGHTMOVE_GROUNDKICK; + switch (GetWeapon()->m_eWeaponType) { + case WEAPONTYPE_SCREWDRIVER: + case WEAPONTYPE_KNIFE: + animAssoc->speed = 1.05f; + break; + case WEAPONTYPE_GOLFCLUB: + case WEAPONTYPE_NIGHTSTICK: + case WEAPONTYPE_BASEBALLBAT: + case WEAPONTYPE_HAMMER: + case WEAPONTYPE_KATANA: + animAssoc->speed = 0.8f; + break; + case WEAPONTYPE_CLEAVER: + case WEAPONTYPE_MACHETE: + animAssoc->speed = 0.9f; + break; } } - } - if (canAffectMultiplePeople) { - if (kickGround && IsPlayer()) { - m_fRotationDest = angleForGroundKick; - nextFightMove = FIGHTMOVE_GROUNDKICK; - m_fRotationCur = m_fRotationDest; - m_lookTimer = 0; - SetLookFlag(pedOnGround, true); - SetLookTimer(1500); - } else if (goForward) { - nextFightMove = FIGHTMOVE_SHUFFLE_F; - } else { - nextFightMove = FIGHTMOVE_STDPUNCH; + if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) { + animAssoc->SetRun(); + if (!IsPlayer()) + animAssoc->SetCurrentTime(0.0f); } - } - - if (nextFightMove != FIGHTMOVE_IDLE) { - m_lastFightMove = nextFightMove; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); + if (IsPlayer()) + animAssoc->SetCurrentTime(0.08f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); - if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) { - animAssoc->SetCurrentTime(0.0f); - animAssoc->SetRun(); - } m_fightButtonPressure = 0; } m_fightState = FIGHTSTATE_NO_MOVE; - } else if (m_takeAStepAfterAttack && m_lastFightMove != FIGHTMOVE_SHUFFLE_F + } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F #ifndef FIX_BUGS && CheckForPedsOnGroundToAttack(this, nil) == 4) { #else && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) { #endif - m_lastFightMove = FIGHTMOVE_SHUFFLE_F; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId); + m_lastFightMove = m_curFightMove; + m_curFightMove = FIGHTMOVE_SHUFFLE_F; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); if (animAssoc) { animAssoc->SetCurrentTime(0.0f); animAssoc->blendDelta = 4.0f; animAssoc->SetRun(); } else { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 32.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f); } animAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; @@ -7685,13 +7940,14 @@ CPed::Fight(void) } else if (m_takeAStepAfterAttack) { EndFight(ENDFIGHT_FAST); - } else if (m_lastFightMove == FIGHTMOVE_IDLE) { + } else if (m_curFightMove == FIGHTMOVE_IDLE) { if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { EndFight(ENDFIGHT_NORMAL); } } else { - m_lastFightMove = FIGHTMOVE_IDLE; + m_lastFightMove = m_curFightMove; + m_curFightMove = FIGHTMOVE_IDLE; if (IsPlayer()) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; else @@ -7781,12 +8037,13 @@ CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg) ped->bIsPedDieAnimPlaying = false; } +// --MIAMI: Done void CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg) { CPed *ped = (CPed*)arg; - if (tFightMoves[ped->m_lastFightMove].animId == animAssoc->animId) { + if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) { ped->m_fightState = FIGHTSTATE_MOVE_FINISHED; animAssoc->blendDelta = -1000.0f; } @@ -8519,6 +8776,7 @@ CPed::SeekFollowingPath(void) return &vecNextPathNode; } +// --MIAMI: Done void CPed::Flee(void) { @@ -8530,11 +8788,14 @@ CPed::Flee(void) } if (mayFinishFleeing) { + bMakeFleeScream = false; eMoveState moveState = m_nMoveState; ClearFlee(); - if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) + if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) { + bBeingChasedByPolice = false; RestorePreviousObjective(); + } if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) { SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil); @@ -8544,6 +8805,11 @@ CPed::Flee(void) m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000; } + if (bMakeFleeScream && !((CTimer::GetFrameCounter() + m_randomSeed) & 7)) { + Say(SOUND_PED_FLEE_SPRINT); + bMakeFleeScream = false; + } + if (bUsePedNodeSeek) { CPathNode *realLastNode = nil; uint8 nextDirection = 0; @@ -8567,7 +8833,7 @@ CPed::Flee(void) } if (m_pNextPathNode) { - m_vecSeekPos = m_pNextPathNode->GetPosition(); + m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); if (m_nMoveState == PEDMOVE_RUN) bIsRunning = true; @@ -8621,32 +8887,15 @@ CPed::Flee(void) m_fRotationDest -= TWOPI; } - if (CTimer::GetTimeInMilliseconds() & 0x20) { - //CVector forwardPos = GetPosition(); - CMatrix forwardMat(GetMatrix()); - forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f)); - CVector forwardPos = forwardMat.GetPosition(); - - CEntity *foundEnt; - CColPoint foundCol; - bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0); - - if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) { - m_fRotationDest += DEGTORAD(112.5f); - m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; - } - } - if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer) return; if (!m_collidingEntityWhileFleeing) return; - double damagingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; - - if (damagingThingPriorityMult <= 1.5) { + double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; + if (collidingThingPriorityMult <= 1.5) { double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints( GetPosition().x, GetPosition().y, @@ -8654,35 +8903,34 @@ CPed::Flee(void) m_collidingEntityWhileFleeing->GetPosition().y); angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity); - // It includes projectiles, but is everything collides with us included? - double angleToFleeDamagingThing = CGeneral::GetRadianAngleBetweenPoints( + double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints( m_vecDamageNormal.x, m_vecDamageNormal.y, 0.0f, 0.0f); - angleToFleeDamagingThing = CGeneral::LimitRadianAngle(angleToFleeDamagingThing); + angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing); - if (angleToFleeEntity - PI > angleToFleeDamagingThing) - angleToFleeDamagingThing += TWOPI; - else if (PI + angleToFleeEntity < angleToFleeDamagingThing) - angleToFleeDamagingThing -= TWOPI; + if (angleToFleeEntity - PI > angleToFleeCollidingThing) + angleToFleeCollidingThing += TWOPI; + else if (PI + angleToFleeEntity < angleToFleeCollidingThing) + angleToFleeCollidingThing -= TWOPI; - if (damagingThingPriorityMult <= 1.0f) { + if (collidingThingPriorityMult <= 1.0f) { // Range [0.0, 1.0] - float angleToFleeBoth = (angleToFleeDamagingThing + angleToFleeEntity) * 0.5f; + float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f; if (m_fRotationDest - PI > angleToFleeBoth) angleToFleeBoth += TWOPI; else if (PI + m_fRotationDest < angleToFleeBoth) angleToFleeBoth -= TWOPI; - m_fRotationDest = (1.0f - damagingThingPriorityMult) * m_fRotationDest + damagingThingPriorityMult * angleToFleeBoth; + m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth; } else { // Range (1.0, 1.5] - double adjustedMult = (damagingThingPriorityMult - 1.0f) * 2.0f; - m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeDamagingThing; + double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f; + m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing; } } else { m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( @@ -9726,8 +9974,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) CPed::InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); CPed::SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); - if ((m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD) - && !m_pCollidingEntity && + if (OnGround() && !m_pCollidingEntity && (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) { m_pCollidingEntity = car; @@ -11394,7 +11641,7 @@ CPed::ProcessControl(void) break; case PED_FLEE_ENTITY: if (!m_fleeFrom) { - b157_10 = false; + bMakeFleeScream = false; SetIdle(); break; } @@ -11581,7 +11828,7 @@ CPed::ProcessControl(void) if (bInVehicle && !m_pMyVehicle) bInVehicle = false; - if (b156_8) { + if (bHeldHostageInCar) { if (m_pMyVehicle && m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->IsPlayer()) { Say(SOUND_PED_FLEE_SPRINT); } @@ -12247,27 +12494,34 @@ CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) } } +// --MIAMI: Done void CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) { CPed* ped = (CPed*)arg; CVehicle* veh = ped->m_pMyVehicle; - if (animAssoc) + if (animAssoc) { + if ((animAssoc->animId == ANIM_CAR_ROLLOUT_LHS || animAssoc->animId == ANIM_CAR_ROLLOUT_RHS) && ped && ped->m_nPedState == PED_FALL) { + ped->RestoreHeadingRate(); + return; + } animAssoc->blendDelta = -1000.0f; + if (animAssoc->animId == ANIM_BIKE_GETOFF_BACK) + ped->RestoreHeadingRate(); + } if (!veh) { PedSetOutCarCB(nil, ped); return; } -#ifdef VC_PED_PORTS CVector posForZ = ped->GetPosition(); CPedPlacement::FindZCoorForPed(&posForZ); if (ped->GetPosition().z - 0.5f > posForZ.z) { PedSetOutCarCB(nil, ped); return; } -#endif + veh->m_nStaticFrames = 0; veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f); veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f); @@ -12340,10 +12594,8 @@ CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg) } } -#ifdef VC_PED_PORTS if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) closeDoor = false; -#endif if (!closeDoor) { if (!veh->IsDoorMissing(door) && !veh->bIsBus) { @@ -12664,7 +12916,7 @@ CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg) if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) { for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) { CPed *passenger = veh->pPassengers[i]; - if (passenger && !passenger->bStayInCarOnJack && !passenger->b156_8 && (passenger->m_leader != ped || !ped->bIsLeader)) { + if (passenger && !passenger->bStayInCarOnJack && !passenger->bHeldHostageInCar && (passenger->m_leader != ped || !ped->bIsLeader)) { passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh); passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds(); } @@ -13095,10 +13347,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) ped->RestartNonPartialAnims(); ped->m_pVehicleAnim = nil; - CVector posFromZ = ped->GetPosition(); - CPedPlacement::FindZCoorForPed(&posFromZ); ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - ped->SetPosition(posFromZ); veh = ped->m_pMyVehicle; if (veh) { if (ped->m_nPedType == PEDTYPE_PROSTITUTE) { @@ -13113,7 +13362,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) } } } - if (veh->IsBike()) + if (veh && veh->IsBike()) veh->m_nGettingOutFlags &= ~GetBikeDoorFlag(ped->m_vehEnterType); else veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType); @@ -13168,6 +13417,7 @@ CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg) if (createdBy == MISSION_CHAR && !startedToRun) ped->SetMoveState(PEDMOVE_WALK); } + ped->bHeldHostageInCar = false; } // --MIAMI: Done, but enumarate weapon slots @@ -14839,10 +15089,9 @@ CPed::ProcessObjective(void) // fall through case OBJECTIVE_LEAVE_CAR: if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (InVehicle() - && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() - || bBusJacked) - ) { + if (InVehicle() && + (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() || bBusJacked)) { + if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN && (m_nPedType != PEDTYPE_COP || m_pMyVehicle->IsBoat() @@ -14861,7 +15110,7 @@ CPed::ProcessObjective(void) RestorePreviousObjective(); } } - if (b156_8) { + if (bHeldHostageInCar) { if (CTheScripts::IsPlayerOnAMission()) { CVehicle *playerVeh = FindPlayerVehicle(); if (playerVeh && playerVeh->IsPassenger(this)) { @@ -15088,7 +15337,12 @@ CPed::ProcessObjective(void) else { GetPedAttractorManager()->DeRegisterPed(this, m_attractor); SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus); - bDontDragMeOutCar = true; // TODO(MIAMI): check, add more flags + bDontDragMeOutCar = true; + b157_40 = true; + CPlayerPed *player = FindPlayerPed(); + if (pBus->IsPassenger(player) || pBus->IsDriver(player)) { + b158_10 = true; + } } } } @@ -16383,7 +16637,7 @@ CPed::PreRender(void) CVector speed = FindPlayerSpeed(); if (Abs(speed.x) <= 0.05f && Abs(speed.y) <= 0.05f) { - if (m_nPedState != PED_FALL && !DyingOrDead() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + if (!OnGround() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { if (!IsPedHeadAbovePos(0.3f) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED)) { doSplashUp = false; } @@ -17141,13 +17395,27 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) uint32 optedDoorNode = wantedDoorNode; bool teleportNeeded = false; bool isLow = !!veh->bLowVehicle; -// TODO(MIAMI): argument - if (!veh->CanPedExitCar(false)) { - if (veh->pDriver && !veh->pDriver->IsPlayer()) { - veh->AutoPilot.m_nCruiseSpeed = 0; - veh->AutoPilot.m_nCarMission = MISSION_NONE; + + bool canJumpOut = false; + if (!veh->CanPedExitCar(false) && !bBusJacked) { + if (IsPlayer()) { + // TODO(Miami): Do jumping out of car + canJumpOut = false; + } + if (!canJumpOut) { + if (veh->pDriver) { + if (veh->pDriver->IsPlayer()) { + if (veh->pDriver != this) { + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 5000; + bHeldHostageInCar = true; + } + } else { + veh->AutoPilot.m_nCruiseSpeed = 0; + veh->AutoPilot.m_nCarMission = MISSION_NONE; + } + } + return; } - return; } if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) @@ -17312,9 +17580,9 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) SetPedState(PED_EXIT_CAR); if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL) m_pVehicleAnim->blendDelta = -1000.0f; + RemoveInCarAnims(); SetMoveState(PEDMOVE_NONE); CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); - RemoveInCarAnims(); veh->AutoPilot.m_nCruiseSpeed = 0; if (teleportNeeded) { PedSetOutCarCB(nil, this); @@ -18051,7 +18319,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) Say(SOUND_PED_DEFEND); switch (hitLevel) { case HITLEVEL_GROUND: - m_lastFightMove = FIGHTMOVE_HITONFLOOR; + m_curFightMove = FIGHTMOVE_HITONFLOOR; break; case HITLEVEL_LOW: if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) { @@ -18063,52 +18331,52 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) Say(SOUND_PED_DEFEND); return; } - m_lastFightMove = FIGHTMOVE_HITBODY; + m_curFightMove = FIGHTMOVE_HITBODY; break; case HITLEVEL_HIGH: switch (direction) { case 1: - m_lastFightMove = FIGHTMOVE_HITLEFT; + m_curFightMove = FIGHTMOVE_HITLEFT; break; case 2: - m_lastFightMove = FIGHTMOVE_HITBACK; + m_curFightMove = FIGHTMOVE_HITBACK; break; case 3: - m_lastFightMove = FIGHTMOVE_HITRIGHT; + m_curFightMove = FIGHTMOVE_HITRIGHT; break; default: if (unk <= 5) - m_lastFightMove = FIGHTMOVE_HITHEAD; + m_curFightMove = FIGHTMOVE_HITHEAD; else - m_lastFightMove = FIGHTMOVE_HITBIGSTEP; + m_curFightMove = FIGHTMOVE_HITBIGSTEP; break; } break; default: switch (direction) { case 1: - m_lastFightMove = FIGHTMOVE_HITLEFT; + m_curFightMove = FIGHTMOVE_HITLEFT; break; case 2: - m_lastFightMove = FIGHTMOVE_HITBACK; + m_curFightMove = FIGHTMOVE_HITBACK; break; case 3: - m_lastFightMove = FIGHTMOVE_HITRIGHT; + m_curFightMove = FIGHTMOVE_HITRIGHT; break; default: if (unk <= 5) - m_lastFightMove = FIGHTMOVE_HITCHEST; + m_curFightMove = FIGHTMOVE_HITCHEST; else - m_lastFightMove = FIGHTMOVE_HITBIGSTEP; + m_curFightMove = FIGHTMOVE_HITBIGSTEP; break; } break; } if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f)) - m_lastFightMove = FIGHTMOVE_HITONFLOOR; + m_curFightMove = FIGHTMOVE_HITONFLOOR; if (m_nPedState == PED_FIGHT) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); moveAssoc->SetCurrentTime(0.0f); moveAssoc->SetFinishCallback(FinishFightMoveCB, this); if (IsPlayer()) @@ -18119,7 +18387,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) } else if (IsPlayer() && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bFightMode) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); moveAssoc->SetCurrentTime(0.0f); moveAssoc->speed = 1.2f; @@ -18133,7 +18401,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) } SetPedState(PED_FIGHT); m_fightButtonPressure = 0; - m_lastHitState = 2; + m_lastFightMove = FIGHTMOVE_IDLE; RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT); CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START); if (walkStartAssoc) { @@ -18163,7 +18431,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE); } fightIdleAssoc->blendAmount = 1.0f; - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); moveAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; m_takeAStepAfterAttack = false; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index d5062ee1..c8621c82 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -98,7 +98,6 @@ enum PedFightMoves FIGHTMOVE_PUNCHHOOK, FIGHTMOVE_PUNCHJAB, FIGHTMOVE_PUNCH, - FIGHTMOVE_BODYBLOW = FIGHTMOVE_PUNCH, FIGHTMOVE_LONGKICK, FIGHTMOVE_ROUNDHOUSE, // Directionals @@ -457,7 +456,7 @@ public: uint32 bIsDrowning : 1; uint32 bDrownsInWater : 1; //uint32 b156_4 - uint32 b156_8 : 1; + uint32 bHeldHostageInCar : 1; uint32 bIsPlayerFriend : 1; uint32 bHeadStuckInCollision : 1; uint32 bDeadPedInFrontOfCar : 1; @@ -467,7 +466,7 @@ public: uint32 bDoomAim : 1; uint32 bCanBeShotInVehicle : 1; //uint32 b157_8 - uint32 b157_10 : 1; + uint32 bMakeFleeScream : 1; uint32 bPushedAlongByCar : 1; uint32 b157_40 : 1; uint32 bIgnoreThreatsBehindObjects : 1; @@ -482,7 +481,6 @@ public: //uint32 b158_80 // our own flags - uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle uint8 m_gangFlags; @@ -590,8 +588,8 @@ public: uint8 m_wepAccuracy; CEntity *m_pPointGunAt; CVector m_vecHitLastPos; + uint32 m_curFightMove; uint32 m_lastFightMove; - uint32 m_lastHitState; // TODO(Miami): What's this? uint8 m_fightButtonPressure; FightState m_fightState; bool m_takeAStepAfterAttack; @@ -757,6 +755,8 @@ public: void SetWaitState(eWaitState, void*); bool FightStrike(CVector&, bool); void FightHitPed(CPed*, CVector&, CVector&, int16); + int32 ChooseAttackPlayer(uint8, bool); + int32 ChooseAttackAI(uint8, bool); int GetLocalDirection(const CVector2D &); void StartFightDefend(uint8, uint8, uint8); void PlayHitSound(CPed*); @@ -960,6 +960,7 @@ public: bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool OnGroundOrGettingUp(void) { return OnGround() || m_nPedState == PED_GETUP; } bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. @@ -1028,6 +1029,20 @@ public: else return (AnimationId)0; } + + static AnimationId GetFinishingAttackAnim(CWeaponInfo* weapon) { + if (!!weapon->m_bFinish3rd) + return ANIM_MELEE_ATTACK_FINISH; + else + return (AnimationId)0; + } + + static AnimationId GetSecondFireAnim(CWeaponInfo* weapon) { + if (!!weapon->m_bUse2nd) + return ANIM_WEAPON_FIRE_2ND; // or ANIM_MELEE_ATTACK_2ND + else + return (AnimationId)0; + } // -- // My additions, because there were many, many instances of that. diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 35689e4e..98974bd3 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -784,6 +784,7 @@ CPlayerPed::PlayerControlM16(CPad *padUsed) GetWeapon()->Update(m_audioEntityId, nil); } +// --MIAMI: Done void CPlayerPed::PlayerControlFighter(CPad *padUsed) { @@ -809,6 +810,7 @@ CPlayerPed::PlayerControlFighter(CPad *padUsed) } } +// --MIAMI: Done void CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) { diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 18a0c963..d3b1499a 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -559,16 +559,23 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree CZoneInfo zoneInfo; CPed *gangLeader = nil; bool addCop = false; + bool forceAddingCop = false; CPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus]; CVector playerCentreOfWorld = FindPlayerCentreOfWorld(CWorld::PlayerInFocus); CTheZones::GetZoneInfoForTimeOfDay(&playerCentreOfWorld, &zoneInfo); CWanted *wantedInfo = playerInfo->m_pPed->m_pWanted; + if (wantedInfo->m_nWantedLevel > 2) { - if (ms_nNumCop < wantedInfo->m_MaxCops && !playerInfo->m_pPed->bInVehicle - && (CCarCtrl::NumLawEnforcerCars >= wantedInfo->m_MaximumLawEnforcerVehicles + if (!CGame::IsInInterior() && (CGeneral::GetRandomNumber() % 32 == 0) && FindPlayerVehicle()) + forceAddingCop = true; + + uint32 maxCops = CGame::IsInInterior() ? wantedInfo->m_MaxCops * 1.6f : wantedInfo->m_MaxCops; + if ((ms_nNumCop < maxCops || forceAddingCop) && + (!playerInfo->m_pPed->bInVehicle && + (CCarCtrl::NumLawEnforcerCars >= wantedInfo->m_MaximumLawEnforcerVehicles || CCarCtrl::NumRandomCars >= playerInfo->m_nTrafficMultiplier * CCarCtrl::CarDensityMultiplier || CCarCtrl::NumFiretrucksOnDuty + CCarCtrl::NumAmbulancesOnDuty + CCarCtrl::NumParkedCars - + CCarCtrl::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse)) { + + CCarCtrl::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse) || forceAddingCop)) { addCop = true; minDist = PedCreationDistMultiplier() * MIN_CREATION_DIST; maxDist = PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE); @@ -693,6 +700,9 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree if (!farEnoughToAdd) break; CPed *newPed = AddPed((ePedType)pedTypeToAdd, modelToAdd, generatedCoors); + if (forceAddingCop && newPed->m_nPedType == PEDTYPE_COP) + ((CCopPed*)newPed)->m_bThrowsSpikeTrap = true; + newPed->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8)); if (i != 0) { @@ -721,10 +731,11 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree } } +// TODO(Miami) CPed* CPopulation::AddPedInCar(CVehicle* car, bool isDriver) { - int defaultModel = MI_MALE01; + const int defaultModel = MI_MALE01; int miamiViceIndex = 0; bool imSureThatModelIsLoaded = true; CVector coors = FindPlayerCoors(); @@ -744,10 +755,6 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver) preferredModel = 0; pedType = PEDTYPE_EMERGENCY; break; - case MI_FBICAR: - preferredModel = COP_FBI; - pedType = PEDTYPE_COP; - break; case MI_POLICE: case MI_PREDATOR: preferredModel = COP_STREET; @@ -762,24 +769,24 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver) preferredModel = COP_ARMY; pedType = PEDTYPE_COP; break; - case MI_VICECHEE: // TODO(MIAMI): figure out new structure of the function - preferredModel = COP_MIAMIVICE; + case MI_FBIRANCH: + preferredModel = COP_FBI; pedType = PEDTYPE_COP; - miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); break; - case MI_TAXI: - case MI_CABBIE: - case MI_ZEBRA: - case MI_KAUFMAN: - if (CGeneral::GetRandomTrueFalse()) { - pedType = PEDTYPE_CIVMALE; - preferredModel = MI_TAXI_D; + default: + if (car->GetModelIndex() == MI_TAXI || car->GetModelIndex() == MI_CABBIE || car->GetModelIndex() == MI_ZEBRA || car->GetModelIndex() == MI_KAUFMAN) { + if (isDriver) { + pedType = PEDTYPE_CIVMALE; + preferredModel = MI_TAXI_D; + break; + } + } else if (car->GetModelIndex() == MI_VICECHEE && car->bIsLawEnforcer) { + preferredModel = COP_MIAMIVICE; + pedType = PEDTYPE_COP; + miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1); break; } - defaultModel = MI_TAXI_D; - // fall through - default: int gangOfPed = 0; imSureThatModelIsLoaded = false; @@ -798,8 +805,12 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver) if (preferredModel == -1) preferredModel = defaultModel; - if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModelInfo->m_vehicleClass)) - break; + if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->GetRwObject()) { + if (!car->IsPassenger(preferredModel) && !car->IsDriver(preferredModel)) { + if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModelInfo->m_vehicleClass)) + break; + } + } } if (i == -1) preferredModel = defaultModel; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 21d862af..6a3cdeaa 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -70,6 +70,7 @@ bool CHud::m_Wants_To_Draw_Hud; bool CHud::m_Wants_To_Draw_3dMarkers; wchar CHud::m_BigMessage[6][128]; int16 CHud::m_ItemToFlash; +bool CHud::m_HideRadar; // These aren't really in CHud float CHud::BigMessageInUse[6]; @@ -902,20 +903,25 @@ void CHud::Draw() /* DrawRadar */ - if (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR) { + if (FrontEndMenuManager.m_PrefsRadarMode != 2 && + !m_HideRadar && (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR)) { + + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); CRadar::DrawMap(); - CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); + if (FrontEndMenuManager.m_PrefsRadarMode != 1) { + CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT)); #ifdef FIX_BUGS - rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #else - rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); + rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT)); #endif - rect.Grow(6.0f); - rect.Translate(0.0f, 2.0f); - Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); - rect.Translate(0.0f, -2.0f); - Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + rect.Grow(6.0f); + rect.Translate(0.0f, 2.0f); + Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255)); + rect.Translate(0.0f, -2.0f); + Sprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR); + } CRadar::DrawBlips(); } } @@ -1570,6 +1576,7 @@ void CHud::Initialise() m_WeaponFadeTimer = 0; m_WeaponTimer = 0; + m_HideRadar = false; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; m_LastWanted = 0; @@ -1617,6 +1624,7 @@ void CHud::ReInitialise() { m_WeaponFadeTimer = 0; m_WeaponTimer = 0; + m_HideRadar = false; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; m_LastWanted = 0; } diff --git a/src/render/Hud.h b/src/render/Hud.h index f8ca4f6d..c6aff654 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -85,6 +85,7 @@ public: static bool m_Wants_To_Draw_3dMarkers; static wchar m_BigMessage[6][128]; static int16 m_ItemToFlash; + static bool m_HideRadar; // These aren't really in CHud static float BigMessageInUse[6]; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 217b383f..fc856de1 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -1349,7 +1349,7 @@ CAutomobile::ProcessControl(void) if(!IsAlarmOn()) ReduceHornCounter(); }else{ - if(UsesSiren(GetModelIndex())){ + if(UsesSiren()){ if(Pads[0].bHornHistory[Pads[0].iCurrHornHistory]){ if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] && Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+3) % 5]) @@ -1559,7 +1559,7 @@ CAutomobile::ProcessControl(void) if(m_bSirenOrAlarm && (CTimer::GetFrameCounter()&7) == 5 && - UsesSiren(GetModelIndex()) && GetModelIndex() != MI_MRWHOOP) + UsesSiren() && GetModelIndex() != MI_MRWHOOP) CCarAI::MakeWayForCarWithSiren(this); diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index c8fa1c22..83c727f5 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -460,7 +460,7 @@ bool CCrane::DoesCranePickUpThisCarType(uint32 mi) return mi == MI_FIRETRUCK || mi == MI_AMBULAN || mi == MI_ENFORCER || - mi == MI_FBICAR || + mi == MI_FBIRANCH || mi == MI_RHINO || mi == MI_BARRACKS || mi == MI_POLICE; @@ -474,7 +474,7 @@ bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi) case MI_FIRETRUCK: return (CarsCollectedMilitaryCrane & 1); case MI_AMBULAN: return (CarsCollectedMilitaryCrane & 2); case MI_ENFORCER: return (CarsCollectedMilitaryCrane & 4); - case MI_FBICAR: return (CarsCollectedMilitaryCrane & 8); + case MI_FBIRANCH: return (CarsCollectedMilitaryCrane & 8); case MI_RHINO: return (CarsCollectedMilitaryCrane & 0x10); case MI_BARRACKS: return (CarsCollectedMilitaryCrane & 0x20); case MI_POLICE: return (CarsCollectedMilitaryCrane & 0x40); @@ -489,7 +489,7 @@ void CCranes::RegisterCarForMilitaryCrane(uint32 mi) case MI_FIRETRUCK: CarsCollectedMilitaryCrane |= 1; break; case MI_AMBULAN: CarsCollectedMilitaryCrane |= 2; break; case MI_ENFORCER: CarsCollectedMilitaryCrane |= 4; break; - case MI_FBICAR: CarsCollectedMilitaryCrane |= 8; break; + case MI_FBIRANCH: CarsCollectedMilitaryCrane |= 8; break; case MI_RHINO: CarsCollectedMilitaryCrane |= 0x10; break; case MI_BARRACKS: CarsCollectedMilitaryCrane |= 0x20; break; case MI_POLICE: CarsCollectedMilitaryCrane |= 0x40; break; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index e26fd99f..2c296ee2 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1512,7 +1512,7 @@ CVehicle::MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&pl for(i = 0; i < numPeds2; i++) if(peds2[i]->IsFemale() || CGeneral::GetRandomTrueFalse()){ peds2[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 10000; - peds2[i]->b156_8 = true; + peds2[i]->bHeldHostageInCar = true; peds2[i]->bFleeAfterExitingCar = true; } } @@ -1557,9 +1557,9 @@ CVehicle::IsLawEnforcementVehicle(void) } bool -CVehicle::UsesSiren(uint32 id) +CVehicle::UsesSiren(void) { - switch(id){ + switch(GetModelIndex()){ case MI_FIRETRUCK: case MI_AMBULAN: case MI_FBICAR: diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index b1e3d803..34106327 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -345,7 +345,7 @@ public: int FindTyreNearestPoint(float x, float y); bool IsLawEnforcementVehicle(void); void ChangeLawEnforcerState(uint8 enable); - bool UsesSiren(uint32 id); + bool UsesSiren(void); bool IsVehicleNormal(void); bool CarHasRoof(void); bool IsUpsideDown(void); From cf69f22a0ce5b808a4d945a5cef1d9d4c51c0b5c Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 9 Jul 2020 19:18:42 +0300 Subject: [PATCH 32/85] Remove island loading --- src/control/Script.cpp | 10 ++++++++++ src/core/Collision.cpp | 29 +++++++++++++++++++++++++++-- src/core/Streaming.cpp | 14 +++++++++++++- src/core/config.h | 1 + src/modelinfo/ModelInfo.cpp | 2 ++ src/render/Renderer.cpp | 10 +++++++++- src/save/GenericGameStorage.cpp | 5 ++++- 7 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 4de45e0d..3309dbd2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -10027,11 +10027,15 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CollectParameters(&m_nIp, 1); CTimer::Stop(); CGame::currLevel = (eLevelName)ScriptParams[0]; +#ifndef NO_ISLAND_LOADING CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); +#endif CCollision::SortOutCollisionAfterLoad(); +#ifndef NO_ISLAND_LOADING CStreaming::RequestIslands(CGame::currLevel); CStreaming::LoadAllRequestedModels(true); +#endif CTimer::Update(); return 0; } @@ -10647,18 +10651,24 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CTimer::Stop(); CGame::currLevel = (eLevelName)ScriptParams[0]; if (CGame::currLevel != CCollision::ms_collisionInMemory) { +#ifndef NO_ISLAND_LOADING DMAudio.SetEffectsFadeVol(0); CPad::StopPadsShaking(); CCollision::LoadCollisionScreen(CGame::currLevel); DMAudio.Service(); +#endif CPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false); +#ifndef NO_ISLAND_LOADING CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); +#endif CCollision::SortOutCollisionAfterLoad(); +#ifndef NO_ISLAND_LOADING CStreaming::RequestIslands(CGame::currLevel); CStreaming::RequestBigBuildings(CGame::currLevel); CStreaming::LoadAllRequestedModels(true); DMAudio.SetEffectsFadeVol(127); +#endif } CTimer::Update(); return 0; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 23eaa8dd..cb8b4189 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -180,12 +180,16 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) if(level == CGame::currLevel || forceChange){ CTimer::Stop(); +#ifndef NO_ISLAND_LOADING DMAudio.SetEffectsFadeVol(0); CPad::StopPadsShaking(); LoadCollisionScreen(CGame::currLevel); DMAudio.Service(); +#endif CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false); + +#ifndef NO_ISLAND_LOADING CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); @@ -196,19 +200,27 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) CStreaming::RemoveUnusedModelsInLoadedList(); CGame::TidyUpMemory(true, true); CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); +#endif + ms_collisionInMemory = CGame::currLevel; CReplay::EmptyReplayBuffer(); +#ifndef NO_ISLAND_LOADING if(CGame::currLevel != LEVEL_NONE) LoadSplash(GetLevelSplashScreen(CGame::currLevel)); CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); CStreaming::RequestBigBuildings(CGame::currLevel); +#endif CStreaming::LoadAllRequestedModels(true); +#ifndef NO_ISLAND_LOADING CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); CGame::TidyUpMemory(true, true); +#endif CTimer::Update(); +#ifndef NO_ISLAND_LOADING DMAudio.SetEffectsFadeVol(127); +#endif } } @@ -217,10 +229,23 @@ CCollision::SortOutCollisionAfterLoad(void) { if(ms_collisionInMemory == CGame::currLevel) return; - +#ifndef NO_ISLAND_LOADING CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); - if(CGame::currLevel != LEVEL_NONE){ +#endif + if (CGame::currLevel != LEVEL_NONE) { +#ifdef NO_ISLAND_LOADING + static bool bAlreadyLoaded = false; + if (bAlreadyLoaded) { + ms_collisionInMemory = CGame::currLevel; + return; + } + bAlreadyLoaded = true; + CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL); + CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL); + CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN); +#else CFileLoader::LoadCollisionFromDatFile(CGame::currLevel); +#endif if(!CGame::playingIntro) LoadSplash(GetLevelSplashScreen(CGame::currLevel)); } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index c961f53d..b701f43f 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -725,7 +725,11 @@ CStreaming::RequestBigBuildings(eLevelName level) n = CPools::GetBuildingPool()->GetSize()-1; for(i = n; i >= 0; i--){ b = CPools::GetBuildingPool()->GetSlot(i); - if(b && b->bIsBIGBuilding && b->m_level == level) + if(b && b->bIsBIGBuilding +#ifndef NO_ISLAND_LOADING + && b->m_level == level +#endif + ) RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); } RequestIslands(level); @@ -735,6 +739,7 @@ CStreaming::RequestBigBuildings(eLevelName level) void CStreaming::RequestIslands(eLevelName level) { +#ifndef NO_ISLAND_LOADING switch(level){ case LEVEL_INDUSTRIAL: RequestModel(islandLODcomInd, BIGBUILDINGFLAGS); @@ -750,6 +755,7 @@ CStreaming::RequestIslands(eLevelName level) break; default: break; } +#endif } void @@ -935,12 +941,14 @@ CStreaming::RemoveBuildings(eLevelName level) void CStreaming::RemoveUnusedBigBuildings(eLevelName level) { +#ifndef NO_ISLAND_LOADING if(level != LEVEL_INDUSTRIAL) RemoveBigBuildings(LEVEL_INDUSTRIAL); if(level != LEVEL_COMMERCIAL) RemoveBigBuildings(LEVEL_COMMERCIAL); if(level != LEVEL_SUBURBAN) RemoveBigBuildings(LEVEL_SUBURBAN); +#endif RemoveIslandsNotUsed(level); } @@ -960,6 +968,7 @@ DeleteIsland(CEntity *island) void CStreaming::RemoveIslandsNotUsed(eLevelName level) { +#ifndef NO_ISLAND_LOADING switch(level){ case LEVEL_INDUSTRIAL: DeleteIsland(pIslandLODindustEntity); @@ -977,13 +986,16 @@ CStreaming::RemoveIslandsNotUsed(eLevelName level) DeleteIsland(pIslandLODcomIndEntity); break; default: +#endif // !NO_ISLAND_LOADING DeleteIsland(pIslandLODindustEntity); DeleteIsland(pIslandLODcomIndEntity); DeleteIsland(pIslandLODcomSubEntity); DeleteIsland(pIslandLODsubIndEntity); DeleteIsland(pIslandLODsubComEntity); +#ifndef NO_ISLAND_LOADING break; } +#endif // !NO_ISLAND_LOADING } void diff --git a/src/core/config.h b/src/core/config.h index 9d9577ff..5010ed3d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -198,6 +198,7 @@ enum Config { #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number +#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL // Particle diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index da09bdfa..713600fd 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -217,6 +217,7 @@ CModelInfo::IsBikeModel(int32 id) void CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level) { +#ifndef NO_ISLAND_LOADING int i; CBaseModelInfo *mi; CColModel *colmodel; @@ -229,6 +230,7 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level) colmodel->RemoveCollisionVolumes(); } } +#endif } void diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8a48eb11..53181e52 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -700,8 +700,16 @@ CRenderer::ScanWorld(void) poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y); } ScanSectorPoly(poly, 3, ScanSectorList); - +#ifdef NO_ISLAND_LOADING + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL)); + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_COMMERCIAL)); + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_SUBURBAN)); +#else + #ifdef FIX_BUGS + if (CCollision::ms_collisionInMemory != LEVEL_NONE) + #endif ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory)); +#endif ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_NONE)); } } diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index eff0f2ff..1ac17982 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -562,14 +562,17 @@ RestoreForStartLoad() ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().x); ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().y); ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z); +#ifndef NO_ISLAND_LOADING CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); +#endif CCollision::SortOutCollisionAfterLoad(); +#ifndef NO_ISLAND_LOADING CStreaming::RequestBigBuildings(CGame::currLevel); CStreaming::LoadAllRequestedModels(false); CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); CGame::TidyUpMemory(true, false); - +#endif if (CloseFile(file)) { return true; } else { From c012e5a7ffa4a1d2d4a0d67a7aeacf973d9f8db4 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 9 Jul 2020 20:40:15 +0300 Subject: [PATCH 33/85] Disable loading screen --- src/core/config.h | 3 ++- src/core/main.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/config.h b/src/core/config.h index 5010ed3d..b43fc90b 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -198,7 +198,8 @@ enum Config { #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number -#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU +#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time +#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL // Particle diff --git a/src/core/main.cpp b/src/core/main.cpp index 1e26381a..2608612a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -471,6 +471,7 @@ ResetLoadingScreenBar() void LoadingScreen(const char *str1, const char *str2, const char *splashscreen) { +#ifndef DISABLE_LOADING_SCREEN CSprite2d *splash; #ifndef RANDOMSPLASH @@ -534,6 +535,7 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) CFont::DrawFonts(); DoRWStuffEndOfFrame(); } +#endif } void From aabf0f4c2c5b7b4b5dd528653b7fd6c755ecbfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 9 Jul 2020 21:48:43 +0300 Subject: [PATCH 34/85] keep loading screen, but for a second --- src/core/main.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 2608612a..f8a3bd0d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -467,13 +467,16 @@ ResetLoadingScreenBar() NumberOfChunksLoaded = 0.0f; } -// TODO: compare with PS2 void LoadingScreen(const char *str1, const char *str2, const char *splashscreen) { -#ifndef DISABLE_LOADING_SCREEN CSprite2d *splash; +#ifdef DISABLE_LOADING_SCREEN + if (str1 && str2) + return; +#endif + #ifndef RANDOMSPLASH if(CGame::frenchGame || CGame::germanGame || !CGame::nastyGame) splashscreen = "mainsc2"; @@ -535,7 +538,6 @@ LoadingScreen(const char *str1, const char *str2, const char *splashscreen) CFont::DrawFonts(); DoRWStuffEndOfFrame(); } -#endif } void From 00bba630f6e070a94af498812bd555e2fd4d9ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 10 Jul 2020 12:28:00 +0300 Subject: [PATCH 35/85] enable island loading for now --- src/core/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config.h b/src/core/config.h index b43fc90b..f2716783 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -199,7 +199,7 @@ enum Config { #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time -#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU +//#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL // Particle From 6eb8f6ae5a87fe32c93388e67559da988f48fb7f Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 11 Jul 2020 12:03:56 +0300 Subject: [PATCH 36/85] Add cutscene borders switch to the menu --- src/core/Frontend.cpp | 10 ++++++++++ src/core/Frontend.h | 4 ++++ src/core/config.h | 1 + src/core/main.cpp | 12 ++++++++++-- src/core/re3.cpp | 14 ++++++++++++++ src/render/Draw.cpp | 6 +++++- 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 841f6bbb..e67e939a 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -112,6 +112,10 @@ int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; int32 CMenuManager::m_PrefsMusicVolume = 102; int32 CMenuManager::m_PrefsSfxVolume = 102; +#ifdef CUTSCENE_BORDERS_SWITCH +bool CMenuManager::m_PrefsCutsceneBorders = true; +#endif + char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME; int32 CMenuManager::m_KeyPressedCode = -1; @@ -3217,6 +3221,9 @@ CMenuManager::LoadSettings() CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); #ifdef FREE_CAM CFileMgr::Read(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#endif +#ifdef CUTSCENE_BORDERS_SWITCH + CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); #endif } } @@ -3310,6 +3317,9 @@ CMenuManager::SaveSettings() CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); #ifdef FREE_CAM CFileMgr::Write(fileHandle, (char*)&TheCamera.bFreeCam, 1); +#endif +#ifdef CUTSCENE_BORDERS_SWITCH + CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsCutsceneBorders, 1); #endif } diff --git a/src/core/Frontend.h b/src/core/Frontend.h index b07f7260..758e29aa 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -582,6 +582,10 @@ public: static uint8 m_PrefsPlayerGreen; static uint8 m_PrefsPlayerBlue; +#ifdef CUTSCENE_BORDERS_SWITCH + static bool m_PrefsCutsceneBorders; +#endif + #ifndef MASTER static bool m_PrefsMarketing; static bool m_PrefsDisableTutorials; diff --git a/src/core/config.h b/src/core/config.h index f2716783..2ba7a021 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -201,6 +201,7 @@ enum Config { #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time //#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU //#define USE_TEXTURE_POOL +#define CUTSCENE_BORDERS_SWITCH // Particle //#define PC_PARTICLE diff --git a/src/core/main.cpp b/src/core/main.cpp index f8a3bd0d..a1c64a6d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -254,7 +254,11 @@ DoFade(void) fadeColor.a = alpha; } - if(TheCamera.m_WideScreenOn){ + if(TheCamera.m_WideScreenOn +#ifdef CUTSCENE_BORDERS_SWITCH + && CMenuManager::m_PrefsCutsceneBorders +#endif + ){ // what's this? float y = SCREEN_HEIGHT/2 * TheCamera.m_ScreenReductionPercentage/100.0f; rect.left = 0.0f; @@ -862,7 +866,11 @@ Render2dStuff(void) CReplay::Display(); CPickups::RenderPickUpText(); - if(TheCamera.m_WideScreenOn) + if(TheCamera.m_WideScreenOn +#ifdef CUTSCENE_BORDERS_SWITCH + && CMenuManager::m_PrefsCutsceneBorders +#endif + ) TheCamera.DrawBordersForWideScreen(); CPed *player = FindPlayerPed(); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 7aa6800e..d6319f3a 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -132,6 +132,14 @@ void ToggleFreeCam(int8 action) } #endif +#ifdef CUTSCENE_BORDERS_SWITCH +void BorderModeChange(int8 displayedValue) +{ + CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; + FrontEndMenuManager.SaveSettings(); +} +#endif + // Reloaded on language change, so you can use hardcoded wchar* and TheText.Get with peace of mind void CustomFrontendOptionsPopulate(void) @@ -161,6 +169,12 @@ CustomFrontendOptionsPopulate(void) FrontendOptionSetPosition(MENUPAGE_CONTROLLER_PC, 1); FrontendOptionAddDynamic(text, nil, ToggleFreeCam, nil); #endif + +#ifdef CUTSCENE_BORDERS_SWITCH + static const wchar *off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") }; + FrontendOptionSetPosition(MENUPAGE_GRAPHICS_SETTINGS, 9); + FrontendOptionAddSelect((const wchar *)L"CUTSCENE BORDERS", off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil); +#endif } #endif diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index bb37a3a3..db87e76d 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -3,6 +3,7 @@ #include "Draw.h" #include "Frontend.h" #include "Camera.h" +#include "CutsceneMgr.h" #ifdef ASPECT_RATIO_SCALE float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO; @@ -62,7 +63,10 @@ void CDraw::SetFOV(float fov) { #ifdef ASPECT_RATIO_SCALE - ms_fScaledFOV = ConvertFOV(fov); + if (!CCutsceneMgr::IsRunning()) + ms_fScaledFOV = ConvertFOV(fov); + else + ms_fScaledFOV = fov; #endif ms_fFOV = fov; } From 841fa5155c17b6edf4774deaa311a4e5935be4d6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 13 Jul 2020 17:43:09 +0300 Subject: [PATCH 37/85] Rename LEVEL_NONE to LEVEL_GENERIC --- src/control/GameLogic.cpp | 12 ++++++------ src/control/Record.cpp | 4 ++-- src/control/Replay.cpp | 6 +++--- src/control/Restart.cpp | 8 ++++---- src/control/Script.cpp | 8 ++++---- src/core/Collision.cpp | 32 ++++++++++++++++---------------- src/core/Game.cpp | 4 ++-- src/core/Game.h | 2 +- src/core/PlayerInfo.cpp | 2 +- src/core/TempColModels.cpp | 6 +++--- src/core/World.cpp | 2 +- src/core/Zones.cpp | 8 ++++---- src/entities/Building.cpp | 2 +- src/entities/Entity.cpp | 4 ++-- src/entities/Physical.cpp | 2 +- src/modelinfo/ModelInfo.cpp | 2 +- src/modelinfo/PedModelInfo.cpp | 4 ++-- src/peds/CivilianPed.cpp | 2 +- src/peds/CopPed.cpp | 2 +- src/peds/EmergencyPed.cpp | 2 +- src/peds/Ped.cpp | 2 +- src/peds/Population.cpp | 10 +++++----- src/render/Renderer.cpp | 4 ++-- src/save/GenericGameStorage.cpp | 2 +- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Boat.cpp | 2 +- src/vehicles/Plane.cpp | 2 +- 27 files changed, 69 insertions(+), 69 deletions(-) diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 04983e30..47b4586b 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -121,8 +121,8 @@ CGameLogic::Update() CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverrideHospitalLevel = LEVEL_NONE; - CRestart::OverridePoliceStationLevel = LEVEL_NONE; + CRestart::OverrideHospitalLevel = LEVEL_GENERIC; + CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; PassTime(720); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); SortOutStreamingAndMemory(pPlayerInfo.GetPos()); @@ -200,8 +200,8 @@ CGameLogic::Update() CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverrideHospitalLevel = LEVEL_NONE; - CRestart::OverridePoliceStationLevel = LEVEL_NONE; + CRestart::OverrideHospitalLevel = LEVEL_GENERIC; + CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; PassTime(720); RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); pPlayerInfo.m_pPed->ClearWeapons(); @@ -249,8 +249,8 @@ CGameLogic::Update() CCarCtrl::ClearInterestingVehicleList(); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat); - CRestart::OverridePoliceStationLevel = LEVEL_NONE; - CRestart::OverrideHospitalLevel = LEVEL_NONE; + CRestart::OverridePoliceStationLevel = LEVEL_GENERIC; + CRestart::OverrideHospitalLevel = LEVEL_GENERIC; RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat); SortOutStreamingAndMemory(pPlayerInfo.GetPos()); TheCamera.m_fCamShakeForce = 0.0f; diff --git a/src/control/Record.cpp b/src/control/Record.cpp index d086543f..30bca2f3 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -426,8 +426,8 @@ void RemoveUnusedCollision(void) "com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22" }; for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++) - CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE; - CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE); + CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_GENERIC; + CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC); for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++) CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL; } diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 707f1d87..cb9df508 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -164,7 +164,7 @@ static void ApplyPanelDamageToCar(uint32 panels, CAutomobile* vehicle, bool flyi void PrintElementsInPtrList(void) { - for (CPtrNode* node = CWorld::GetBigBuildingList(LEVEL_NONE).first; node; node = node->next) { + for (CPtrNode* node = CWorld::GetBigBuildingList(LEVEL_GENERIC).first; node; node = node->next) { /* Most likely debug print was present here */ } } @@ -1124,7 +1124,7 @@ void CReplay::StoreStuffInMem(void) pWorld1 = new uint8[sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y]; memcpy(pWorld1, CWorld::GetSector(0, 0), NUMSECTORS_X * NUMSECTORS_Y * sizeof(CSector)); WorldPtrList = CWorld::GetMovingEntityList().first; // why - BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE).first; + BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_GENERIC).first; pPickups = new uint8[sizeof(CPickup) * NUMPICKUPS]; memcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup)); pReferences = new uint8[(sizeof(CReference) * NUMREFERENCES)]; @@ -1170,7 +1170,7 @@ void CReplay::RestoreStuffFromMem(void) delete[] pWorld1; pWorld1 = nil; CWorld::GetMovingEntityList().first = WorldPtrList; - CWorld::GetBigBuildingList(LEVEL_NONE).first = BigBuildingPtrList; + CWorld::GetBigBuildingList(LEVEL_GENERIC).first = BigBuildingPtrList; memcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS); delete[] pPickups; pPickups = nil; diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 5a322cdb..a6482d04 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -24,8 +24,8 @@ uint16 CRestart::NumberOfPoliceRestarts; void CRestart::Initialise() { - OverridePoliceStationLevel = LEVEL_NONE; - OverrideHospitalLevel = LEVEL_NONE; + OverridePoliceStationLevel = LEVEL_GENERIC; + OverrideHospitalLevel = LEVEL_GENERIC; bFadeInAfterNextArrest = true; bFadeInAfterNextDeath = true; OverrideHeading = 0.0f; @@ -86,7 +86,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f // find closest point on this level for (int i = 0; i < NumberOfHospitalRestarts; i++) { - if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) { + if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_GENERIC ? OverrideHospitalLevel : curlevel)) { float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; @@ -133,7 +133,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo // find closest point on this level for (int i = 0; i < NumberOfPoliceRestarts; i++) { - if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) { + if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_GENERIC ? OverridePoliceStationLevel : curlevel)) { float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr(); if (fMinDist >= dist) { fMinDist = dist; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 3309dbd2..1f25f00c 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8708,7 +8708,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CEntity* apEntities[16]; CWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true); if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_NONE), pos, range, true, &total, 16, apEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities); if (total == 0) CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities); CEntity* pClosestEntity = nil; @@ -9460,7 +9460,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CEntity* apEntities[16]; CWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false); if (total == 0) - CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_NONE), pos, radius, true, &total, 16, apEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities); if (total == 0) CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities); CEntity* pClosestEntity = nil; @@ -10062,7 +10062,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) if (ScriptParams[1]) pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); else - pVehicle->m_nZoneLevel = LEVEL_NONE; + pVehicle->m_nZoneLevel = LEVEL_GENERIC; return 0; } case COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL: @@ -10073,7 +10073,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) if (ScriptParams[1]) pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); else - pPed->m_nZoneLevel = LEVEL_NONE; + pPed->m_nZoneLevel = LEVEL_GENERIC; return 0; } case COMMAND_REGISTER_4X4_ONE_TIME: diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index cb8b4189..3244d0b9 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -38,7 +38,7 @@ void CCollision::Init(void) { ms_colModelCache.Init(NUMCOLCACHELINKS); - ms_collisionInMemory = LEVEL_NONE; + ms_collisionInMemory = LEVEL_GENERIC; } void @@ -59,7 +59,7 @@ CCollision::Update(void) return; // hardcode a level if there are no zones - if(level == LEVEL_NONE){ + if(level == LEVEL_GENERIC){ if(CGame::currLevel == LEVEL_INDUSTRIAL && playerCoors.x < 400.0f){ level = LEVEL_COMMERCIAL; @@ -78,7 +78,7 @@ CCollision::Update(void) } } } - if(level != LEVEL_NONE && level != CGame::currLevel) + if(level != LEVEL_GENERIC && level != CGame::currLevel) CGame::currLevel = level; if(ms_collisionInMemory != CGame::currLevel) LoadCollisionWhenINeedIt(forceLevelChange); @@ -95,10 +95,10 @@ GetCollisionInSectorList(CPtrList &list) for(node = list.first; node; node = node->next){ e = (CEntity*)node->item; level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level; - if(level != LEVEL_NONE) + if(level != LEVEL_GENERIC) return (eLevelName)level; } - return LEVEL_NONE; + return LEVEL_GENERIC; } // Get a level this sector is in based on collision models @@ -108,15 +108,15 @@ GetCollisionInSector(CSector §) int level; level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]); - if(level == LEVEL_NONE) + if(level == LEVEL_GENERIC) level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]); - if(level == LEVEL_NONE) + if(level == LEVEL_GENERIC) level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]); - if(level == LEVEL_NONE) + if(level == LEVEL_GENERIC) level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]); - if(level == LEVEL_NONE) + if(level == LEVEL_GENERIC) level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]); - if(level == LEVEL_NONE) + if(level == LEVEL_GENERIC) level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]); return (eLevelName)level; } @@ -133,7 +133,7 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) int xmin, xmax, ymin, ymax; int x, y; - level = LEVEL_NONE; + level = LEVEL_GENERIC; playerCoors = FindPlayerCoors(); sx = CWorld::GetSectorIndexX(playerCoors.x); @@ -161,8 +161,8 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) for(x = xmin; x <= xmax; x++) for(y = ymin; y <= ymax; y++){ l = GetCollisionInSector(*CWorld::GetSector(x, y)); - if(l != LEVEL_NONE){ - if(level == LEVEL_NONE) + if(l != LEVEL_GENERIC){ + if(level == LEVEL_GENERIC) level = l; if(level != l) multipleLevels = true; @@ -173,7 +173,7 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) if(multipleLevels && veh && veh->IsBoat()) for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){ level = GetCollisionInSector(*ei->sector); - if(level != LEVEL_NONE) + if(level != LEVEL_GENERIC) break; } } @@ -205,7 +205,7 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) ms_collisionInMemory = CGame::currLevel; CReplay::EmptyReplayBuffer(); #ifndef NO_ISLAND_LOADING - if(CGame::currLevel != LEVEL_NONE) + if(CGame::currLevel != LEVEL_GENERIC) LoadSplash(GetLevelSplashScreen(CGame::currLevel)); CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); @@ -232,7 +232,7 @@ CCollision::SortOutCollisionAfterLoad(void) #ifndef NO_ISLAND_LOADING CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel); #endif - if (CGame::currLevel != LEVEL_NONE) { + if (CGame::currLevel != LEVEL_GENERIC) { #ifdef NO_ISLAND_LOADING static bool bAlreadyLoaded = false; if (bAlreadyLoaded) { diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 4c8aaa72..fe073d29 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -357,7 +357,7 @@ bool CGame::Initialise(const char* datFile) CStreaming::Init(); CStreaming::LoadInitialVehicles(); CStreaming::LoadInitialPeds(); - CStreaming::RequestBigBuildings(LEVEL_NONE); + CStreaming::RequestBigBuildings(LEVEL_GENERIC); CStreaming::LoadAllRequestedModels(false); printf("Streaming uses %dK of its memory", CStreaming::ms_memoryUsed / 1024); LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen()); @@ -511,7 +511,7 @@ void CGame::ReInitGameObjectVariables(void) CTimeCycle::Initialise(); CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; - CStreaming::RequestBigBuildings(LEVEL_NONE); + CStreaming::RequestBigBuildings(LEVEL_GENERIC); CStreaming::LoadAllRequestedModels(false); CPed::Initialise(); CEventList::Initialise(); diff --git a/src/core/Game.h b/src/core/Game.h index 48f31abc..46e8fc68 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -2,7 +2,7 @@ enum eLevelName { LEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel - LEVEL_NONE = 0, + LEVEL_GENERIC = 0, LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, LEVEL_SUBURBAN diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 69c1fe49..09b3a499 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -553,7 +553,7 @@ CPlayerInfo::Process(void) veh->m_nZoneLevel = LEVEL_IGNORE; for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) { if (veh->pPassengers[i]) - veh->pPassengers[i]->m_nZoneLevel = LEVEL_NONE; + veh->pPassengers[i]->m_nZoneLevel = LEVEL_GENERIC; } CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled; } else { diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index 1252e2c7..ab73631d 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -36,19 +36,19 @@ CTempColModels::Initialise(void) #define SET_COLMODEL_SPHERES(colmodel, sphrs)\ colmodel.numSpheres = ARRAY_SIZE(sphrs);\ colmodel.spheres = sphrs;\ - colmodel.level = LEVEL_NONE;\ + colmodel.level = LEVEL_GENERIC;\ colmodel.ownsCollisionVolumes = false;\ int i; ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); - ms_colModelBBox.level = LEVEL_NONE; + ms_colModelBBox.level = LEVEL_GENERIC; for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); - ms_colModelCutObj[i].level = LEVEL_NONE; + ms_colModelCutObj[i].level = LEVEL_GENERIC; } // Ped Spheres diff --git a/src/core/World.cpp b/src/core/World.cpp index 8bcce8e7..9f384048 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1797,7 +1797,7 @@ CWorld::ClearForRestart(void) CWorld::Remove(pEntity); delete pEntity; } - for(CPtrNode *pNode = GetBigBuildingList(LEVEL_NONE).first; pNode; pNode = pNode->next) { + for(CPtrNode *pNode = GetBigBuildingList(LEVEL_GENERIC).first; pNode; pNode = pNode->next) { CVehicle *pVehicle = (CVehicle *)pNode->item; if(pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { CWorld::Remove(pVehicle); diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 4f491a49..1556731b 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -90,7 +90,7 @@ CTheZones::Init(void) TotalNumberOfZoneInfos = 1; // why 1? TotalNumberOfZones = 1; - m_CurrLevel = LEVEL_NONE; + m_CurrLevel = LEVEL_GENERIC; m_pPlayersZone = &ZoneArray[0]; strcpy(ZoneArray[0].name, "CITYZON"); @@ -100,7 +100,7 @@ CTheZones::Init(void) ZoneArray[0].maxx = 4000.0f; ZoneArray[0].maxy = 4000.0f; ZoneArray[0].maxz = 500.0f; - ZoneArray[0].level = LEVEL_NONE; + ZoneArray[0].level = LEVEL_GENERIC; for(i = 0; i < NUMMAPZONES; i++){ memset(&MapZoneArray[i], 0, sizeof(CZone)); @@ -116,7 +116,7 @@ CTheZones::Init(void) MapZoneArray[0].maxx = 4000.0f; MapZoneArray[0].maxy = 4000.0f; MapZoneArray[0].maxz = 500.0f; - MapZoneArray[0].level = LEVEL_NONE; + MapZoneArray[0].level = LEVEL_GENERIC; } void @@ -577,7 +577,7 @@ CTheZones::FindZoneForPoint(const CVector &pos) return LEVEL_COMMERCIAL; if(PointLiesWithinZone(&pos, GetZone(FindZoneByLabelAndReturnIndex("SUB_ZON")))) return LEVEL_SUBURBAN; - return LEVEL_NONE; + return LEVEL_GENERIC; } void diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp index 3c096636..00bbb21e 100644 --- a/src/entities/Building.cpp +++ b/src/entities/Building.cpp @@ -17,6 +17,6 @@ CBuilding::ReplaceWithNewModel(int32 id) m_modelIndex = id; if(bIsBIGBuilding) - if(m_level == LEVEL_NONE || m_level == CGame::currLevel) + if(m_level == LEVEL_GENERIC || m_level == CGame::currLevel) CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); } diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 31da489f..0319c7ea 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -332,14 +332,14 @@ CEntity::SetupBigBuilding(void) bStreamingDontDelete = true; bUsesCollision = false; m_level = CTheZones::GetLevelFromPosition(&GetPosition()); - if(m_level == LEVEL_NONE){ + if(m_level == LEVEL_GENERIC){ if(mi->GetTxdSlot() != CTxdStore::FindTxdSlot("generic")){ mi->SetTexDictionary("generic"); printf("%d:%s txd has been set to generic\n", m_modelIndex, mi->GetName()); } } if(mi->m_lodDistances[0] > 2000.0f) - m_level = LEVEL_NONE; + m_level = LEVEL_GENERIC; } CRect diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index e89b4858..49060fe7 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -70,7 +70,7 @@ CPhysical::CPhysical(void) #ifdef FIX_BUGS m_nSurfaceTouched = SURFACE_DEFAULT; #endif - m_nZoneLevel = LEVEL_NONE; + m_nZoneLevel = LEVEL_GENERIC; } CPhysical::~CPhysical(void) diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index 713600fd..d6fb0102 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -226,7 +226,7 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level) mi = GetModelInfo(i); if(mi){ colmodel = mi->GetColModel(); - if(colmodel && colmodel->level != LEVEL_NONE && colmodel->level != level) + if(colmodel && colmodel->level != LEVEL_GENERIC && colmodel->level != level) colmodel->RemoveCollisionVolumes(); } } diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 1d8aa4dc..60c63114 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -265,7 +265,7 @@ CPedModelInfo::CreateHitColModel(void) max.x = max.y = 0.5f; max.z = 1.2f; colmodel->boundingBox.Set(min, max, 0, 0); - colmodel->level = LEVEL_NONE; + colmodel->level = LEVEL_GENERIC; m_hitColModel = colmodel; } @@ -349,7 +349,7 @@ CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) max.x = max.y = 0.5f; max.z = 1.2f; colmodel->boundingBox.Set(min, max, 0, 0); - colmodel->level = LEVEL_NONE; + colmodel->level = LEVEL_GENERIC; m_hitColModel = colmodel; } diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 7c569257..2d782a73 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -232,7 +232,7 @@ CCivilianPed::CivilianAI(void) void CCivilianPed::ProcessControl(void) { - if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) + if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; CPed::ProcessControl(); diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 99e8c1ae..6d106b0e 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -559,7 +559,7 @@ CCopPed::CopAI(void) void CCopPed::ProcessControl(void) { - if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) + if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; CPed::ProcessControl(); diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 083941b8..8d6999c3 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -44,7 +44,7 @@ CEmergencyPed::InRange(CPed *victim) void CEmergencyPed::ProcessControl(void) { - if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) + if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; CPed::ProcessControl(); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7a1bc3fc..92eb8b13 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -9177,7 +9177,7 @@ CPed::ProcessControl(void) CColPoint foundCol; CEntity *foundEnt = nil; - if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) + if (m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index e2257a28..1357907d 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -394,7 +394,7 @@ CPopulation::FindCollisionZoneForCoors(CVector *coors, int *safeZoneOut, eLevelN } // Then it's transition area if (*safeZoneOut >= 0) - *levelOut = LEVEL_NONE; + *levelOut = LEVEL_GENERIC; else *levelOut = CTheZones::GetLevelFromPosition(coors); } @@ -867,7 +867,7 @@ CPopulation::MoveCarsAndPedsOutOfAbandonedZones() for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh && veh->m_nZoneLevel == LEVEL_NONE && veh->IsCar()) { + if (veh && veh->m_nZoneLevel == LEVEL_GENERIC && veh->IsCar()) { if(veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_PLAYER && veh->GetStatus() != STATUS_PLAYER_REMOTE) { @@ -876,7 +876,7 @@ CPopulation::MoveCarsAndPedsOutOfAbandonedZones() CPopulation::FindCollisionZoneForCoors(&vehPos, &zone, &level); // Level 0 is transition zones, and we don't wanna touch cars on transition zones. - if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && vehPos.z > -4.0f) { + if (level != LEVEL_GENERIC && level != CCollision::ms_collisionInMemory && vehPos.z > -4.0f) { if (veh->bIsLocked || !veh->CanBeDeleted()) { switch (movedVehicleCount & 3) { case 0: @@ -913,13 +913,13 @@ CPopulation::MoveCarsAndPedsOutOfAbandonedZones() for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex); - if (ped && ped->m_nZoneLevel == LEVEL_NONE && !ped->bInVehicle) { + if (ped && ped->m_nZoneLevel == LEVEL_GENERIC && !ped->bInVehicle) { CVector pedPos(ped->GetPosition()); CPopulation::FindCollisionZoneForCoors(&pedPos, &zone, &level); // Level 0 is transition zones, and we don't wanna touch peds on transition zones. - if (level != LEVEL_NONE && level != CCollision::ms_collisionInMemory && pedPos.z > -4.0f) { + if (level != LEVEL_GENERIC && level != CCollision::ms_collisionInMemory && pedPos.z > -4.0f) { if (ped->CanBeDeleted()) { CWorld::Remove(ped); delete ped; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 53181e52..9ebbc1bb 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -706,11 +706,11 @@ CRenderer::ScanWorld(void) ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_SUBURBAN)); #else #ifdef FIX_BUGS - if (CCollision::ms_collisionInMemory != LEVEL_NONE) + if (CCollision::ms_collisionInMemory != LEVEL_GENERIC) #endif ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory)); #endif - ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_NONE)); + ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC)); } } } diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 1ac17982..1e2d5da7 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -489,7 +489,7 @@ CheckDataNotCorrupt(int32 slot, char *name) char filename[100]; int32 blocknum = 0; - eLevelName level = LEVEL_NONE; + eLevelName level = LEVEL_GENERIC; CheckSum = 0; uint32 bytes_processed = 0; sprintf(filename, "%s%i%s", DefaultPCSaveFileName, slot + 1, ".b"); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index f89dd552..1f651bb2 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -230,7 +230,7 @@ CAutomobile::ProcessControl(void) bWarnedPeds = false; // skip if the collision isn't for the current level - if(colModel->level > LEVEL_NONE && colModel->level != CCollision::ms_collisionInMemory) + if(colModel->level > LEVEL_GENERIC && colModel->level != CCollision::ms_collisionInMemory) return; // Improve grip of vehicles in certain cases diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 9113800d..50117690 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -109,7 +109,7 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos) void CBoat::ProcessControl(void) { - if(m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) + if(m_nZoneLevel > LEVEL_GENERIC && m_nZoneLevel != CCollision::ms_collisionInMemory) return; bool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f; diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 3bf385a0..1f5fcb5a 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -83,7 +83,7 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) SetStatus(STATUS_PLANE); bIsBIGBuilding = true; - m_level = LEVEL_NONE; + m_level = LEVEL_GENERIC; #ifdef FIX_BUGS m_isFarAway = true; From 23da99622c2d2d8acf4edd67de5537f52fc6078e Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 16 Jul 2020 13:35:35 +0200 Subject: [PATCH 38/85] tiny cleanup --- src/rw/RwHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index cd2a1bf6..3503e27d 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -202,7 +202,7 @@ isSkinnedCb(RpAtomic *atomic, void *data) RpAtomic **pAtomic = (RpAtomic**)data; if(*pAtomic) return nil; // already found one - if(RpSkinGeometryGetSkin(atomic->geometry)) + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))) *pAtomic = atomic; // we could just return nil here directly... return atomic; } From 4e3e1d0b87b88738741955fd2b673ee6ea4295ab Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 16 Jul 2020 13:36:25 +0200 Subject: [PATCH 39/85] make game load all platform dffs --- src/core/FileLoader.cpp | 17 ++++++++ src/modelinfo/VehicleModelInfo.cpp | 2 +- src/rw/RwHelper.cpp | 69 +++++++++++++++++++++++++++++- src/rw/RwHelper.h | 4 +- 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 08126081..a7ab365c 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -393,6 +393,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data) return atomic; } +#ifdef LIBRW +void +InitClump(RpClump *clump) +{ + RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil); +} +#else +#define InitClump(clump) +#endif + void CFileLoader::LoadModelFile(const char *filename) { @@ -404,6 +414,7 @@ CFileLoader::LoadModelFile(const char *filename) if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){ clump = RpClumpStreamRead(stream); if(clump){ + InitClump(clump); RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump); RpClumpDestroy(clump); } @@ -429,6 +440,7 @@ CFileLoader::LoadClumpFile(const char *filename) GetNameAndLOD(nodename, name, &n); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil); if(mi){ + InitClump(clump); assert(mi->IsClump()); mi->SetClump(clump); }else @@ -449,6 +461,7 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id) clump = RpClumpStreamRead(stream); if(clump == nil) return false; + InitClump(clump); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi->SetClump(clump); return true; @@ -476,6 +489,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id) clump = RpClumpGtaStreamRead2(stream); if(clump){ + InitClump(clump); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi->SetClump(clump); return true; @@ -496,6 +510,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id) clump = RpClumpStreamRead(stream); if(clump == nil) return false; + InitClump(clump); gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump); RpClumpDestroy(clump); @@ -531,6 +546,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename) stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename); if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) clump = RpClumpStreamRead(stream); + if(clump) + InitClump(clump); RwStreamClose(stream, nil); return clump; } diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index f80e908a..d5396d12 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -1091,7 +1091,7 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data) RpGeometry *geo; geo = RpAtomicGetGeometry(atomic); - fx = 0; + fx = rpMATFXEFFECTNULL; RpGeometryForAllMaterials(geo, GetMatFXEffectMaterialCB, &fx); if(fx != rpMATFXEFFECTNULL){ RpMatFXAtomicEnableEffects(atomic); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 76c6c753..e8a85be6 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -212,7 +212,7 @@ isSkinnedCb(RpAtomic *atomic, void *data) RpAtomic **pAtomic = (RpAtomic**)data; if(*pAtomic) return nil; // already found one - if(RpSkinGeometryGetSkin(atomic->geometry)) + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))) *pAtomic = atomic; // we could just return nil here directly... return atomic; } @@ -621,3 +621,70 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer) WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); } WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); } #endif + +#ifdef LIBRW +#include +#include "VehicleModelInfo.h" + +int32 +findPlatform(rw::Atomic *a) +{ + rw::Geometry *g = a->geometry; + if(g->instData) + return g->instData->platform; + return 0; +} + +// Game doesn't read atomic extensions so we never get any other than the default pipe, +// but we need it for uninstancing +void +attachPipe(rw::Atomic *atomic) +{ + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))) + atomic->pipeline = rw::skinGlobals.pipelines[rw::platform]; + else{ + int fx = rpMATFXEFFECTNULL; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), CVehicleModelInfo::GetMatFXEffectMaterialCB, &fx); + if(fx != rpMATFXEFFECTNULL) + RpMatFXAtomicEnableEffects(atomic); + } +} + +// Attach pipes for the platform we have native data for so we can uninstance +void +switchPipes(rw::Atomic *a, int32 platform) +{ + if(a->pipeline && a->pipeline->platform != platform){ + uint32 plgid = a->pipeline->pluginID; + switch(plgid){ + // assume default pipe won't be attached explicitly + case rw::ID_SKIN: + a->pipeline = rw::skinGlobals.pipelines[platform]; + break; + case rw::ID_MATFX: + a->pipeline = rw::matFXGlobals.pipelines[platform]; + break; + } + } +} + +RpAtomic* +ConvertPlatformAtomic(RpAtomic *atomic, void *data) +{ + int32 driver = rw::platform; + int32 platform = findPlatform(atomic); + if(platform != 0 && platform != driver){ + attachPipe(atomic); // kludge + rw::ObjPipeline *origPipe = atomic->pipeline; + rw::platform = platform; + switchPipes(atomic, rw::platform); + if(atomic->geometry->flags & rw::Geometry::NATIVE) + atomic->uninstance(); + // no ADC in this game + //rw::ps2::unconvertADC(atomic->geometry); + rw::platform = driver; + atomic->pipeline = origPipe; + } + return atomic; +} +#endif diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 993acd89..94a8bd94 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -54,4 +54,6 @@ RwCamera *CameraCreate(RwInt32 width, void _TexturePoolsInitialise(); -void _TexturePoolsShutdown(); \ No newline at end of file +void _TexturePoolsShutdown(); + +RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data); From ec09055599a1c09aa0214e7236ddf2a18e46a611 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Jul 2020 22:21:09 +0300 Subject: [PATCH 40/85] Fix CCarStateEachFrame --- src/control/Record.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/control/Record.h b/src/control/Record.h index 7af733ba..8b55b1f4 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -17,13 +17,13 @@ public: int8 forwardY; int8 forwardZ; int8 wheel; - uint8 gas; - uint8 brake; + int8 gas; + int8 brake; bool handbrake; CVector pos; }; -extern char gString[256];; +extern char gString[256]; class CRecordDataForChase { From 81c03f8e6d914b8e0d91d3d422c868fa5bb0fbe3 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Jul 2020 22:30:55 +0300 Subject: [PATCH 41/85] Audio fixes --- src/audio/AudioLogic.cpp | 83 +++++++++++++++++++--------------------- src/audio/AudioManager.h | 2 +- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index d3d9f74d..ef3814a2 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -980,7 +980,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) relativeGearChange = Min(1.0f, (params->m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f); if (traction == 0.0f && automobile->GetStatus() != STATUS_SIMPLE && - params->m_fVelocityChange >= transmission->Gears[1].fShiftUpVelocity) { + params->m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity) { traction = 0.7f; } relativeChange = traction * automobile->m_fGasPedalAudio * 0.95f + (1.0f - traction) * relativeGearChange; @@ -993,7 +993,7 @@ cAudioManager::ProcessVehicleEngine(cVehicleParams *params) relativeChange = automobile->m_fGasPedalAudio; } modificator = relativeChange; - if (currentGear || !automobile->m_nWheelsOnGround) + if (currentGear != 0 || automobile->m_nWheelsOnGround == 0) freq = 1200 * currentGear + 18000.f * modificator + 14000; else freq = 13000.f * modificator + 14000; @@ -1279,7 +1279,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * SampleManager.StopChannel(m_nActiveSamples); bAccelSampleStopped = true; } - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) + if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction) gasPedalAudio = automobile->m_fGasPedalAudio; else gasPedalAudio = Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); @@ -1292,8 +1292,8 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * bAccelSampleStopped = true; } nCruising = 0; - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || - params->m_fVelocityChange >= 0.01f && automobile->m_fGasPedalAudio > 0.2f) { + if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction || + params->m_fVelocityChange < 0.01f && automobile->m_fGasPedalAudio > 0.2f) { automobile->m_fGasPedalAudio *= 0.6f; gasPedalAudio = automobile->m_fGasPedalAudio; } @@ -1313,11 +1313,11 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * CurrentPretendGear = Max(1, currentGear); } else { while (nCruising == 0) { - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + if (accelerateState < 150 || automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction || currentGear < 2 && velocityChange - automobile->m_fVelocityChangeForAudio < 0.01f) { // here could be used abs - if (!automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction) { - if (!automobile->m_nWheelsOnGround && automobile->m_nDriveWheelsOnGround || - (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround) { + if (automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction) { + if (automobile->m_nWheelsOnGround == 0 && automobile->m_nDriveWheelsOnGround != 0 || + (automobile->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame) && automobile->m_nWheelsOnGround != 0) { automobile->m_fGasPedalAudio *= 0.6f; } freqModifier = 0; @@ -1381,11 +1381,11 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * } if (nCruising != 0) { bAccelSampleStopped = true; - if (accelerateState < 150 || !automobile->m_nWheelsOnGround || automobile->bIsHandbrakeOn || lostTraction || + if (accelerateState < 150 || automobile->m_nWheelsOnGround == 0 || automobile->bIsHandbrakeOn || lostTraction || currentGear < params->m_pTransmission->nNumberOfGears - 1) { nCruising = 0; } else { - if (accelerateState >= 220 && 0.001f + params->m_fVelocityChange < automobile->m_fVelocityChangeForAudio) { + if (accelerateState >= 220 && params->m_fVelocityChange + 0.001f < automobile->m_fVelocityChangeForAudio) { if (nCruising < 800) ++nCruising; } else if (nCruising > 3) { @@ -1404,7 +1404,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * bLostTractionLastFrame = lostTraction; } -void +bool cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) { const float SOUND_INTENSITY = 40.0f; @@ -1416,10 +1416,10 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) float skidVal = 0.0f; if (params->m_fDistance >= SQR(SOUND_INTENSITY)) - return; + return false; automobile = (CAutomobile *)params->m_pVehicle; - if (!automobile->m_nWheelsOnGround) - return; + if (automobile->m_nWheelsOnGround == 0) + return true; CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); for (int32 i = 0; i < ARRAY_SIZE(automobile->m_aWheelState); i++) { if (automobile->m_aWheelState[i] == WHEEL_STATE_NORMAL || automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING) @@ -1459,6 +1459,8 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) emittingVol /= 4; m_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f; m_sQueueSample.m_nVolume /= 4; + if (m_sQueueSample.m_nVolume == 0) + return true; break; case SURFACE_GRAVEL: case SURFACE_MUD_DRY: @@ -1490,43 +1492,40 @@ cAudioManager::ProcessVehicleSkidding(cVehicleParams *params) AddSampleToRequestedQueue(); } } + return true; } float cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) { - tWheelState wheelState; - float relativeVelChange; + float relativeVelChange = 0.0f; float gasPedalAudio = automobile->m_fGasPedalAudio; - float modificator; float velChange; float relativeVel; - wheelState = automobile->m_aWheelState[wheel]; - if (wheelState == WHEEL_STATE_SPINNING && gasPedalAudio > 0.4f) { - relativeVelChange = (gasPedalAudio - 0.4f) * 1.25f; - - } else if (wheelState == WHEEL_STATE_SKIDDING) { + switch (automobile->m_aWheelState[wheel]) + { + case WHEEL_STATE_SPINNING: + if (gasPedalAudio > 0.4f) + relativeVelChange = (gasPedalAudio - 0.4f) * 1.6666666f * 0.75f; + break; + case WHEEL_STATE_SKIDDING: relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); - } else if (wheelState == WHEEL_STATE_FIXED) { - modificator = 0.4f; - relativeVelChange = gasPedalAudio; - if (relativeVelChange > 0.4f) { - relativeVelChange = relativeVelChange - 0.4f; - modificator = 5.f / 3.f; - } + break; + case WHEEL_STATE_FIXED: + relativeVel = gasPedalAudio; + if (relativeVel > 0.4f) + relativeVel = (gasPedalAudio - 0.4f) * 1.6666666f; + velChange = Abs(velocityChange); - if (relativeVelChange > 0.4f) - relativeVelChange = relativeVelChange * modificator; - if (velChange > 0.04f) { - relativeVel = Min(1.0f, velChange / transmission->fMaxVelocity); - } else { - relativeVel = 0.0f; - } - if (relativeVel >= relativeVelChange) + if (velChange > 0.04f) + relativeVelChange = Min(1.0f, velChange / transmission->fMaxVelocity); + if (relativeVel > relativeVelChange) relativeVelChange = relativeVel; - } else { - relativeVelChange = 0.0f; + + break; + default: + break; } return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); @@ -1535,12 +1534,10 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil float cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, cTransmission *transmission, float velocityChange) { - float relativeVelChange; + float relativeVelChange = 0.0f; if (automobile->m_aWheelState[wheel] == WHEEL_STATE_SKIDDING) relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); - else - relativeVelChange = 0.0f; return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); } diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 8c579ca8..363031b7 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -421,7 +421,7 @@ public: bool ProcessVehicleReverseWarning(cVehicleParams *params); bool ProcessVehicleRoadNoise(cVehicleParams *params); bool ProcessVehicleSirenOrAlarm(cVehicleParams *params); - void ProcessVehicleSkidding(cVehicleParams *params); + bool ProcessVehicleSkidding(cVehicleParams *params); void ProcessWaterCannon(int32); void ProcessWeather(int32 id); bool ProcessWetRoadNoise(cVehicleParams *params); From 693a5e0c2a874b5bc4057c51772deb35d0a10a46 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Jul 2020 12:57:47 +0300 Subject: [PATCH 42/85] Fix wheel water splash with PC_PARTICLE --- src/vehicles/Automobile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 1f651bb2..d2fedbd5 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -3588,7 +3588,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) ) { CParticle::AddParticle( -#ifdef FIX_BUGS +#if defined(FIX_BUGS) && !defined(PC_PARTICLE) // looks wrong on PC particles PARTICLE_WHEEL_WATER, #else PARTICLE_WATERSPRAY, From 949d0c8853d31ae88fdf3427bae05ec337ab4b0b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Jul 2020 13:48:25 +0300 Subject: [PATCH 43/85] Add audio cache for faster initialization --- src/audio/sampman_miles.cpp | 17 ++++++++++++++++- src/audio/sampman_oal.cpp | 13 ++++++++++++- src/control/Record.cpp | 2 ++ src/core/FileLoader.cpp | 2 ++ src/core/config.h | 3 +++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/audio/sampman_miles.cpp b/src/audio/sampman_miles.cpp index d625ac35..098b6efa 100644 --- a/src/audio/sampman_miles.cpp +++ b/src/audio/sampman_miles.cpp @@ -959,6 +959,15 @@ cSampleManager::Initialise(void) } +#ifdef AUDIO_CACHE + TRACE("cache"); + FILE *cacheFile = fopen("audio\\sound.cache", "rb"); + if (cacheFile) { + fread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); + m_bInitialised = true; + }else { +#endif TRACE("cdrom"); S32 tatalms; @@ -1115,7 +1124,13 @@ cSampleManager::Initialise(void) _bUseHDDAudio = false; } #endif - +#ifdef AUDIO_CACHE + cacheFile = fopen("audio\\sound.cache", "wb"); + fwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); + } +#endif + TRACE("stream"); { for ( int32 i = 0; i < MAX_STREAMS; i++ ) diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index 1952f370..49ce5230 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -604,7 +604,13 @@ cSampleManager::Initialise(void) return false; } } - +#ifdef AUDIO_CACHE + FILE *cacheFile = fopen("audio\\sound.cache", "rb"); + if (cacheFile) { + fread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); + } else +#endif { for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) @@ -622,6 +628,11 @@ cSampleManager::Initialise(void) else USERERROR("Can't open '%s'\n", StreamedNameTable[i]); } +#ifdef AUDIO_CACHE + cacheFile = fopen("audio\\sound.cache", "wb"); + fwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile); + fclose(cacheFile); +#endif } LoadSampleBank(SAMPLEBANK_MAIN); diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 30bca2f3..8dc0028a 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -439,8 +439,10 @@ void CRecordDataForChase::StartChaseScene(float startTime) Status = STATE_PLAYBACK; AnimTime = startTime; AnimStartTime = CTimer::GetTimeInMilliseconds(); +#ifndef NO_ISLAND_LOADING RemoveUnusedCollision(); CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN); +#endif CGame::TidyUpMemory(true, true); CStreaming::ImGonnaUseStreamingMemory(); CFileMgr::SetDir("data\\paths"); diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 3c4ed040..63be2e7b 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -104,7 +104,9 @@ CFileLoader::LoadLevel(const char *filename) LoadingScreenLoadingFile(line + 8); LoadMapZones(line + 8); }else if(strncmp(line, "SPLASH", 6) == 0){ +#ifndef DISABLE_LOADING_SCREEN LoadSplash(GetRandomSplashScreen()); +#endif }else if(strncmp(line, "CDIMAGE", 7) == 0){ CdStreamAddImage(line + 8); } diff --git a/src/core/config.h b/src/core/config.h index 2ba7a021..9dd25064 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -275,3 +275,6 @@ enum Config { //#define PS2_CAM_TRANSITION // old way of transitioning between cam modes #define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future #define FREE_CAM // Rotating cam + +// Audio +#define AUDIO_CACHE // cache sound lengths to speed up the cold boot From 27e1fa1d28c67dee48601e2ea9a7a205b4cdaf54 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Jul 2020 17:56:59 +0300 Subject: [PATCH 44/85] Add missing f's --- src/render/Credits.cpp | 148 ++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index e0134e52..2cfdba90 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -129,12 +129,12 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED041"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED042"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED043"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED044"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); @@ -177,14 +177,14 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED061"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED062"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED063"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED064"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED065"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED066"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED067"), lineoffset, scrolloffset); @@ -192,16 +192,16 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED069"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED070"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED071"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED072"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED073"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED074"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED075"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED076"), lineoffset, scrolloffset); @@ -221,16 +221,16 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED085"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED086"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED087"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED088"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED089"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED090"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED091"), lineoffset, scrolloffset); @@ -250,7 +250,7 @@ CCredits::Render(void) PrintCreditSpace(2.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED100"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED101"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED102"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED103"), lineoffset, scrolloffset); @@ -261,82 +261,82 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRED269"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED107"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED108"), lineoffset, scrolloffset); - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED109"), lineoffset, scrolloffset); + PrintCreditSpace(1.5f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED108"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED109"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED110"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED110"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED111"), lineoffset, scrolloffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED112"), lineoffset, scrolloffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED112"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED113"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED113"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED114"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED114"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED115"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED115"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED116"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED116"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED117"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED117"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED118"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED118"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED119"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED119"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED120"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED120"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED121"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED121"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED122"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED122"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED123"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED123"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED124"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED124"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED125"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED125"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED126"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED126"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED127"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED127"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED128"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED128"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED129"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED129"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED130"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED130"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED131"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED131"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED132"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED132"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED133"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED133"), lineoffset, scrolloffset); if(CMenuManager::m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN) - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED134"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED134"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED135"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED136"), lineoffset, scrolloffset); @@ -349,7 +349,7 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRD138A"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRD138B"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED139"), lineoffset, scrolloffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED139"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.7f, 1.0f, TheText.Get("CRED140"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140A"), lineoffset, scrolloffset); @@ -359,12 +359,12 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRD140E"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED141"), lineoffset, scrolloffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED142"), lineoffset, scrolloffset); - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED143"), lineoffset, scrolloffset); - PrintCreditSpace(1.0, lineoffset); - PrintCreditText(1.0, 1.0, TheText.Get("CRED144"), lineoffset, scrolloffset); - PrintCreditSpace(1.0, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED142"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED143"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); + PrintCreditText(1.0f, 1.0f, TheText.Get("CRED144"), lineoffset, scrolloffset); + PrintCreditSpace(1.0f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED145"), lineoffset, scrolloffset); PrintCreditText(1.4f, 1.4f, TheText.Get("CRED146"), lineoffset, scrolloffset); @@ -441,19 +441,19 @@ CCredits::Render(void) PrintCreditText(1.4f, 1.4f, TheText.Get("CRED241"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED217"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED218"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRD218A"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRD218B"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED219"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED220"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED221"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED222"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED223"), lineoffset, scrolloffset); @@ -462,7 +462,7 @@ CCredits::Render(void) PrintCreditText(1.7f, 1.7f, TheText.Get("CRED226"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); PrintCreditText(1.4f, 0.82f, TheText.Get("CRED227"), lineoffset, scrolloffset); - PrintCreditSpace(1.5, lineoffset); + PrintCreditSpace(1.5f, lineoffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED228"), lineoffset, scrolloffset); PrintCreditText(1.7f, 1.7f, TheText.Get("CRED229"), lineoffset, scrolloffset); PrintCreditSpace(2.0f, lineoffset); From 1b161275e1b48ef0e13e6b83d667f56a3895d748 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Jul 2020 18:23:11 +0300 Subject: [PATCH 45/85] Fix CalcScreenCoors... again --- src/render/Sprite.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 0789769a..9ec7b002 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -29,11 +29,7 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, float recip = 1.0f/out->z; out->x *= SCREEN_WIDTH * recip; out->y *= SCREEN_HEIGHT * recip; -#ifdef ASPECT_RATIO_SCALE - float fov = CDraw::ConvertFOV(DefaultFOV); -#else const float fov = DefaultFOV; -#endif // this is used to scale correctly if you zoom in with sniper rifle float fovScale = fov / CDraw::GetFOV(); From e8ded77e27fb576126c7ab7132af4f65e11958b0 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Jul 2020 21:14:48 +0300 Subject: [PATCH 46/85] Add fix/workaround for black screen at startup --- src/skel/win/win.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 52941d7d..a57f4846 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -2235,6 +2235,11 @@ WinMain(HINSTANCE instance, CloseClip(); CoUninitialize(); +#ifdef FIX_BUGS + // draw one frame because otherwise we'll end up looking at black screen for a while if vsync is on + RsCameraShowRaster(Scene.camera); +#endif + #ifdef PS2_MENU extern char version_name[64]; if ( CGame::frenchGame || CGame::germanGame ) From cf5dd6289e5f4a805131aca4b57acb6c5d66adc8 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 13:09:21 +0300 Subject: [PATCH 47/85] Fix TempVertexBuffer overflow --- src/render/RenderBuffer.cpp | 4 ++-- src/render/RenderBuffer.h | 4 ++-- src/render/Sprite2d.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp index 5239dc06..b4f48a26 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/render/RenderBuffer.cpp @@ -5,8 +5,8 @@ int32 TempBufferVerticesStored; int32 TempBufferIndicesStored; -RwIm2DVertex TempVertexBuffer[TEMPBUFFERVERTSIZE]; -RwIm3DVertex *TempBufferRenderVertices = (RwIm3DVertex * )TempVertexBuffer; +RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +RwIm2DVertex *TempVertexBuffer = (RwIm2DVertex*)TempBufferRenderVertices; RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; int RenderBuffer::VerticesToBeStored; diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h index e67a28d0..0789dfa5 100644 --- a/src/render/RenderBuffer.h +++ b/src/render/RenderBuffer.h @@ -14,6 +14,6 @@ public: extern int32 TempBufferVerticesStored; extern int32 TempBufferIndicesStored; -extern RwIm2DVertex TempVertexBuffer[TEMPBUFFERVERTSIZE]; -extern RwIm3DVertex *TempBufferRenderVertices; +extern RwIm2DVertex *TempVertexBuffer; +extern RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; \ No newline at end of file diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index bf39d15e..5f1e79db 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -449,7 +449,7 @@ CSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float bool CSprite2d::IsVertexBufferFull() { - return (nextBufferVertex > ARRAY_SIZE(TempVertexBuffer)-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6); + return (nextBufferVertex > TEMPBUFFERINDEXSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6); } void From d4444f8252ea1d5919598a225b614b4cd5b83ea3 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 18 Jul 2020 13:09:37 +0300 Subject: [PATCH 48/85] fix --- src/control/Script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 1f25f00c..27e40106 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1925,7 +1925,7 @@ void CTheScripts::Init() dbg_log = fopen("SCRDBG.LOG", "w"); static const char* init_msg = "Starting debug script log\n\n"; PrintToLog(init_msg); - CFileMgr::SetDir("\\"); + CFileMgr::SetDir(""); #endif } @@ -2028,7 +2028,7 @@ void CTheScripts::Process() dbg_log = fopen("SCRDBG.LOG", "w"); static const char* init_msg = "Starting debug script log\n\n"; PrintToLog(init_msg); - CFileMgr::SetDir("\\"); + CFileMgr::SetDir(""); #endif PrintToLog("------------------------\n"); PrintToLog("CTheScripts::Process started, CTimer::GetTimeInMilliseconds == %u\n", CTimer::GetTimeInMilliseconds()); From dd717b2d933a024da14e8232fadc1302064ab2bf Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 13:27:31 +0300 Subject: [PATCH 49/85] Actual fix now xD --- src/render/Sprite2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 5f1e79db..b71039e8 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -449,7 +449,7 @@ CSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float bool CSprite2d::IsVertexBufferFull() { - return (nextBufferVertex > TEMPBUFFERINDEXSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6); + return (nextBufferVertex > TEMPBUFFERVERTSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6); } void From 87eb96453a405bfa0fbfffb57c9d6cfc74acfb70 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 13:30:51 +0300 Subject: [PATCH 50/85] Add compatibility with RW 3.4 --- premake5.lua | 10 +- rwsdk/include/d3d8/baaplylt.c | 793 -------------------- rwsdk/include/d3d8/rpanisot.h | 4 +- rwsdk/include/d3d8/rpanisot.rpe | 466 ------------ rwsdk/include/d3d8/rpcollis.h | 12 +- rwsdk/include/d3d8/rpcollis.rpe | 466 ------------ rwsdk/include/d3d8/rpcriter.h | 488 +------------ rwsdk/include/d3d8/rpdbgerr.c | 2 +- rwsdk/include/d3d8/rpdbgerr.h | 19 +- rwsdk/include/d3d8/rpdmorph.h | 4 +- rwsdk/include/d3d8/rpdmorph.rpe | 466 ------------ rwsdk/include/d3d8/rphanim.h | 838 ++++++++------------- rwsdk/include/d3d8/rphanim.rpe | 471 ------------ rwsdk/include/d3d8/rplodatm.h | 5 +- rwsdk/include/d3d8/rplodatm.rpe | 466 ------------ rwsdk/include/d3d8/rplogo.h | 2 +- rwsdk/include/d3d8/rplogo.rpe | 466 ------------ rwsdk/include/d3d8/rpltmap.h | 11 +- rwsdk/include/d3d8/rpltmap.rpe | 466 ------------ rwsdk/include/d3d8/rpmatfx.h | 6 +- rwsdk/include/d3d8/rpmatfx.rpe | 466 ------------ rwsdk/include/d3d8/rpmipkl.h | 28 +- rwsdk/include/d3d8/rpmipkl.rpe | 466 ------------ rwsdk/include/d3d8/rpmorph.h | 3 +- rwsdk/include/d3d8/rpmorph.rpe | 466 ------------ rwsdk/include/d3d8/rppatch.h | 22 +- rwsdk/include/d3d8/rppatch.rpe | 466 ------------ rwsdk/include/d3d8/rpprtstd.h | 153 ++-- rwsdk/include/d3d8/rpprtstd.rpe | 472 +----------- rwsdk/include/d3d8/rpptank.h | 113 ++- rwsdk/include/d3d8/rpptank.rpe | 466 ------------ rwsdk/include/d3d8/rppvs.h | 59 +- rwsdk/include/d3d8/rppvs.rpe | 466 ------------ rwsdk/include/d3d8/rprandom.h | 2 +- rwsdk/include/d3d8/rprandom.rpe | 466 ------------ rwsdk/include/d3d8/rpskin.h | 60 +- rwsdk/include/d3d8/rpskin.rpe | 466 ------------ rwsdk/include/d3d8/rpspline.h | 2 +- rwsdk/include/d3d8/rpspline.rpe | 466 ------------ rwsdk/include/d3d8/rpstereo.h | 141 ---- rwsdk/include/d3d8/rpstereo.rpe | 641 ---------------- rwsdk/include/d3d8/rpusrdat.h | 2 +- rwsdk/include/d3d8/rpusrdat.rpe | 466 ------------ rwsdk/include/d3d8/rpworld.h | 785 ++++++++++---------- rwsdk/include/d3d8/rt2d.h | 195 ++++- rwsdk/include/d3d8/rt2d.rpe | 467 +----------- rwsdk/include/d3d8/rt2danim.h | 233 +++--- rwsdk/include/d3d8/rt2danim.rpe | 472 +----------- rwsdk/include/d3d8/rtbary.h | 6 +- rwsdk/include/d3d8/rtbary.rpe | 466 ------------ rwsdk/include/d3d8/rtbezpat.h | 11 +- rwsdk/include/d3d8/rtbezpat.rpe | 466 ------------ rwsdk/include/d3d8/rtbmp.h | 2 +- rwsdk/include/d3d8/rtbmp.rpe | 466 ------------ rwsdk/include/d3d8/rtcharse.h | 4 +- rwsdk/include/d3d8/rtcharse.rpe | 466 ------------ rwsdk/include/d3d8/rtimport.h | 420 ++++++----- rwsdk/include/d3d8/rtimport.rpe | 466 ------------ rwsdk/include/d3d8/rtintel.h | 1206 ------------------------------- rwsdk/include/d3d8/rtintel.rpe | 645 ----------------- rwsdk/include/d3d8/rtintsec.h | 4 +- rwsdk/include/d3d8/rtintsec.rpe | 466 ------------ rwsdk/include/d3d8/rtltmap.h | 95 ++- rwsdk/include/d3d8/rtltmap.rpe | 466 ------------ rwsdk/include/d3d8/rtmipk.h | 4 +- rwsdk/include/d3d8/rtmipk.rpe | 466 ------------ rwsdk/include/d3d8/rtpick.h | 2 +- rwsdk/include/d3d8/rtpick.rpe | 466 ------------ rwsdk/include/d3d8/rtpitexd.h | 2 +- rwsdk/include/d3d8/rtpitexd.rpe | 466 ------------ rwsdk/include/d3d8/rtpng.h | 2 +- rwsdk/include/d3d8/rtpng.rpe | 466 ------------ rwsdk/include/d3d8/rtquat.h | 4 +- rwsdk/include/d3d8/rtquat.rpe | 466 ------------ rwsdk/include/d3d8/rtras.h | 2 +- rwsdk/include/d3d8/rtras.rpe | 466 ------------ rwsdk/include/d3d8/rtray.h | 6 +- rwsdk/include/d3d8/rtray.rpe | 466 ------------ rwsdk/include/d3d8/rtslerp.h | 2 +- rwsdk/include/d3d8/rtslerp.rpe | 466 ------------ rwsdk/include/d3d8/rtsplpvs.h | 2 +- rwsdk/include/d3d8/rtsplpvs.rpe | 466 ------------ rwsdk/include/d3d8/rttiff.h | 2 +- rwsdk/include/d3d8/rttiff.rpe | 466 ------------ rwsdk/include/d3d8/rttilerd.h | 2 +- rwsdk/include/d3d8/rttilerd.rpe | 466 ------------ rwsdk/include/d3d8/rttoc.h | 47 +- rwsdk/include/d3d8/rttoc.rpe | 466 ------------ rwsdk/include/d3d8/rtvcat.rpe | 466 ------------ rwsdk/include/d3d8/rtworld.h | 2 +- rwsdk/include/d3d8/rtworld.rpe | 466 ------------ rwsdk/include/d3d8/rwcore.h | 715 +++++------------- rwsdk/include/d3d8/rwplcore.h | 1067 ++++++++++++++++----------- src/animation/RpAnimBlend.cpp | 4 + src/core/main.cpp | 7 +- src/rw/RwHelper.cpp | 8 +- 96 files changed, 2572 insertions(+), 25458 deletions(-) delete mode 100644 rwsdk/include/d3d8/baaplylt.c delete mode 100644 rwsdk/include/d3d8/rpstereo.h delete mode 100644 rwsdk/include/d3d8/rpstereo.rpe delete mode 100644 rwsdk/include/d3d8/rtintel.h delete mode 100644 rwsdk/include/d3d8/rtintel.rpe diff --git a/premake5.lua b/premake5.lua index 6a27c5af..03610a03 100644 --- a/premake5.lua +++ b/premake5.lua @@ -48,10 +48,10 @@ workspace "reVC" filter { "system:windows" } platforms { - "win-x86-RW33_d3d8-mss", + "win-x86-RW34_d3d8-mss", "win-x86-librw_d3d9-mss", "win-x86-librw_gl3_glfw-mss", - "win-x86-RW33_d3d8-oal", + "win-x86-RW34_d3d8-oal", "win-x86-librw_d3d9-oal", "win-x86-librw_gl3_glfw-oal", } @@ -128,7 +128,7 @@ project "librw" targetdir "lib/%{cfg.platform}/%{cfg.buildcfg}" files { path.join(Librw, "src/*.*") } files { path.join(Librw, "src/*/*.*") } - filter "platforms:*RW33*" + filter "platforms:*RW34*" flags { "ExcludeFromBuild" } filter {} end @@ -218,11 +218,11 @@ project "reVC" filter "platforms:linux*oal" links { "openal", "mpg123", "sndfile", "pthread" } - filter "platforms:*RW33*" + filter "platforms:*RW34*" staticruntime "on" includedirs { "rwsdk/include/d3d8" } libdirs { "rwsdk/lib/d3d8/release" } - links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtcharse" } + links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtanim", "rtcharse", "rpanisot" } defines { "RWLIBS" } linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" diff --git a/rwsdk/include/d3d8/baaplylt.c b/rwsdk/include/d3d8/baaplylt.c deleted file mode 100644 index ad518e6a..00000000 --- a/rwsdk/include/d3d8/baaplylt.c +++ /dev/null @@ -1,793 +0,0 @@ - -/* If this file is used outside of the core RW SDK, - * the following things need to be defined - */ -#if (!defined(RWASSERT)) -#define RWASSERT(_assertval) /* No op */ -#endif -#if (!defined(RWFUNCTION)) -#define RWFUNCTION(_rwfunctionstring) /* No op */ -#endif -#if (!defined(RWRETURN)) -#define RWRETURN(_rwreturnval) return(_rwreturnval) -#endif -#if (!defined(RWRETURNVOID)) -#define RWRETURNVOID() return -#endif - -/* These are used by specular lighting, - * sorry I have to leave them in here... IDBS - * I'll make it neater when I have time. - */ -#if (!defined(FALLOFFAMBIENT)) -#define FALLOFFAMBIENT() /* No op */ -#endif -#if (!defined(FALLOFFDIRECTIONAL)) -#define FALLOFFDIRECTIONAL() /* No op */ -#endif -#if (!defined(FALLOFFPOINT)) -#define FALLOFFPOINT() /* No op */ -#endif -#if (!defined(FALLOFFSPOT)) -#define FALLOFFSPOT() /* No op */ -#endif -#if (!defined(FALLOFFSOFTSPOT)) -#define FALLOFFSOFTSPOT() /* No op */ -#endif - -/*************************************************************************** - _rwApplyAmbientLight - - On entry : Instanced data - : Light - : Optional inverse object matrix - : (to transform light to object space) - : Inverse scale of object - : Surface properties of the light - On exit : - */ - -static void -_rwApplyAmbientLight(VERTSARG, - const void *voidLight, - const RwMatrix * __RWUNUSED__ inverseMat, - RwReal __RWUNUSED__ invScale, - const RwSurfaceProperties * surfaceProps) -{ - CAMVERTDECL; - NUMVERTDECL; - const RpLight *light = (const RpLight *) voidLight; - RwReal scale; - RwV3d vertToLight; - - RWFUNCTION(RWSTRING("_rwApplyAmbientLight")); - RWASSERT(light); - RWASSERT(surfaceProps); - - CAMVERTINIT(); - NUMVERTINIT(); - - /* No directional component: - * (this is used in CAMVERTADDRGBA in a specular lighting node) */ - vertToLight.x = 0; - vertToLight.y = 0; - vertToLight.z = 0; - - /* rpLIGHTAMBIENT - Constant illumination on all vertices - */ - if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) - { - scale = 255.0f * light->color.red * surfaceProps->ambient; - - /* Ambient light affects all vertices the same */ - while (numVert--) - { - RwReal lum = scale; - -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFAMBIENT - CAMVERTADDRGBA(1, 1, 1, 0); - CAMVERTINC(); - } - } - else - /* perform for coloured lights */ - { - scale = 255.0f * surfaceProps->ambient; - - /* Ambient light affects all vertices the same */ - while (numVert--) - { - RwReal lum = scale; - -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFAMBIENT - CAMVERTADDRGBA(light->color.red, light->color.green, - light->color.blue, 0); - CAMVERTINC(); - } - } - RWRETURNVOID(); -} - -/*************************************************************************** - _rwApplyDirectionalLight - - On entry : Instanced data - : Light - : Optional inverse object matrix - : (to transform light to object space) - : Inverse scale of object - : Surface properties of the light - On exit : - */ - -static void -_rwApplyDirectionalLight(VERTSARG, - const void *voidLight, - const RwMatrix * inverseMat, - RwReal __RWUNUSED__ invScale, - const RwSurfaceProperties * surfaceProps) -{ - OBJCAMVERTDECL; - NUMVERTDECL; - const RpLight *light = (const RpLight *) voidLight; - RwV3d vertToLight; - RwReal scale; - RwReal dot; - RwFrame *lightFrame; - - RWFUNCTION(RWSTRING("_rwApplyDirectionalLight")); - RWASSERT(light); - RWASSERT(surfaceProps); - - OBJCAMVERTINIT(); - NUMVERTINIT(); - - /* rpLIGHTDIRECTIONAL - Lighting scaled by dot product - * of vertex normal and light lookAt vector. - */ - /* This may not have a frame - we need to check */ - lightFrame = RpLightGetFrame(light); - if (lightFrame) - { - vertToLight = RwFrameGetLTM(lightFrame)->at; - - /* Transform the light into object space if necessary */ - if (inverseMat) - { - RwV3dTransformVectors(&vertToLight, &vertToLight, 1, inverseMat); - _rwV3dNormalize(&vertToLight, &vertToLight); - } - - /* Vert TO light */ - RwV3dScale(&vertToLight, &vertToLight, -1); - - /* Optimise for grey lights? */ - if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) - { - /* Use one of the light colour intensities as general intensity */ - /* light vector tests are to be identical to others */ - scale = 255.0f * light->color.red * surfaceProps->diffuse; - - /* Loop through each of the vertices */ - while (numVert--) - { - RwV3d objNormal; - - OBJVERTGETNORMAL(&objNormal); - /* Calculate angle between vertex normal and light vector */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - - /* Ensure vector is facing light, - * don't light areas not facing */ - - if (dot > 0.0f) - { - RwReal lum = dot * scale; - -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFDIRECTIONAL - CAMVERTADDRGBA(1, 1, 1, 0); - } - - /* Next vertex */ - OBJCAMVERTINC(); - } - } - else - /* perform for coloured lights */ - { - scale = 255.0f * surfaceProps->diffuse; - - /* Loop through each of the vertices */ - while (numVert--) - { - RwV3d objNormal; - - OBJVERTGETNORMAL(&objNormal); - /* Calculate angle between vertex normal and light vector */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - - /* Ensure vector is facing light, - * don't light areas not facing */ - - if (dot > 0.0f) - { - RwReal lum = dot * scale; - -#define FALLOFFCALC FALLOFFDIRECTIONAL - CAMVERTADDRGBA(light->color.red, light->color.green, - light->color.blue, 0); - } - - /* Next vertex */ - OBJCAMVERTINC(); - } - } - } - - RWRETURNVOID(); -} - -/*************************************************************************** - _rwApplyPointLight - - On entry : Instanced data - : Light - : Optional inverse object matrix - : (to transform light to object space) - : Inverse scale of object - : Surface properties of the light - On exit : - */ - -static void -_rwApplyPointLight(VERTSARG, const void *voidLight, - const RwMatrix * inverseMat, - RwReal invScale, const RwSurfaceProperties * surfaceProps) -{ - OBJCAMVERTDECL; - NUMVERTDECL; - const RpLight *light = (const RpLight *) voidLight; - RwReal scale, recipRad; - RwV3d lightPos, vertToLight; - RwReal radSquared; - - RWFUNCTION(RWSTRING("_rwApplyPointLight")); - RWASSERT(light); - RWASSERT(surfaceProps); - - OBJCAMVERTINIT(); - NUMVERTINIT(); - - /* rpLIGHTPOINT - Linear falloff with distance, scaled by - * dot product of vertex normal and light to vertex vector. - */ - lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; - - if (inverseMat) - { - RwReal scaledRad; - - scaledRad = ((light->radius) * (invScale)); - radSquared = ((scaledRad) * (scaledRad)); - recipRad = (((RwReal) (1)) / (scaledRad)); - - /* Transform light into object space */ - RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); - } - else - { - radSquared = ((light->radius) * (light->radius)); - recipRad = (((RwReal) (1)) / (light->radius)); - } - - if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) - { - /* The scale encapsulates the common elements to do - * with light intensity and surface lighting properties - */ - scale = - ((((RwReal) (255)) * (light->color.red))) * - (surfaceProps->diffuse); - - while (numVert--) - { - RwV3d objVertex, objNormal; - RwReal dot, dist2; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Discover the vector between vertex and light and it's length */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - /* Ensure vertex lies within the light's radius */ - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - if (dist2 < radSquared) - { - RwReal lum; - RwReal recipDist; - RwReal dist; - - rwSqrt(&dist, dist2); - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - /* - * The following simplifies down to: - * - * -scale * - * (dot/dist) * - * (1 - dist/lightRadius) - * - * Where - * scale - * takes care of the light intensity and - * diffuse lighting coefficient - * (dot/dist) - * is a normalised dot product of - * light->vertex vector and vertex normal - * (1 - dist/lightRadius) - * is a linear falloff factor - */ - lum = scale * dot * (recipDist - recipRad); - - /* Calculate the luminance at vertex */ -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFPOINT - CAMVERTADDRGBA(1, 1, 1, 0); - } - } - - OBJCAMVERTINC(); - } - } - else - { - scale = (((RwReal) (255)) * (surfaceProps->diffuse)); - - while (numVert--) - { - RwV3d objVertex, objNormal; - RwReal dot, dist2; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Discover the vector between vertex and light and it's length */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - - /* Ensure vertex lies within the light's radius */ - if (dist2 < radSquared) - { - RwReal lum; - RwReal recipDist; - RwReal dist; - - /* Only now calculate the actual length of vector */ - rwSqrt(&dist, dist2); - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - lum = scale * dot * (recipDist - recipRad); - /* Alter the luminance according to light colour */ -#define FALLOFFCALC FALLOFFPOINT - CAMVERTADDRGBA(light->color.red, light->color.green, - light->color.blue, 0); - } - } - - /* Next point */ - OBJCAMVERTINC(); - } - } - RWRETURNVOID(); -} - -/*************************************************************************** - _rwApplySpotLight - - On entry : Instanced data - : Light - : Optional inverse object matrix - : (to transform light to object space) - : Inverse scale of object - : Surface properties of the light - On exit : - */ - -static void -_rwApplySpotLight(VERTSARG, - const void *voidLight, - const RwMatrix * inverseMat, - RwReal invScale, const RwSurfaceProperties * surfaceProps) -{ - OBJCAMVERTDECL; - NUMVERTDECL; - const RpLight *light = (const RpLight *) voidLight; - RwReal recipRad; - RwReal radSquared; - RwV3d lightPos, at; - - RWFUNCTION(RWSTRING("_rwApplySpotLight")); - RWASSERT(light); - RWASSERT(surfaceProps); - - OBJCAMVERTINIT(); - NUMVERTINIT(); - - /* rpLIGHTSPOT - Linear falloff with distance, cone to restrict - * angle that light has effect, constant intensity across cone, - * scaled by dot product of vertex normal and light to vertex vector. - */ - - lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; - at = RwFrameGetLTM(RpLightGetFrame(light))->at; - - if (inverseMat) - { - RwReal scaledRad; - - scaledRad = ((light->radius) * (invScale)); - recipRad = (((RwReal) (1)) / (scaledRad)); - radSquared = ((scaledRad) * (scaledRad)); - - /* Transform light into object space */ - /* The at is required to ensure within cone */ - RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); - RwV3dTransformVectors(&at, &at, 1, inverseMat); - _rwV3dNormalize(&at, &at); - } - else - { - recipRad = (((RwReal) (1)) / (light->radius)); - radSquared = ((light->radius) * (light->radius)); - } - - if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) - { - RwReal scale = - - ((RwReal) 255) * (light->color.red) * (surfaceProps->diffuse); - - while (numVert--) - { - RwV3d vertToLight, objVertex, objNormal; - RwReal dot; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Find the squared distance from light point to vertex */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - RwReal dist2; - - /* Ensure vertex lies within the light's radius */ - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - if (dist2 < radSquared) - { - RwReal dist; - RwReal compare; - RwReal proj; - - rwSqrt(&dist, dist2); - compare = dist * light->minusCosAngle; - proj = RwV3dDotProduct(&vertToLight, &at); - - if (proj < compare) - { - RwReal lum; - RwReal recipDist; - - /* Get the real distance from the light - * to the vertex (not squared) */ - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - /* This model is the same as the point source - * inside the cone, zero outside the cone */ - lum = scale * dot * (recipDist - recipRad); -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFSPOT - CAMVERTADDRGBA(1, 1, 1, 0); - } - } - /* Next vertex */ - OBJCAMVERTINC(); - } - } - } - else - { - RwReal scale = - - (((RwReal) (255)) * (surfaceProps->diffuse)); - - while (numVert--) - { - RwV3d vertToLight, objVertex, objNormal; - RwReal dot; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Find the squared distance from light point to vertex */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - RwReal dist2; - - /* Ensure vertex lies within the light's radius */ - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - if (dist2 < radSquared) - { - RwReal dist; - RwReal compare; - RwReal proj; - - rwSqrt(&dist, dist2); - compare = dist * light->minusCosAngle; - proj = RwV3dDotProduct(&vertToLight, &at); - - if (proj < compare) - { - RwReal lum; - RwReal recipDist; - - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - /* This model is the same as the point source - * inside the cone, zero outside the cone */ - lum = scale * dot * (recipDist - recipRad); - - /* Introduce the light colours as a - * scaling factor for luminance */ -#define FALLOFFCALC FALLOFFSPOT - CAMVERTADDRGBA(light->color.red, - light->color.green, light->color.blue, - 0); - } - } - } - - /* Next */ - OBJCAMVERTINC(); - } - } - - RWRETURNVOID(); -} - -/*************************************************************************** - _rwApplySpotSoftLight - - On entry : Instanced data - : Light - : Optional inverse object matrix - : (to transform light to object space) - : Inverse scale of object - : Surface properties of the light - On exit : - */ - -static void -_rwApplySpotSoftLight(VERTSARG, const void *voidLight, - const RwMatrix * inverseMat, RwReal invScale, - const RwSurfaceProperties * surfaceProps) -{ - OBJCAMVERTDECL; - NUMVERTDECL; - const RpLight *light = (const RpLight *) voidLight; - RwReal recipRad; - RwReal radSquared; - RwV3d lightPos, at; - - RWFUNCTION(RWSTRING("_rwApplySpotSoftLight")); - RWASSERT(light); - RWASSERT(surfaceProps); - - OBJCAMVERTINIT(); - NUMVERTINIT(); - - /* rpLIGHTSPOTSOFT - Linear falloff with distance, cone to restrict - * angle that light has effect, falloff to edge of cone, scaled by - * dot product of vertex normal and light to vertex vector. - */ - - lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; - at = RwFrameGetLTM(RpLightGetFrame(light))->at; - - if (inverseMat) - { - RwReal scaledRad; - - scaledRad = ((light->radius) * (invScale)); - recipRad = (((RwReal) (1)) / (scaledRad)); - radSquared = ((scaledRad) * (scaledRad)); - - /* Transform light into object space */ - /* The at is required to ensure within cone */ - RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); - RwV3dTransformVectors(&at, &at, 1, inverseMat); - _rwV3dNormalize(&at, &at); - } - else - { - recipRad = 1.0f / light->radius; - radSquared = light->radius * light->radius; - } - - if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) - { - RwReal scale = - - ((RwReal) 255) * (light->color.red) * (surfaceProps->diffuse); - - while (numVert--) - { - RwV3d vertToLight, objVertex, objNormal; - RwReal dot; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Find the squared distance from light point to vertex */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - RwReal dist2; - - /* Ensure vertex lies within the light's radius */ - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - if (dist2 < radSquared) - { - RwReal dist; - RwReal compare; - RwReal proj; - - rwSqrt(&dist, dist2); - compare = dist * light->minusCosAngle; - proj = RwV3dDotProduct(&vertToLight, &at); - - if (proj < compare) - { - RwReal lum; - RwReal recipDist; - RwReal normalise; - - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - /* This model is the same as the point source - * inside the cone, zero outside the cone */ - lum = scale * dot * (recipDist - recipRad); - - /* It has an extra term for quadratic falloff - * across the cone though */ - normalise = (dist + compare); - RWASSERT(normalise >= 0.0f); - if (normalise > 0.0f) - { - normalise = (dist + proj) / normalise; - - normalise *= normalise; - lum *= (((RwReal) 1) - normalise); - } - -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFSOFTSPOT - CAMVERTADDRGBA(1, 1, 1, 0); - } - } - } - - /* Next */ - OBJCAMVERTINC(); - } - } - - else - { - RwReal scale = 255.0f * surfaceProps->diffuse; - - while (numVert--) - { - RwV3d vertToLight, objVertex, objNormal; - RwReal dot; - - OBJVERTGETPOS(&objVertex); - OBJVERTGETNORMAL(&objNormal); - - /* Find the squared distance from light point to vertex */ - RwV3dSub(&vertToLight, &lightPos, &objVertex); - - /* Ensure that this vertex is facing the light source */ - dot = RwV3dDotProduct(&vertToLight, &objNormal); - if (dot > 0.0f) - { - RwReal dist2; - - /* Ensure vertex lies within the light's radius */ - dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); - if (dist2 < radSquared) - { - RwReal dist; - RwReal compare; - RwReal proj; - - rwSqrt(&dist, dist2); - compare = dist * light->minusCosAngle; - proj = RwV3dDotProduct(&vertToLight, &at); - - if (proj < compare) - { - - RwReal lum; - RwReal normalise; - RwReal recipDist; - - /* Get the real distance from the light - * to the vertex (not squared) */ - recipDist = - (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; - - /* This model is the same as the point source - * inside the cone, zero outside the cone */ - lum = scale * dot * (recipDist - recipRad); - - /* It has an extra term for quadratic falloff - * across the cone though */ - /* It has an extra term for quadratic falloff - * across the cone though */ - normalise = (dist + compare); - RWASSERT(normalise >= 0.0f); - if (normalise > 0.0f) - { - normalise = (dist + proj) / normalise; - - normalise *= normalise; - lum *= (((RwReal) 1) - normalise); - - } - /* Introduce the light colours as a - * scaling factor for luminance */ -#undef FALLOFFCALC -#define FALLOFFCALC FALLOFFSOFTSPOT - CAMVERTADDRGBA(light->color.red, - light->color.green, - light->color.blue, 0); - } - } - } - - /* Next */ - OBJCAMVERTINC(); - } - } - - RWRETURNVOID(); -} diff --git a/rwsdk/include/d3d8/rpanisot.h b/rwsdk/include/d3d8/rpanisot.h index 4f4445a4..323786f4 100644 --- a/rwsdk/include/d3d8/rpanisot.h +++ b/rwsdk/include/d3d8/rpanisot.h @@ -7,7 +7,7 @@ /** * \defgroup rpanisot RpAnisot - * \ingroup rpplugin + * \ingroup mipmapping * * Anisotropic Texture Sampling Plugin for RenderWare Graphics. */ @@ -22,7 +22,7 @@ * \li \b Plugin \b attachments: \ref RpWorldPluginAttach, \ref RpAnisotPluginAttach * * \subsection anisotoverview Overview - * The RpAnisot plugin is used to extend an RwTexture with a maximum + * The RpAnisot plugin is used to extend an \ref RwTexture with a maximum * anisotropy value that will be used when a particular texture is drawn. * When textured polygons are viewed nearly edge on, for example when looking * dowm a road or a football pitch, distant pixels are not sampled very well diff --git a/rwsdk/include/d3d8/rpanisot.rpe b/rwsdk/include/d3d8/rpanisot.rpe index 5216ec9c..0464081f 100644 --- a/rwsdk/include/d3d8/rpanisot.rpe +++ b/rwsdk/include/d3d8/rpanisot.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpcollis.h b/rwsdk/include/d3d8/rpcollis.h index 908fb68e..23e67f35 100644 --- a/rwsdk/include/d3d8/rpcollis.h +++ b/rwsdk/include/d3d8/rpcollis.h @@ -31,7 +31,7 @@ /** * \defgroup rpcollis RpCollision - * \ingroup rpplugin + * \ingroup collisiondetection * * Collision Plugin for RenderWare Graphics. */ @@ -67,12 +67,12 @@ enum RpIntersectType }; typedef enum RpIntersectType RpIntersectType; +typedef union RpIntersectData RpIntersectData; /** * \ingroup rpcollis * RpIntersectData, this union type is used to specify the parameters * for an intersection primitive of the desired type (\ref RpIntersectType) */ -typedef union RpIntersectData RpIntersectData; union RpIntersectData { RwLine line; /** #include -static const char rcsid[] __RWUNUSED__ = "@@(#)$Id: //RenderWare/RW33Active/dev/rwsdk/src/plcore/rpdbgerr.c#1 $"; +static const char rcsid[] __RWUNUSED__ = "@@(#)$Id: rpdbgerr.c,v 1.2 2004/08/31 17:40:34 gtristram Exp $"; #ifdef RWDEBUG diff --git a/rwsdk/include/d3d8/rpdbgerr.h b/rwsdk/include/d3d8/rpdbgerr.h index 6918469a..e0500057 100644 --- a/rwsdk/include/d3d8/rpdbgerr.h +++ b/rwsdk/include/d3d8/rpdbgerr.h @@ -16,8 +16,6 @@ /* Pick up _ASSERTE macro */ #ifdef _XBOX #include -#else /* _XBOX */ -#include #endif /* _XBOX */ #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) #define _CRTDBG_MAP_ALLOC @@ -235,6 +233,22 @@ do \ } \ while (0) +#define RWASSERTM(condition, messageArgs) \ +do \ +{ \ + if (!(condition)) \ + { \ + RwDebugSendMessage(rwDEBUGASSERT, \ + __dbFunctionName, \ + RWSTRING(#condition)); \ + RwDebugSendMessage(rwDEBUGMESSAGE, \ + __dbFunctionName, \ + _rwdbsprintf messageArgs); \ + } \ + RWASSERTE(condition); \ +} \ +while (0) + #else /* RWDEBUG */ #define RWRETURN(value) return(value) @@ -253,6 +267,7 @@ while (0) #define RWFUNCTION(name) #define RWAPIFUNCTION(name) #define RWASSERT(condition) +#define RWASSERTM(condition, messageArgs) #define RWMESSAGE(args) #endif diff --git a/rwsdk/include/d3d8/rpdmorph.h b/rwsdk/include/d3d8/rpdmorph.h index 1494bf3d..89c51b31 100644 --- a/rwsdk/include/d3d8/rpdmorph.h +++ b/rwsdk/include/d3d8/rpdmorph.h @@ -28,7 +28,7 @@ /** * \defgroup rpdmorph RpDMorph - * \ingroup rpplugin + * \ingroup deltamorphing * \file rpdmorph.h * * Delta Morphing Plugin for RenderWare Graphics. @@ -153,7 +153,7 @@ RpDMorphTargetGetFlags( RpDMorphTarget *dMorphTarget ); * These functions work at the DMorphAtomic level. */ extern RpAtomic * -RpDMorphAtomicInitalize( RpAtomic *atomic ); +RpDMorphAtomicInitialize( RpAtomic *atomic ); extern RwReal * RpDMorphAtomicGetDMorphValues( RpAtomic *atomic ); diff --git a/rwsdk/include/d3d8/rpdmorph.rpe b/rwsdk/include/d3d8/rpdmorph.rpe index a5202425..b35acc4e 100644 --- a/rwsdk/include/d3d8/rpdmorph.rpe +++ b/rwsdk/include/d3d8/rpdmorph.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rphanim.h b/rwsdk/include/d3d8/rphanim.h index a9b0438a..0d1bba7a 100644 --- a/rwsdk/include/d3d8/rphanim.h +++ b/rwsdk/include/d3d8/rphanim.h @@ -26,7 +26,6 @@ * Purpose : Hierarchical animation * * * **************************************************************************/ - #ifndef RPHANIM_H #define RPHANIM_H @@ -38,7 +37,7 @@ /** * \defgroup rphanim RpHAnim - * \ingroup rpplugin + * \ingroup objectframehanim * * Hierarchical Animation Plugin for RenderWare Graphics. */ @@ -66,45 +65,26 @@ */ #include /* automatically generated header file */ #include +#include #define rpHANIMSTREAMCURRENTVERSION 0x100 -/** - * \ingroup rphanim - * \ref RpHAnimAtomicGlobalVars typedef for struct RpHAnimAtomicGlobalVars - */ +#if (!defined(DOXYGEN)) + typedef struct RpHAnimAtomicGlobalVars RpHAnimAtomicGlobalVars; -/** - * \ingroup rphanim - * \struct RpHAnimAtomicGlobalVars - */ struct RpHAnimAtomicGlobalVars { - RwInt32 engineOffset ; /* Offset into global data */ + RwInt32 engineOffset; RwFreeList *HAnimFreeList; - RwFreeList *HAnimAnimationFreeList; }; -extern RpHAnimAtomicGlobalVars RpHAnimAtomicGlobals; +#endif /* (!defined(DOXYGEN)) */ -#define rpHANIMSTDKEYFRAMESIZE sizeof(RpHAnimStdKeyFrame) +#define rpHANIMSTDKEYFRAMESIZE sizeof(RpHAnimKeyFrame) #define rpHANIMSTDKEYFRAMETYPEID 0x1 -#define RwAnimMalloc() \ - RwFreeListAlloc(RpHAnimAtomicGlobals.HAnimFreeList) - -#define RwAnimFree(_anim) \ - RwFreeListFree(RpHAnimAtomicGlobals.HAnimFreeList, (_anim)) - -#define RwAnimAnimationMalloc() \ - RwFreeListAlloc(RpHAnimAtomicGlobals.HAnimAnimationFreeList) - -#define RwAnimAnimationFree(_animAnimation) \ - RwFreeListFree(RpHAnimAtomicGlobals.HAnimAnimationFreeList, \ - (_animAnimation)) - -#define RpV3dInterpolate(o, a, s, b) \ +#define RpV3dInterpolate(o,a,s,b) \ MACRO_START \ { \ (o)->x = (((a)->x) + ((s)) * (((b)->x) - ((a)->x))); \ @@ -113,224 +93,58 @@ MACRO_START \ } \ MACRO_STOP + +/** + * \ingroup rphanim + * \ref RpHAnimKeyFrame + * typedef for struct RpHAnimKeyFrame. Based on \ref RtAnimKeyFrameHeader. + */ +typedef struct RpHAnimKeyFrame RpHAnimKeyFrame; + +/** + * \ingroup rphanim + * \struct RpHAnimKeyFrame + * A structure representing the standard keyframe data. Sequences of + * such keyframes in an \ref RtAnimAnimation defines the animation of each + * node in a hierarchy. + */ +struct RpHAnimKeyFrame +{ + RpHAnimKeyFrame *prevFrame; /**< Pointer to the previous keyframe */ + RwReal time; /**< Time at keyframe */ + RtQuat q; /**< Quaternion rotation at keyframe */ + RwV3d t; /**< Translation at keyframe */ +}; + +/** + * \ingroup rphanim + * \ref RpHAnimInterpFrame + * typedef for struct RpHAnimInterpFrame. Based on \ref RtAnimInterpFrameHeader. + */ +typedef struct RpHAnimInterpFrame RpHAnimInterpFrame; + +/** + * \ingroup rphanim + * \struct RpHAnimInterpFrame + * A structure representing an interpolated keyframe. The initial part of the + * structure matches \ref RtAnimInterpFrameHeader. + */ +struct RpHAnimInterpFrame +{ + RpHAnimKeyFrame *keyFrame1; + /**< Pointer to 1st keyframe of current interpolation pair */ + RpHAnimKeyFrame *keyFrame2; + /**< Pointer to 2nd keyframe of current interpolation pair */ + RtQuat q; /**< Quaternion rotation */ + RwV3d t; /**< Translation */ +}; + /** * \ingroup rphanim * \ref RpHAnimHierarchy typedef for struct RpHAnimHierarchy */ typedef struct RpHAnimHierarchy RpHAnimHierarchy; -/** - * \ingroup rphanim - * \ref RpHAnimAnimation typedef for struct RpHAnimAnimation - */ -typedef struct RpHAnimAnimation RpHAnimAnimation; - -/** - * \ingroup rphanim - * \ref RpHAnimHierarchyCallBack - * This typedef defines a callback function for use with the - * \ref RpHAnimHierarchySetAnimCallBack and - * \ref RpHAnimHierarchySetAnimLoopCallBack functions. - * - * \param hierarchy - * A pointer to the AnimHierarchy structure. - * - * \param data User-defined data. - * You can use this to pass your own data - * structure(s) to the callback function. - * - * \see RpHAnimHierarchySetAnimCallBack - * \see RpHAnimHierarchySetAnimLoopCallBack - * - */ - -typedef RpHAnimHierarchy * (*RpHAnimHierarchyCallBack) (RpHAnimHierarchy *hierarchy, - void *data); - -/* - * The following CallBacks are needed for each overloaded interpolation - * scheme. See RpHAnimInterpolatorInfo. - */ - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameToMatrixCallBack - * This typedef defines a callback function for converting - * an animation keyframe into a modeling matrix. The output matrix will be - * used to construct the array of world or local space matrices for the - * hierarchy as obtained with \ref RpHAnimHierarchyGetMatrixArray, and - * possibly used for updating an external \ref RwFrame hierarchy. - * - * \param matrix This is the matrix to store the output of the conversion - * \param voidIFrame This is a void pointer to the keyframe and should be cast - * to the keyframe type this callback is for. - */ -typedef void (*RpHAnimKeyFrameToMatrixCallBack) (RwMatrix *matrix, void *voidIFrame); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameBlendCallBack - * This typedef defines a callback function for blending between two animation - * keyframes by the given blend factor. - * - * \param voidOut This is the void pointer for the output of the blend - * \param voidIn1 First input keyframe - * \param voidIn2 Second input keyframe - * \param alpha Blend factor - */ -typedef void (*RpHAnimKeyFrameBlendCallBack) (void *voidOut, void *voidIn1, - void *voidIn2, RwReal alpha); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameInterpolateCallBack - * This typedef defines a callback function for interpolating between two - * animation keyframes according to the given time. - * - * \param voidOut This is the void pointer for the output of the - * interpolation - * \param voidIn1 First input keyframe - * \param voidIn2 Second input keyframe - * \param time Time at which to interpolate - */ -typedef void (*RpHAnimKeyFrameInterpolateCallBack) (void *voidOut, void *voidIn1, - void *voidIn2, RwReal time); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameAddCallBack - * This typedef defines a callback function for adding together two animation - * keyframes. One of the keyframes would usually be a delta. - * - * \param voidOut This is the void pointer for the output summed keyframe - * \param voidIn1 First input keyframe - * \param voidIn2 Second input keyframe - */ -typedef void (*RpHAnimKeyFrameAddCallBack) (void *voidOut, void *voidIn1, - void *voidIn2); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameMulRecipCallBack - * This typedef defines a callback function for multiplying a keyframe - * by the inverse of another keyframe - * - * \param voidFrame This is the void pointer for the keyframe to be modified - * \param voidStart First start keyframe to take the reciprocal of. - */ -typedef void (*RpHAnimKeyFrameMulRecipCallBack) (void *voidFrame, void *voidStart); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameStreamReadCallBack - * This typedef defines a callback function for reading in keyframes - * from an \ref RwStream for the given animation. - * - * \param stream The stream to read the keyframes from - * \param animation The animation to read the keyframes into - * - * \return Pointer to the animation. - */ -typedef RpHAnimAnimation * (*RpHAnimKeyFrameStreamReadCallBack) (RwStream *stream, RpHAnimAnimation *animation); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameStreamWriteCallBack - * This typedef defines a callback function for writing keyframes from the - * given animation to an \ref RwStream. - * - * \param animation The animation to write out from - * \param stream The stream to write the keyframes to - * - * \return TRUE if successful. - */ -typedef RwBool (*RpHAnimKeyFrameStreamWriteCallBack) (RpHAnimAnimation *animation, RwStream *stream); - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameStreamGetSizeCallBack - * This typedef defines a callback function for calculating the binary stream - * size of keyframe data within an animation. - * - * \param animation The animation to calculate sizes of - * - * \return Size in bytes of the keyframe data. - */ -typedef RwInt32 (*RpHAnimKeyFrameStreamGetSizeCallBack) (RpHAnimAnimation *animation); - -/** - * \ingroup rphanim - * \ref RpHAnimInterpolatorInfo - * typedef for struct \ref RpHAnimInterpolatorInfo - */ -typedef struct RpHAnimInterpolatorInfo RpHAnimInterpolatorInfo; - -/** - * \ingroup rphanim - * \struct RpHAnimInterpolatorInfo - * This is used to hold information for a keyframe interpolation scheme. - * - * \see RpHAnimRegisterInterpolationScheme - * \see RpHAnimGetInterpolatorInfo - */ -struct RpHAnimInterpolatorInfo -{ - RwInt32 typeID; /**< The ID of the interpolation scheme */ - RwInt32 keyFrameSize; /**< Size in bytes of the keyframe structure */ - RpHAnimKeyFrameToMatrixCallBack keyFrameToMatrixCB; /**< Pointer to a function that converts a keyframe to a matrix */ - RpHAnimKeyFrameBlendCallBack keyFrameBlendCB; /**< Pointer to a function that blends between a pair of keyframes for a given delta value */ - RpHAnimKeyFrameInterpolateCallBack keyFrameInterpolateCB; /**< Pointer to a function that interpolates between two keyframes for a given time in between */ - RpHAnimKeyFrameAddCallBack keyFrameAddCB; /**< Pointer to a function that adds two keyframes (one of which may be a delta) */ - RpHAnimKeyFrameMulRecipCallBack keyFrameMulRecipCB; /**< Pointer to a function that multiplies a keyframe by the reciprocal of another */ - RpHAnimKeyFrameStreamReadCallBack keyFrameStreamReadCB; /**< Pointer to a function that reads the keyframes from a stream for a given animation */ - RpHAnimKeyFrameStreamWriteCallBack keyFrameStreamWriteCB; /**< Pointer to a function that writes the keyframes to a stream for a given animation */ - RpHAnimKeyFrameStreamGetSizeCallBack keyFrameStreamGetSizeCB; /**< Pointer to a function that returns the binary stream size of the keyframes for a given animation */ -}; - -/** - * \ingroup rphanim - * \ref RpHAnimKeyFrameHeader - * typedef for struct RpHAnimKeyFrameHeader - */ -typedef struct RpHAnimKeyFrameHeader RpHAnimKeyFrameHeader; - -/** - * \ingroup rphanim - * \struct RpHAnimKeyFrameHeader - * Holds header information for a keyframe. All keyframe structures used with - * the overloadable interpolation system should start with this data. - * - * \see RpHAnimStdKeyFrame - * \see RpHAnimRegisterInterpolationScheme - */ -struct RpHAnimKeyFrameHeader -{ - void *prevFrame; /**< Previous keyframe for particular hierarchy node */ - RwReal time; /**< Time at keyframe */ -}; - -/** - * \ingroup rphanim - * \ref RpHAnimStdKeyFrame - * typedef for struct RpHAnimStdKeyFrame - */ -typedef struct RpHAnimStdKeyFrame RpHAnimStdKeyFrame; - -/** - * \ingroup rphanim - * \struct RpHAnimStdKeyFrame - * A structure representing the standard keyframe data. Sequences of - * such keyframes in an \ref RpHAnimAnimation defines the animation of each - * node in a hierarchy. - */ -struct RpHAnimStdKeyFrame -{ - RpHAnimStdKeyFrame *prevFrame; /**< Previous keyframe for particular hierarchy node */ - RwReal time; /**< Time at keyframe */ - RtQuat q; /**< Quaternion rotation at keyframe */ - RwV3d t; /**< Translation at keyframe */ -}; - /* Flags for FrameInfos */ #define rpHANIMPOPPARENTMATRIX 0x01 @@ -347,54 +161,23 @@ typedef struct RpHAnimNodeInfo RpHAnimNodeInfo; * \ingroup rphanim * \struct RpHAnimNodeInfo * + * Used to describe a hierarchy toplogy. + * It holds flags representing its position in the + * hierarchy as well as a pointer to the matching \ref RwFrame if the + * hierarchy has been attached to a \ref RwFrame hierarchy. + * */ struct RpHAnimNodeInfo { - RwInt32 nodeID; /**< User defined ID for this node */ - RwInt32 nodeIndex; /**< Array index of node */ + RwInt32 nodeID; /**< User defined ID for this node */ + RwInt32 nodeIndex; /**< Array index of node */ RwInt32 flags; /**< Matrix push/pop flags */ RwFrame * pFrame; /**< Pointer to an attached RwFrame (see \ref RpHAnimHierarchyAttach) */ }; -/** - * \ingroup rphanim - * \struct RpHAnimAnimation - * A hierarchical animation consists of an array of keyframe structures, - * along with some flags and a duration. - * - * The keyframes should be presented in the order they are needed - * to animate forwards through time. Pointers link all of the keyframes - * for a particular node backwards through time in a list. - * - * For example, a 3 node animation, with keyframes at the following times: - * - * Node 1: 0.0, 1.0, 2.0, 3.0 - * Node 2: 0.0, 3.0 - * Node 3: 0.0, 2.0, 2.5, 3.0 - * - * should be formatted in an RpHAnimAnimation animation like this: - * - * B1,0.0 B2,0.0 B3,0.0 B1,1.0, B2,3.0, B3,2.0, B1,2.0, B1,3.0, B3,2.5 B3,3.0 - * - * Each node MUST start at time = 0.0, and each node must terminate with a keyframe - * at time = duration of animation. - * - * \see RpHAnimAnimationCreate - */ -struct RpHAnimAnimation -{ - RpHAnimInterpolatorInfo *interpInfo; /**< Pointer to interpolation scheme information */ - RwInt32 numFrames; /**< Number of keyframes in the animation */ - RwInt32 flags; /**< Specifies details about animation, relative translation modes etc */ - RwReal duration; /**< Duration of animation in seconds */ - void *pFrames; /**< Pointer to the animation keyframes */ -}; - /** * \ingroup rphanim * \ref RpHAnimHierarchyFlag defines type and update modes in HAnimHierarchies - * - * \see RpAnimHierarchyFlag */ enum RpHAnimHierarchyFlag { @@ -411,9 +194,7 @@ enum RpHAnimHierarchyFlag rpHANIMHIERARCHYFLAGFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; -/** - * \ingroup rphanim - * \typedef RpHAnimHierarchyFlag +/* * These flags are used to control the creation and * update status of the hierarchy */ @@ -422,13 +203,7 @@ typedef enum RpHAnimHierarchyFlag RpHAnimHierarchyFlag; /** * \ingroup rphanim * \struct RpHAnimHierarchy - * An RpHAnimHierarchy is used to "play back" an animation - it holds the - * interpolated keyframe data for the current state of an animation - * concatenated on the end of the structure. - * - * The rpHANIMHIERARCHYGETINTERPFRAME() macro can be used to access the current - * interpolated data, for the current time or to write to this data to override - * it with procedural animation. + * An RpHAnimHierarchy is used to "play back" an animation. * * The structure of a hierarchy is defined by an array * of \ref RpHAnimNodeInfo structures. @@ -443,49 +218,19 @@ struct RpHAnimHierarchy { RwInt32 flags; /**< Flags for the hierarchy */ RwInt32 numNodes; /**< Number of nodes in the hierarchy */ - RpHAnimAnimation *pCurrentAnim; /**< Current animation applied to hierarchy */ - RwReal currentTime; /**< Current animation time */ - void *pNextFrame; /**< Next animation keyframe to be played */ - RpHAnimHierarchyCallBack pAnimCallBack; /**< Animation callback function pointer */ - void *pAnimCallBackData; /**< Animation callback function user data */ - RwReal animCallBackTime; /**< Trigger time for callback function */ - RpHAnimHierarchyCallBack pAnimLoopCallBack; /**< Animation loop callback function pointer */ - void *pAnimLoopCallBackData; /**< Animation loop callback function data */ + RwMatrix *pMatrixArray; /**< Pointer to node matrices*/ void *pMatrixArrayUnaligned; /**< Pointer to memory used for node matrices * from which the aligned pMatrixArray is allocated */ RpHAnimNodeInfo *pNodeInfo; /**< Array of node information (push/pop flags etc) */ RwFrame *parentFrame; /**< Pointer to the Root RwFrame of the hierarchy this * RpHAnimHierarchy represents */ - RwInt32 maxKeyFrameSize; /**< Maximum size of keyframes usable on this hierarhcy - * (set at creation time) */ - RwInt32 currentKeyFrameSize; /**< Size of keyframes in the current animation */ - RpHAnimKeyFrameToMatrixCallBack keyFrameToMatrixCB; /**< Internal use */ - RpHAnimKeyFrameBlendCallBack keyFrameBlendCB; /**< Internal use */ - RpHAnimKeyFrameInterpolateCallBack keyFrameInterpolateCB; /**< Internal use */ - RpHAnimKeyFrameAddCallBack keyFrameAddCB; /**< Internal use */ RpHAnimHierarchy *parentHierarchy; /**< Internal use */ - RwInt32 offsetInParent; /**< Internal use */ RwInt32 rootParentOffset; /**< Internal use */ + + RtAnimInterpolator *currentAnim; /**< Internal use */ }; -#define rpHANIMHIERARCHYGETINTERPFRAME( hierarchy, nodeIndex ) \ - ( (void *)( ( (RwUInt8 *)&(hierarchy[1]) + \ - ((nodeIndex) * \ - hierarchy->currentKeyFrameSize) ) ) ) - -#define rpHANIMHIERARCHYGETINTERPFRAME1( hierarchy, nodeIndex ) \ - ( (void *)( ( (RwUInt8 *)&(hierarchy[1]) + \ - ((hierarchy->numNodes + \ - (nodeIndex)) * \ - hierarchy->currentKeyFrameSize) ) ) ) - -#define rpHANIMHIERARCHYGETINTERPFRAME2( hierarchy, nodeIndex ) \ - ( (void *)( ( (RwUInt8 *)&(hierarchy[1]) + \ - ((hierarchy->numNodes * 2 + \ - (nodeIndex)) * \ - hierarchy->currentKeyFrameSize) ) ) ) - /** * \ingroup rphanim * \ref RpHAnimFrameExtension typedef for struct RpHAnimFrameExtension @@ -496,36 +241,40 @@ typedef struct RpHAnimFrameExtension RpHAnimFrameExtension; /** * \ingroup rphanim * \struct RpHAnimFrameExtension + * + * Used to extend \ref RwFrame objects, and thus + * allow the mapping between animation hierarchy node ID and \ref RwFrame. + * */ struct RpHAnimFrameExtension { - RwInt32 id; /**< ID given to this RwFrame (default of -1) */ + RwInt32 id; /**< ID given to this RwFrame (default of -1) */ RpHAnimHierarchy *hierarchy; /**< Pointer to Animation hierarchy attached to this RwFrame */ }; /*--- Plugin API Functions ---*/ -#define RpHAnimHierarchySetFlagsMacro(hierarchy, _flags) \ +#define RpHAnimHierarchySetFlagsMacro(hierarchy,_flags) \ MACRO_START \ { \ - (hierarchy)->flags = _flags; \ + (hierarchy)->flags = _flags; \ } \ MACRO_STOP #define RpHAnimHierarchyGetFlagsMacro(hierarchy) \ ((hierarchy)->flags) -#define RpHAnimStdKeyFrameToMatrixMacro(_matrix, _voidIFrame) \ +#define RpHAnimKeyFrameToMatrixMacro(_matrix,_voidIFrame) \ MACRO_START \ { \ - RpHAnimStdKeyFrame * iFrame = (RpHAnimStdKeyFrame *)(_voidIFrame); \ + RpHAnimInterpFrame * iFrame = (RpHAnimInterpFrame *)(_voidIFrame); \ \ /* \ * RpHAnim uses the same types of quaternion as RtQuat \ * hence no conjugate call as in RpSkin \ */ \ \ - RtQuatUnitConvertToMatrix(&iFrame->q, (_matrix)); \ + RtQuatUnitConvertToMatrix(&iFrame->q,(_matrix)); \ \ (_matrix)->pos.x = iFrame->t.x; \ (_matrix)->pos.y = iFrame->t.y; \ @@ -534,14 +283,14 @@ MACRO_START \ MACRO_STOP + #if (! defined(RWDEBUG)) -#define RpHAnimHierarchySetFlags(hierarchy, _flags) \ - RpHAnimHierarchySetFlagsMacro(hierarchy, _flags) +#define RpHAnimHierarchySetFlags(hierarchy,_flags) \ + RpHAnimHierarchySetFlagsMacro(hierarchy,_flags) #define RpHAnimHierarchyGetFlags(hierarchy) \ (RpHAnimHierarchyFlag)RpHAnimHierarchyGetFlagsMacro(hierarchy) - #endif /* (! defined(RWDEBUG)) */ #ifdef __cplusplus @@ -549,6 +298,8 @@ extern "C" { #endif /* __cplusplus */ +extern RpHAnimAtomicGlobalVars RpHAnimAtomicGlobals; + #if (defined(RWDEBUG)) extern RpHAnimHierarchy * @@ -560,15 +311,9 @@ RpHAnimHierarchyGetFlags(RpHAnimHierarchy *hierarchy); #endif /* (defined(RWDEBUG)) */ -/* Keyframe Interpolator Types */ - -extern RwBool -RpHAnimRegisterInterpolationScheme(RpHAnimInterpolatorInfo *interpolatorInfo); - -extern RpHAnimInterpolatorInfo * -RpHAnimGetInterpolatorInfo(RwInt32 typeID); - /* Animation hierarchy creation */ +extern void +RpHAnimHierarchySetFreeListCreateParams(RwInt32 blockSize,RwInt32 numBlocksToPrealloc); extern RpHAnimHierarchy * RpHAnimHierarchyCreate(RwInt32 numNodes, @@ -613,45 +358,10 @@ extern RpHAnimHierarchy * RpHAnimFrameGetHierarchy(RwFrame *frame); /* Macros for legacy support of old function names */ -#define RpHAnimSetHierarchy(frame, hierarchy) \ - RpHAnimFrameSetHierarchy(frame, hierarchy) +#define RpHAnimSetHierarchy(frame,hierarchy) \ + RpHAnimFrameSetHierarchy(frame,hierarchy) #define RpHAnimGetHierarchy(frame) RpHAnimFrameGetHierarchy(frame) -extern RwBool -RpHAnimHierarchySetKeyFrameCallBacks(RpHAnimHierarchy *hierarchy, - RwInt32 keyFrameTypeID); - -extern RwBool -RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, - RpHAnimAnimation *anim); - -extern RwBool -RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, - RwReal time); - -extern RwBool -RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, - RwReal time); - -extern RwBool -RpHAnimHierarchyStdKeyFrameAddAnimTime(RpHAnimHierarchy *hierarchy, - RwReal time); - -extern RwBool -RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, - RwReal time); - -extern RpHAnimHierarchy * -RpHAnimHierarchySetAnimCallBack(RpHAnimHierarchy *hierarchy, - RpHAnimHierarchyCallBack callBack, - RwReal time, - void *data ); - -extern RpHAnimHierarchy * -RpHAnimHierarchySetAnimLoopCallBack(RpHAnimHierarchy *hierarchy, - RpHAnimHierarchyCallBack callBack, - void *data ); - extern RwMatrix * RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy); @@ -665,196 +375,48 @@ extern RwInt32 RpHAnimIDGetIndex(RpHAnimHierarchy *hierarchy, RwInt32 ID); -/* Animations */ - -extern RpHAnimAnimation * -RpHAnimAnimationCreate(RwInt32 typeID, - RwInt32 numFrames, - RwInt32 flags, - RwReal duration); - -extern RpHAnimAnimation * -RpHAnimAnimationDestroy(RpHAnimAnimation *animation); - -#ifdef RWDEBUG - -extern RwInt32 -RpHAnimAnimationGetTypeID(RpHAnimAnimation *animation); - -#else /* RWDEBUG */ - -#define RpHAnimAnimationGetTypeID(animation) \ - (animation->interpInfo->typeID) - -#endif /* RWDEBUG */ - -extern RpHAnimAnimation * -RpHAnimAnimationRead(const RwChar * filename); - -extern RwBool -RpHAnimAnimationWrite(RpHAnimAnimation *animation, - const RwChar * filename); - -extern RpHAnimAnimation * -RpHAnimAnimationStreamRead(RwStream *stream); - -extern RwBool -RpHAnimAnimationStreamWrite(RpHAnimAnimation *animation, - RwStream *stream); - -extern RwInt32 -RpHAnimAnimationStreamGetSize(RpHAnimAnimation *animation); - -extern RwBool -RpHAnimAnimationMakeDelta(RpHAnimAnimation *animation, - RwInt32 numNodes, - RwReal time); - /* Plugin support */ extern RwBool RpHAnimPluginAttach(void); -/* Overloadable keyframe functions */ - -#define RpHAnimFrameToMatrixMacro(hierarchy, matrix, iFrame) \ -MACRO_START \ -{ \ - const RpHAnimKeyFrameToMatrixCallBack keyFrameToMatrixCB = \ - (hierarchy)->keyFrameToMatrixCB; \ - \ - if (RpHAnimStdKeyFrameToMatrix == keyFrameToMatrixCB) \ - { \ - RpHAnimStdKeyFrameToMatrixMacro((matrix), (iFrame)); \ - } \ - else \ - { \ - keyFrameToMatrixCB((matrix), (iFrame)); \ - } \ -} \ -MACRO_STOP - -#define RpHAnimFrameInterpolateMacro(hierarchy, out, in1, in2, time) \ -MACRO_START \ -{ \ - (hierarchy)->keyFrameInterpolateCB((out), (in1), (in2), (time)); \ -} \ -MACRO_STOP - -#define RpHAnimFrameBlendMacro(hierarchy, out, in1, in2, fAlpha) \ -MACRO_START \ -{ \ - (hierarchy)->keyFrameBlendCB((out), (in1), (in2), (fAlpha)); \ -} \ -MACRO_STOP - -#define RpHAnimFrameAddTogetherMacro(hierarchy, out, in1, in2) \ -MACRO_START \ -{ \ - (hierarchy)->keyFrameAddCB((out), (in1), (in2)); \ -} \ -MACRO_STOP - -#ifdef RWDEBUG -void -RpHAnimFrameInterpolate(RpHAnimHierarchy *hierarchy, - void *out, void *in1, - void *in2, RwReal time); - -void -RpHAnimFrameBlend(RpHAnimHierarchy *hierarchy, - void *out, - void *in1, - void *in2, - RwReal alpha); - -void -RpHAnimFrameToMatrix(RpHAnimHierarchy *hierarchy, - RwMatrix *matrix, void *iFrame); - -void -RpHAnimFrameAddTogether(RpHAnimHierarchy *hierarchy, - void *out, void *in1, void *in2); - -#else /* RWDEBUG */ - -#define RpHAnimFrameToMatrix(hierarchy, matrix, iFrame) \ - RpHAnimFrameToMatrixMacro(hierarchy, matrix, iFrame) - -#define RpHAnimFrameInterpolate(hierarchy, out, in1, in2, time) \ - RpHAnimFrameInterpolateMacro(hierarchy, out, in1, in2, time) - -#define RpHAnimFrameBlend(hierarchy, out, in1, in2, alpha) \ - RpHAnimFrameBlendMacro(hierarchy, out, in1, in2, alpha) - -#define RpHAnimFrameAddTogether(hierarchy, out, in1, in2) \ - RpHAnimFrameAddTogetherMacro(hierarchy, out, in1, in2) - -#endif /* RWDEBUG */ - -/* Standard keyframe functions */ +/* Hanim keyframe functions */ extern void -RpHAnimStdKeyFrameToMatrix(RwMatrix *matrix, - void * voidIFrame); +RpHAnimKeyFrameApply(void *matrix, + void *voidIFrame); extern void -RpHAnimStdKeyFrameBlend(void *voidOut, +RpHAnimKeyFrameBlend(void *voidOut, void *voidIn1, void *voidIn2, RwReal alpha); extern void -RpHAnimStdKeyFrameInterpolate(void *voidOut, +RpHAnimKeyFrameInterpolate(void *voidOut, void *voidIn1, void *voidIn2, RwReal time); extern void -RpHAnimStdKeyFrameAdd(void *voidOut, +RpHAnimKeyFrameAdd(void *voidOut, void *voidIn1, void *voidIn2); extern void -RpHAnimStdKeyFrameMulRecip(void *voidFrame, +RpHAnimKeyFrameMulRecip(void *voidFrame, void *voidStart); -extern RpHAnimAnimation * -RpHAnimStdKeyFrameStreamRead(RwStream *stream, - RpHAnimAnimation *animation); +extern RtAnimAnimation * +RpHAnimKeyFrameStreamRead(RwStream *stream, + RtAnimAnimation *animation); extern RwBool -RpHAnimStdKeyFrameStreamWrite(RpHAnimAnimation *animation, +RpHAnimKeyFrameStreamWrite(RtAnimAnimation *animation, RwStream *stream); extern RwInt32 -RpHAnimStdKeyFrameStreamGetSize(RpHAnimAnimation *animation); - -/* Hierarchy blending/combination functions */ - -extern RwBool -RpHAnimHierarchyBlend(RpHAnimHierarchy *outHierarchy, - RpHAnimHierarchy *inHierarchy1, - RpHAnimHierarchy *inHierarchy2, - RwReal alpha); -extern RwBool -RpHAnimHierarchyAddTogether(RpHAnimHierarchy *outHierarchy, - RpHAnimHierarchy *inHierarchy1, - RpHAnimHierarchy *inHierarchy2); - -extern RwBool -RpHAnimHierarchyBlendSubHierarchy(RpHAnimHierarchy *outHierarchy, - RpHAnimHierarchy *inHierarchy1, - RpHAnimHierarchy *inHierarchy2, - RwReal alpha); -extern RwBool -RpHAnimHierarchyAddSubHierarchy(RpHAnimHierarchy *outHierarchy, - RpHAnimHierarchy *mainHierarchy, - RpHAnimHierarchy *subHierarchy); - -extern RwBool -RpHAnimHierarchyCopy(RpHAnimHierarchy *outHierarchy, - RpHAnimHierarchy *inHierarchy); +RpHAnimKeyFrameStreamGetSize(RtAnimAnimation *animation); /* Access to RwFrame ID's */ @@ -865,9 +427,215 @@ RpHAnimFrameSetID(RwFrame *frame, extern RwInt32 RpHAnimFrameGetID(RwFrame *frame); +/* + * Utility Functions + */ +#define RpHAnimHierarchySetCurrentAnimMacro(hierarchy,anim)\ + RtAnimInterpolatorSetCurrentAnim((hierarchy)->currentAnim,anim) + +#define RpHAnimHierarchyGetCurrentAnimMacro(hierarchy)\ + RtAnimInterpolatorGetCurrentAnim((hierarchy)->currentAnim) + +#define RpHAnimHierarchySetCurrentAnimTimeMacro(hierarchy,time)\ + RtAnimInterpolatorSetCurrentTime((hierarchy)->currentAnim,time) + +#define RpHAnimHierarchyAddAnimTimeMacro(hierarchy,time)\ + RtAnimInterpolatorAddAnimTime((hierarchy)->currentAnim,time) + +#define RpHAnimHierarchySubAnimTimeMacro(hierarchy,time)\ + RtAnimInterpolatorSubAnimTime((hierarchy)->currentAnim,time) + +#define RpHAnimHierarchySetKeyFrameCallBacksMacro(hierarchy,keyFrameTypeID) \ + RtAnimInterpolatorSetKeyFrameCallBacks((hierarchy)->currentAnim,\ + keyFrameTypeID) + +#define RpHAnimHierarchyBlendMacro(outHierarchy,inHierarchy1,inHierarchy2,alpha)\ + RtAnimInterpolatorBlend((outHierarchy)->currentAnim,\ + (inHierarchy1)->currentAnim,\ + (inHierarchy2)->currentAnim,\ + alpha) + +#define RpHAnimHierarchyAddTogetherMacro(outHierarchy,inHierarchy1,inHierarchy2)\ + RtAnimInterpolatorAddTogether((outHierarchy)->currentAnim,\ + (inHierarchy1)->currentAnim,\ + (inHierarchy2)->currentAnim) + + +#define RpHAnimHierarchySetAnimCallBackMacro(hierarchy,callBack,time,data)\ + RtAnimInterpolatorSetAnimCallBack((hierarchy)->currentAnim,callBack,time,data) + +#define RpHAnimHierarchySetAnimLoopCallBackMacro(hierarchy,callBack,data)\ + RtAnimInterpolatorSetAnimLoopCallBack((hierarchy)->currentAnim,callBack,data) + +#define RpHAnimHierarchyBlendSubHierarchyMacro(outHierarchy,inHierarchy1,inHierarchy2,alpha)\ + RtAnimInterpolatorBlendSubInterpolator((outHierarchy)->currentAnim,(inHierarchy1)->currentAnim,(inHierarchy2)->currentAnim,alpha) + +#define RpHAnimHierarchyAddSubHierarchyMacro(outHierarchy,mainHierarchy,subHierarchy)\ + RtAnimInterpolatorAddSubInterpolator((outHierarchy)->currentAnim,(mainHierarchy)->currentAnim,(subHierarchy)->currentAnim) + +#define RpHAnimHierarchyCopyMacro(outHierarchy,inHierarchy)\ + RtAnimInterpolatorCopy((outHierarchy)->currentAnim,(inHierarchy)->currentAnim) + + + +#ifdef RWDEBUG +extern RwBool +RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, + RtAnimAnimation *anim); + +extern RtAnimAnimation * +RpHAnimHierarchyGetCurrentAnim(RpHAnimHierarchy *hierarchy); + +extern RwBool +RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, + RwReal time); + +extern RwBool +RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, + RwReal time); + +extern RwBool +RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, + RwReal time); + +extern RwBool +RpHAnimHierarchySetKeyFrameCallBacks(RpHAnimHierarchy *hierarchy, + RwInt32 keyFrameTypeID); + +extern void +RpHAnimHierarchySetAnimCallBack(RpHAnimHierarchy *hierarchy, + RtAnimCallBack callBack, + RwReal time, + void *data); + +extern RwBool +RpHAnimHierarchyBlend(RpHAnimHierarchy *outHierarchy, + RpHAnimHierarchy *inHierarchy1, + RpHAnimHierarchy *inHierarchy2, + RwReal alpha); + +extern RwBool +RpHAnimHierarchyAddTogether(RpHAnimHierarchy *outHierarchy, + RpHAnimHierarchy *inHierarchy1, + RpHAnimHierarchy *inHierarchy2); + +extern void +RpHAnimHierarchySetAnimLoopCallBack(RpHAnimHierarchy *hierarchy, + RtAnimCallBack callBack, + void *data); +extern RwBool +RpHAnimHierarchyBlendSubHierarchy(RpHAnimHierarchy *outHierarchy, + RpHAnimHierarchy *inHierarchy1, + RpHAnimHierarchy *inHierarchy2, + RwReal alpha); +extern RwBool +RpHAnimHierarchyAddSubHierarchy(RpHAnimHierarchy *outHierarchy, + RpHAnimHierarchy *mainHierarchy1, + RpHAnimHierarchy *subHierarchy2); +extern RwBool +RpHAnimHierarchyCopy(RpHAnimHierarchy *outHierarchy, + RpHAnimHierarchy *inHierarchy); + +#else + +#define RpHAnimHierarchySetCurrentAnim(hierarchy,anim) \ + RpHAnimHierarchySetCurrentAnimMacro((hierarchy),(anim)) + +#define RpHAnimHierarchyGetCurrentAnim(hierarchy) \ + RpHAnimHierarchyGetCurrentAnimMacro((hierarchy)) + +#define RpHAnimHierarchySetCurrentAnimTime(hierarchy,time) \ + RpHAnimHierarchySetCurrentAnimTimeMacro((hierarchy),(time)) + +#define RpHAnimHierarchyAddAnimTime(hierarchy,time) \ + RpHAnimHierarchyAddAnimTimeMacro((hierarchy),(time)) + +#define RpHAnimHierarchySubAnimTime(hierarchy,time) \ + RpHAnimHierarchySubAnimTimeMacro((hierarchy),(time)) + +#define RpHAnimHierarchySetKeyFrameCallBacks(hierarchy,keyFrameTypeID) \ + RpHAnimHierarchySetKeyFrameCallBacksMacro((hierarchy),(keyFrameTypeID)) + +#define RpHAnimHierarchyBlend(outHierarchy,inHierarchy1,inHierarchy2,alpha) \ + RpHAnimHierarchyBlendMacro((outHierarchy),(inHierarchy1),(inHierarchy2),(alpha)) + +#define RpHAnimHierarchyAddTogether(outHierarchy,inHierarchy1,inHierarchy2) \ + RpHAnimHierarchyAddTogetherMacro((outHierarchy),(inHierarchy1),(inHierarchy2)) + +#define RpHAnimHierarchySetAnimCallBack(hierarchy,callBack,time,data)\ + RpHAnimHierarchySetAnimCallBackMacro((hierarchy),(callBack),(time),(data)) + +#define RpHAnimHierarchySetAnimLoopCallBack(hierarchy,callBack,data)\ + RpHAnimHierarchySetAnimLoopCallBackMacro((hierarchy),(callBack),(data)) + +#define RpHAnimHierarchyBlendSubHierarchy(outHierarchy,inHierarchy1,inHierarchy2,alpha)\ + RpHAnimHierarchyBlendSubHierarchyMacro((outHierarchy),(inHierarchy1),(inHierarchy2),(alpha)) + +#define RpHAnimHierarchyAddSubHierarchy(outHierarchy,mainHierarchy,subHierarchy)\ + RpHAnimHierarchyAddSubHierarchyMacro((outHierarchy),(mainHierarchy),(subHierarchy)) + +#define RpHAnimHierarchyCopy(outHierarchy,inHierarchy)\ + RpHAnimHierarchyCopyMacro((outHierarchy),(inHierarchy)) + +#endif /* RWDEBUG */ + #ifdef __cplusplus } #endif /* __cplusplus */ +/* Legacy TypeDef */ + + +typedef RtAnimAnimation RpHAnimAnimation; +typedef RpHAnimKeyFrame RpHAnimStdKeyFrame; + +/* Legacy Macros */ + + +/* Animations */ + + +#define RpHAnimAnimationCreate(typeID,numFrames,flags,duration)\ + RtAnimAnimationCreate((typeID),(numFrames),(flags),(duration)) + + +#define RpHAnimAnimationDestroy(animation)\ + RtAnimAnimationDestroy((animation)) + +#define RpHAnimAnimationGetTypeID(animation)\ + RtAnimAnimationGetTypeID((animation)) + + +#define RpHAnimAnimationRead(filename)\ + RtAnimAnimationRead((filename)) + + +#define RpHAnimAnimationWrite(animation,filename)\ + RtAnimAnimationWrite((animation),(filename)) + + +#define RpHAnimAnimationStreamRead(stream)\ + RtAnimAnimationStreamRead((stream)) + + +#define RpHAnimAnimationStreamWrite(animation,stream)\ + RtAnimAnimationStreamWrite((animation),(stream)) + + +#define RpHAnimAnimationStreamGetSize(animation)\ + RtAnimAnimationStreamGetSize((animation)) + + +#define RpHAnimAnimationMakeDelta(animation,numNodes,time)\ + RtAnimAnimationMakeDelta((animation),(numNodes),(time)) + + +/* Animation Interpolator */ + +#define RpHAnimHierarchyStdKeyFrameAddAnimTime(hierarchy,time)\ + RpHAnimHierarchyHAnimKeyFrameAddAnimTime((hierarchy),(time)) + +#define RpHAnimHierarchyHAnimKeyFrameAddAnimTime(hierarchy,time)\ + RpHAnimHierarchyAddAnimTime((hierarchy),(time)) #endif /* RPHANIM_H */ diff --git a/rwsdk/include/d3d8/rphanim.rpe b/rwsdk/include/d3d8/rphanim.rpe index c60f8591..1c05d0e9 100644 --- a/rwsdk/include/d3d8/rphanim.rpe +++ b/rwsdk/include/d3d8/rphanim.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -630,11 +164,6 @@ enum e_rwdb_CriterionHANIM { -E_RP_HANIM_INTERP_IDINUSE, - -E_RP_HANIM_INTERP_BLOCKFULL, - -E_RP_HANIM_INTERP_IDUNKNOWN, e_rwdb_CriterionHANIMLAST = RWFORCEENUMSIZEINT }; diff --git a/rwsdk/include/d3d8/rplodatm.h b/rwsdk/include/d3d8/rplodatm.h index d4583338..4e9c8648 100644 --- a/rwsdk/include/d3d8/rplodatm.h +++ b/rwsdk/include/d3d8/rplodatm.h @@ -34,7 +34,7 @@ /** * \defgroup rplodatm RpLODAtomic - * \ingroup rpplugin + * \ingroup scenemanagement * * Level of Detail Management Plugin for RenderWare Graphics. */ @@ -72,6 +72,9 @@ extern "C" { #endif /* __cplusplus */ + extern void + RpLODAtomicCacheSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwBool RpLODAtomicPluginAttach( void ); diff --git a/rwsdk/include/d3d8/rplodatm.rpe b/rwsdk/include/d3d8/rplodatm.rpe index 649bc3bc..a5764cfc 100644 --- a/rwsdk/include/d3d8/rplodatm.rpe +++ b/rwsdk/include/d3d8/rplodatm.rpe @@ -142,472 +142,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rplogo.h b/rwsdk/include/d3d8/rplogo.h index ed527a29..a46823ac 100644 --- a/rwsdk/include/d3d8/rplogo.h +++ b/rwsdk/include/d3d8/rplogo.h @@ -33,7 +33,7 @@ /** * \defgroup rplogo RpLogo - * \ingroup rpplugin + * \ingroup 2dtools * * Logo Plugin for RenderWare Graphics. */ diff --git a/rwsdk/include/d3d8/rplogo.rpe b/rwsdk/include/d3d8/rplogo.rpe index f37b6920..a7f66565 100644 --- a/rwsdk/include/d3d8/rplogo.rpe +++ b/rwsdk/include/d3d8/rplogo.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpltmap.h b/rwsdk/include/d3d8/rpltmap.h index 5add9a26..18c91955 100644 --- a/rwsdk/include/d3d8/rpltmap.h +++ b/rwsdk/include/d3d8/rpltmap.h @@ -1,7 +1,7 @@ /** * \defgroup rpltmap RpLtMap - * \ingroup rpplugin + * \ingroup lighting * * Lightmap Plugin for RenderWare Graphics. */ @@ -17,6 +17,15 @@ #include "rpworld.h" +/* Used during lightmap illumination (sliver triangles are skipped + * (their texels should be filled by dilate()), because their normals + * can't be accurately calculated) */ +#define rpLTMAPDEFAULTSLIVERAREATHRESHOLD (0.001f) + +/* Used during lightmap UV calculation (polySets may be + * joined on the basis of vertices with equal positions) */ +#define rpLTMAPDEFAULTVERTEXWELDTHRESHOLD (0.1f) + #define rpLTMAPDEFAULTLIGHTMAPSIZE 128 #define rpLTMAPMINLIGHTMAPSIZE 16 #define rpLTMAPMAXLIGHTMAPSIZE 512/*?? any better way of determining this ??*/ diff --git a/rwsdk/include/d3d8/rpltmap.rpe b/rwsdk/include/d3d8/rpltmap.rpe index 413caf4c..6e58b62b 100644 --- a/rwsdk/include/d3d8/rpltmap.rpe +++ b/rwsdk/include/d3d8/rpltmap.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpmatfx.h b/rwsdk/include/d3d8/rpmatfx.h index 9b091dd8..fb7ade45 100644 --- a/rwsdk/include/d3d8/rpmatfx.h +++ b/rwsdk/include/d3d8/rpmatfx.h @@ -17,7 +17,7 @@ /** * \defgroup rpmatfx RpMatFX - * \ingroup rpplugin + * \ingroup materials * * Material Effects Plugin for RenderWare Graphics. */ @@ -58,6 +58,10 @@ extern "C" #endif /* __cplusplus */ /*--- Plugin functions ------------------------------------------------------*/ +extern void +RpMatFXMaterialDataSetFreeListCreateParams( RwInt32 blockSize, + RwInt32 numBlocksToPrealloc ); + extern RwBool RpMatFXPluginAttach( void ); diff --git a/rwsdk/include/d3d8/rpmatfx.rpe b/rwsdk/include/d3d8/rpmatfx.rpe index bbc588e3..ba83d96a 100644 --- a/rwsdk/include/d3d8/rpmatfx.rpe +++ b/rwsdk/include/d3d8/rpmatfx.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpmipkl.h b/rwsdk/include/d3d8/rpmipkl.h index 5b8f7e51..82ad7f03 100644 --- a/rwsdk/include/d3d8/rpmipkl.h +++ b/rwsdk/include/d3d8/rpmipkl.h @@ -7,9 +7,9 @@ /** * \defgroup rpmipkl RpMipmapKL - * \ingroup rpplugin + * \ingroup mipmapping * - * PS2/MipMap KL Value Plugin for RenderWare Graphics. + * PlayStation 2 / MipMap KL Value Plugin for RenderWare Graphics. */ #include @@ -19,6 +19,28 @@ extern "C" { #endif +#if (defined(SKY2_DRVMODEL_H)) || (defined(NULLSKY_DRVMODEL_H)) + +#define RpMipmapKLTextureSetDefaultK RpSkyTextureSetDefaultMipmapK + +#define RpMipmapKLTextureSetDefaultL RpSkyTextureSetDefaultMipmapL + +#define RpMipmapKLTextureGetDefaultK RpSkyTextureGetDefaultMipmapK + +#define RpMipmapKLTextureGetDefaultL RpSkyTextureGetDefaultMipmapL + +#define RpMipmapKLTextureSetK RpSkyTextureSetMipmapK + +#define RpMipmapKLTextureSetL RpSkyTextureSetMipmapL + +#define RpMipmapKLTextureGetK RpSkyTextureGetMipmapK + +#define RpMipmapKLTextureGetL RpSkyTextureGetMipmapL + +#define RpMipmapKLPluginAttach() (TRUE) + +#else /* (defined(SKY2_DRVMODEL_H)) || (defined(NULLSKY_DRVMODEL_H)) */ + extern RwReal RpMipmapKLTextureSetDefaultK(RwReal val); extern RwUInt32 RpMipmapKLTextureSetDefaultL(RwUInt32 val); extern RwReal RpMipmapKLTextureGetDefaultK(void); @@ -31,6 +53,8 @@ extern RwUInt32 RpMipmapKLTextureGetL(RwTexture *tex); extern RwBool RpMipmapKLPluginAttach(void); +#endif /* (defined(SKY2_DRVMODEL_H)) || (defined(NULLSKY_DRVMODEL_H)) */ + #ifdef __cplusplus } #endif diff --git a/rwsdk/include/d3d8/rpmipkl.rpe b/rwsdk/include/d3d8/rpmipkl.rpe index 5216ec9c..0464081f 100644 --- a/rwsdk/include/d3d8/rpmipkl.rpe +++ b/rwsdk/include/d3d8/rpmipkl.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpmorph.h b/rwsdk/include/d3d8/rpmorph.h index 4177fba8..52ea70df 100644 --- a/rwsdk/include/d3d8/rpmorph.h +++ b/rwsdk/include/d3d8/rpmorph.h @@ -38,7 +38,7 @@ /** * \defgroup rpmorph RpMorph - * \ingroup rpplugin + * \ingroup morphing * * Morphing Plugin for RenderWare Graphics. */ @@ -76,7 +76,6 @@ struct RpMorphInterpolator /** * \ingroup rpmorph - * \typedef RpMorphGeometryCallBack * This is the callback function supplied to \ref RpMorphGeometrySetCallBack * and returned from \ref RpMorphGeometryGetCallBack. * The supplied function will be passed a pointer to the geometry's parent atomic, diff --git a/rwsdk/include/d3d8/rpmorph.rpe b/rwsdk/include/d3d8/rpmorph.rpe index 14b13076..47834a81 100644 --- a/rwsdk/include/d3d8/rpmorph.rpe +++ b/rwsdk/include/d3d8/rpmorph.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rppatch.h b/rwsdk/include/d3d8/rppatch.h index eb80663f..0b54fb1b 100644 --- a/rwsdk/include/d3d8/rppatch.h +++ b/rwsdk/include/d3d8/rppatch.h @@ -4,7 +4,7 @@ /** * \defgroup rppatch RpPatch - * \ingroup rpplugin + * \ingroup bezierpatches * * Bezier patch library * @@ -124,7 +124,7 @@ * \ingroup rppatch * \ref RpPatchMeshFlag * When creating a \ref RpPatchMesh, these flags can be OR'ed together to - * specify the format along with the \ref rpPATCHMESHTEXCOORDSETS (n) macro + * specify the format along with the \ref rpPATCHMESHTEXCOORDSETS(num) macro * to specify the number of texture coordinate sets required. * * \see RpPatchMeshCreate @@ -220,7 +220,7 @@ typedef struct RpPatchMesh RpPatchMesh; * The patch mesh should be unlocked with \ref RpPatchMeshUnlock before it is * added to an \ref RpAtomic with \ref RpPatchAtomicSetPatchMesh. * - * \see RpPatchMesDefinition + * \see RpPatchMeshDefinition */ struct RpPatchMesh { @@ -278,7 +278,7 @@ struct RpPatchLODRange /** * \ingroup rppatch - * \typedef RpPatchLODUserData + * \ref RpPatchLODUserData * typedef for the user data passed to the \ref RpPatchLODCallBack * function which calculates the atomics' LOD. * @@ -289,9 +289,14 @@ typedef void *RpPatchLODUserData; /** * \ingroup rppatch - * \typedef RpPatchLODCallBack + * \ref RpPatchLODCallBack * typedef for the patch atomic LOD calculation function. * + * \param atomic + * \param userData + * + * \return + * * \see RpPatchAtomicSetPatchLODCallBack * \see RpPatchAtomicGetPatchLODCallBack */ @@ -309,6 +314,13 @@ extern "C" /*---------------------------------------------------------------------------* *- Plugin functions -* *---------------------------------------------------------------------------*/ +extern void +RpPatchGeometrySetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + +extern void +RpPatchAtomicSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + + extern RwBool RpPatchPluginAttach(void); diff --git a/rwsdk/include/d3d8/rppatch.rpe b/rwsdk/include/d3d8/rppatch.rpe index 6d433990..85dca470 100644 --- a/rwsdk/include/d3d8/rppatch.rpe +++ b/rwsdk/include/d3d8/rppatch.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpprtstd.h b/rwsdk/include/d3d8/rpprtstd.h index ad1b87f7..ba0bf1d6 100644 --- a/rwsdk/include/d3d8/rpprtstd.h +++ b/rwsdk/include/d3d8/rpprtstd.h @@ -28,7 +28,7 @@ /** * \defgroup rpprtstd RpPrtStd - * \ingroup rpplugin + * \ingroup particles * * Particle Animation Plugin for RenderWare Graphics. */ @@ -52,7 +52,7 @@ -#define PRTSTD_RSRAND2(_seed) (((RwReal)((RwReal) (_seed) * PRTSTD_SRAND_IMAX) * \ +#define PRTSTD_2RSRAND2(_seed) (((RwReal)((RwReal) (_seed) * PRTSTD_SRAND_IMAX) * \ (RwReal)1.0)) /** @@ -84,6 +84,8 @@ enum RpPrtStdEmitterFlags rpPRTSTDEMITTERFLAGUPDATEPARTICLE = 0x00000020, /**< This indicated if the emitter's particles are updated. */ rpPRTSTDEMITTERFLAGRENDER = 0x00000040, /**< This indicates if the emitter is rendered. */ rpPRTSTDEMITTERFLAGRENDERPARTICLE = 0x00000080, /**< This indicates if the emitter's particles are rendered. */ + rpPRTSTDEMITTERFLAGNOBUFFERSWAP = 0x00000100, /**< Internal usage */ + rpPRTSTDEMITTERFLAGSTREAMREAD = 0x00000200, /**< Internal usage */ rpPRTSTDEMITTERFLAGFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; @@ -109,15 +111,12 @@ enum RpPrtStdParticleCallBackCode rpPRTSTDPARTICLECALLBACKRENDER, /**< Particle render callback */ rpPRTSTDPARTICLECALLBACKCREATE, /**< Particle create callback */ rpPRTSTDPARTICLECALLBACKDESTROY, /**< Particle destroy callback */ - rpPRTSTDPARTICLECALLBACKSTREAMREAD, /**< Particle stream input callback */ - rpPRTSTDPARTICLECALLBACKSTREAMWRITE, /**< Particle stream outout callback */ - rpPRTSTDPARTICLECALLBACKSTREAMGETSIZE, /**< Particle stream get size callback */ rpPRTSTDPARTICLECALLBACKFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; typedef enum RpPrtStdParticleCallBackCode RpPrtStdParticleCallBackCode; -#define rpPRTSTDEMITTERCALLBACKMAX 10 +#define rpPRTSTDEMITTERCALLBACKMAX 11 /** * \ingroup rpprtstd @@ -137,6 +136,7 @@ enum RpPrtStdEmitterCallBackCode rpPRTSTDEMITTERCALLBACKSTREAMREAD, /**< Emitter stream input callback */ rpPRTSTDEMITTERCALLBACKSTREAMWRITE, /**< Emitter stream output callback */ rpPRTSTDEMITTERCALLBACKSTREAMGETSIZE, /**< Emitter stream get size callback */ + rpPRTSTDEMITTERCALLBACKCLONE, /**< Emitter clone callback */ rpPRTSTDEMITTERCALLBACKFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; @@ -154,7 +154,7 @@ typedef struct RpPrtStdEmitter RWALIGN(RpPrtStdEmitter, rwMATRIXALIGNMENT); /** * \ingroup rpprtstd - * \typedef RpPrtStdEmitterCallBack + * \ref RpPrtStdEmitterCallBack * \ref RpPrtStdEmitterCallBack represents the function called for processing * a \ref RpPrtStdEmitter. There can several types of the functions, each performing a * specific task defined by \ref RpPrtStdEmitterCallBackCode. @@ -172,7 +172,6 @@ typedef RpPrtStdEmitter * typedef struct RpPrtStdParticleBatch RWALIGN(RpPrtStdParticleBatch, rwMATRIXALIGNMENT); /** * \ingroup rpprtstd - * \typedef RpPrtStdParticleCallBack * \ref RpPrtStdParticleCallBack represents the function called for processing * a \ref RpPrtStdParticleBatch. There can be several types of the functions, each * performing a specific task defined by \ref RpPrtStdParticleCallBackCode. @@ -189,7 +188,6 @@ typedef RpPrtStdParticleBatch * /** * \ingroup rpprtstd - * \typedef RpPrtStdEmitterCallBackArray * \ref RpPrtStdEmitterCallBackArray represents a set of callback functions for * processing a \ref RpPrtStdEmitter. All the functions are of the type \ref * RpPrtStdEmitterCallBack. @@ -201,7 +199,6 @@ typedef RpPrtStdEmitterCallBack /** * \ingroup rpprtstd - * \typedef RpPrtStdParticleCallBackArray * \ref RpPrtStdParticleCallBackArray represents a set of callback functions for * processing a \ref RpPrtStdParticleBatch. All the functions are of the type \ref * RpPrtStdParticleCallBack. @@ -221,7 +218,6 @@ typedef RpPrtStdParticleCallBack typedef struct RpPrtStdEmitterClass RpPrtStdEmitterClass; /** * \ingroup rpprtstd - * \typedef RpPrtStdEClassSetupCallBack * \ref RpPrtStdEClassSetupCallBack represents the function called for setting up an * emitter class's set of callback function. The callback function is called * after an emitter class is streamed in. @@ -237,7 +233,6 @@ typedef RpPrtStdEmitterClass * typedef struct RpPrtStdParticleClass RpPrtStdParticleClass; /** * \ingroup rpprtstd - * \typedef RpPrtStdPClassSetupCallBack * \ref RpPrtStdPClassSetupCallBack represents the function called for setting up an * emitter class's set of callback function. The callback function is called * after an emitter class is streamed in. @@ -273,6 +268,7 @@ struct RpPrtStdPropertyTable RpPrtStdPropertyTable *next; /**< Internal usage */ RwInt32 id; /**< Property table's id */ + RwInt32 refCount; /**< Reference count. Internal usage */ RwInt32 numProp; /**< Number of properties in the table */ RwInt32 maxProp; /**< Internal usage */ @@ -295,6 +291,7 @@ struct RpPrtStdEmitterClass RpPrtStdEmitterClass *next; /**< Internal usage */ RwInt32 id; /**< Emitter class's id */ + RwInt32 refCount; /**< Reference count. Internal usage */ RwInt32 objSize; /**< Size of the emitter */ RpPrtStdPropertyTable *propTab; /**< Reference to a table of emitter properties */ @@ -316,6 +313,7 @@ struct RpPrtStdParticleClass RpPrtStdParticleClass *next; /**< Internal usage */ RwInt32 id; /**< Particle class's id */ + RwInt32 refCount; /**< Reference count. Internal usage */ RwInt32 objSize; /**< Size of a particle */ RpPrtStdPropertyTable *propTab; /**< Reference to a table of particle properties */ @@ -403,7 +401,6 @@ struct RpPrtStdEmitter #define rpPRTSTDPROPERTYCODEEMITTERSTANDARD 1 #define rpPRTSTDPROPERTYCODEEMITTERPRTCOLOR 2 #define rpPRTSTDPROPERTYCODEEMITTERPRTTEXCOORDS 3 -#define rpPRTSTDPROPERTYCODEEMITTERPRTANIMFRAME 4 #define rpPRTSTDPROPERTYCODEEMITTERPRTSIZE 5 #define rpPRTSTDPROPERTYCODEEMITTERPTANK 6 #define rpPRTSTDPROPERTYCODEEMITTERPRTVELOCITY 7 @@ -414,7 +411,6 @@ struct RpPrtStdEmitter #define rpPRTSTDEMITTERDATAFLAGSTANDARD 0x00000001 #define rpPRTSTDEMITTERDATAFLAGPRTCOLOR 0x00000002 #define rpPRTSTDEMITTERDATAFLAGPRTTEXCOORDS 0x00000004 -#define rpPRTSTDEMITTERDATAFLAGPRTANIMFRAME 0x00000008 #define rpPRTSTDEMITTERDATAFLAGPRTSIZE 0x00000010 #define rpPRTSTDEMITTERDATAFLAGPTANK 0x00000020 #define rpPRTSTDEMITTERDATAFLAGPRTMATRIX 0x00000040 @@ -436,7 +432,7 @@ typedef struct RpPrtStdEmitterStandard RpPrtStdEmitterStandard; * particles. Once an emitter has reached its maximum number of particles, no further particles are * emitted until some of the existing particles have died. * - * Most properties have a bias value to vary the property value. This uses the seed field + * Most properties have a bias value to vary the property's value. This uses the seed field * to give a degreee of randomness. */ struct RpPrtStdEmitterStandard @@ -522,15 +518,6 @@ struct RpPrtStdEmitterPrtTexCoords prtEndUV1Bias; /**< Particle end bottom right texcoords bias */ }; -typedef struct RpPrtStdEmitterPrtAnimFrame RpPrtStdEmitterPrtAnimFrame; - -struct RpPrtStdEmitterPrtAnimFrame -{ - RwInt32 prtNumFrames; - - RwTexCoords *prtAnimFrameTexCoords; -}; - typedef struct RpPrtStdEmitterPrtSize RpPrtStdEmitterPrtSize; /** @@ -550,18 +537,47 @@ struct RpPrtStdEmitterPrtSize prtEndSizeBias; /**< Particle end size bias */ }; + +/** + * \ingroup rpprtstd + * A set of flag settings for use in the \ref RpPrtStdEmitterPrtMatrix flag + */ +enum RpPrtStdEmitterPrtMatrixFlags +{ + rpPRTSTDEMITTERPRTMTXFLAGSCNSMTX = 0x00000001, /**< Apply the prtCnsMtx matrix to + * each particle if set */ + RPPRTSTDEMITTERPRTMTXFLAGSFORCEENUMSIZEINT = RWFORCEENUMSIZEINT +}; + +typedef enum RpPrtStdEmitterPrtMatrixFlags RpPrtStdEmitterPrtMatrixFlags; + typedef struct RpPrtStdEmitterPrtMatrix RWALIGN(RpPrtStdEmitterPrtMatrix, rwMATRIXALIGNMENT); +/** + * \ingroup rpprtstd + * \struct RpPrtStdEmitterPrtMatrix + * + * An optional structure to construct a matrix for each particle during emissions. A particle + * can be represented as a single matrix. This gives the particles an orientation rather than + * just a simple position. + * + * This allows transformation to be applied to the particles, such as rotation. If + * \ref rpPRTSTDEMITTERPRTMTXFLAGSCNSMTX is set in the flag, then the prtCnsMatrix is applied to each + * particle during particle update. + * + * If this structure is not present, then it assumes the particles will have just a position + * property. + */ struct RpPrtStdEmitterPrtMatrix { - RwMatrix prtCnsMtx; + RwMatrix prtCnsMtx; /**< Transformation matrix to be applied to each particle */ - RwV3d prtPosMtxAt, - prtPosMtxAtBias; - RwV3d prtPosMtxUp, - prtPosMtxUpBias; + RwV3d prtPosMtxAt, /**< Particle initial look at vector */ + prtPosMtxAtBias; /**< Particle initial look at vector bias */ + RwV3d prtPosMtxUp, /**< Particle initial up vector. */ + prtPosMtxUpBias; /**< Particle initial up vector bias */ - RwInt32 flags; + RwInt32 flags; /**< Particle matrix flag. See \ref RpPrtStdEmitterPrtMatrixFlags */ }; /************************************************************************ @@ -584,18 +600,42 @@ enum RpPrtStdPTankPropertyCode typedef enum RpPrtStdPTankPropertyCode RpPrtStdPTankPropertyCode; typedef struct RpPrtStdEmitterPTank RpPrtStdEmitterPTank; + +/** + * \ingroup rpprtstd + * \struct RpPrtStdEmitterPTank + * + * A structure for storing the data required to create a RpPTank for use + * with the emitter. The structure allows the user to create a RpPTank + * manually. + */ struct RpPrtStdEmitterPTank { - RwUInt32 dataFlags, - platFlags, - numPrt, - maxPrt, - updateFlags, - emitFlags; - RpAtomic *pTank; - RwChar **dataInPtrs, - **dataOutPtrs; - RwInt32 *dataStride; + RwUInt32 dataFlags, /**< Data flag used in RpPTank creation. See + * \ref RpPTankAtomicCreate */ + platFlags, /**< Platform flag used in RpPTank creation. See + * \ref RpPTankAtomicCreate */ + numPrt, /**< An integer representing the current number of active + * particles */ + maxPrt, /**< An integer representing the maxiumum number of particles + * stored in the RpPTank */ + updateFlags, /**< A flag representing the properties to be updated by + * the particle emiiter during update. A user may select to + * update some properties manually by unsetting the relevant + * bits in the flag. + * The flag settings are the same as \ref RpPTankDataFlags */ + emitFlags; /**< A flag representing the properties to be initialised + * by the particle emitter during particles emission. A user + * may select to initialise some properties manually by + * unsetting the relevant bits in the flag. + * The flag settings are the same as \ref RpPTankDataFlags */ + RpAtomic *pTank; /**< Pointer to the RpPTank */ + RwChar **dataInPtrs, /**< Internal usage */ + **dataOutPtrs; /**< Internal usage */ + RwInt32 *dataStride; /**< Internal usage */ + RwUInt32 strSrcBlend; /**< Internal usage */ + RwUInt32 strDstBlend; /**< Internal usage */ + RwBool strVtxABlend; /**< Internal usage */ }; /************************************************************************ @@ -608,7 +648,6 @@ struct RpPrtStdEmitterPTank #define rpPRTSTDPROPERTYCODEPARTICLEPOSITION 1 #define rpPRTSTDPROPERTYCODEPARTICLECOLOR 2 #define rpPRTSTDPROPERTYCODEPARTICLETEXCOORDS 3 -#define rpPRTSTDPROPERTYCODEPARTICLEANIMFRAME 4 #define rpPRTSTDPROPERTYCODEPARTICLESIZE 5 #define rpPRTSTDPROPERTYCODEPARTICLEVELOCITY 6 #define rpPRTSTDPROPERTYCODEPARTICLEMATRIX 7 @@ -619,7 +658,6 @@ struct RpPrtStdEmitterPTank #define rpPRTSTDPARTICLEDATAFLAGPOSITION 0x00000002 #define rpPRTSTDPARTICLEDATAFLAGCOLOR 0x00000004 #define rpPRTSTDPARTICLEDATAFLAGTEXCOORDS 0x00000008 -#define rpPRTSTDPARTICLEDATAFLAGANIMFRAME 0x00000010 #define rpPRTSTDPARTICLEDATAFLAGSIZE 0x00000020 #define rpPRTSTDPARTICLEDATAFLAGVELOCITY 0x00000040 #define rpPRTSTDPARTICLEDATAFLAGMATRIX 0x00000080 @@ -675,15 +713,6 @@ struct RpPrtStdParticleTexCoords deltaUV1; /**< Particle's bottom right texcoords rate of change */ }; -typedef struct RpPrtStdParticleAnimFrame RpPrtStdParticleAnimFrame; - -struct RpPrtStdParticleAnimFrame -{ - RwInt32 frame; - - RwReal delta; -}; - typedef struct RpPrtStdParticleSize RpPrtStdParticleSize; /** @@ -714,10 +743,13 @@ extern "C" /************************************************************************/ extern RwBool -RpParticleStandardPluginAttach( void ); +RpPrtStdPluginAttach( void ); /************************************************************************/ +extern RwBool +RpAtomicIsParticleEmitter(RpAtomic *atomic); + extern RpAtomic * RpPrtStdAtomicCreate(RpPrtStdEmitterClass *eClass, void *data); @@ -749,6 +781,9 @@ RpPrtStdEmitterCreate(RpPrtStdEmitterClass *eClass); extern RwBool RpPrtStdEmitterDestroy(RpPrtStdEmitter *emt); +extern RpPrtStdEmitter * +RpPrtStdEmitterClone(RpPrtStdEmitter *emt); + extern RpPrtStdEmitter * RpPrtStdEmitterForAllParticleBatch(RpPrtStdEmitter *emt, RpPrtStdParticleCallBack callback, @@ -835,7 +870,6 @@ RpPrtStdPropTabStreamWrite(RpPrtStdPropertyTable *eClass, extern RwInt32 RpPrtStdPropTabStreamGetSize(RpPrtStdPropertyTable *eClass); - /************************************************************************/ extern RwBool @@ -941,6 +975,11 @@ RpPrtStdGlobalDataStreamWrite(RwStream *stream); extern RwInt32 RpPrtStdGlobalDataStreamGetSize( void ); +extern void +RpPrtStdGlobalDataSetStreamEmbedded( RwBool embedded ); + +extern RwBool +RpPrtStdGlobalDataGetStreamEmbedded( void ); /************************************************************************/ @@ -963,10 +1002,18 @@ extern RpPrtStdEmitter * RpPrtStdEmitterStdEmitCB(RpAtomic *atomic, RpPrtStdEmitter *emt, void *data); +extern RpPrtStdEmitter * +RpPrtStdEmitterStdCloneCB(RpAtomic *atomic, + RpPrtStdEmitter *emt, void *data); + extern RpPrtStdEmitter * RpPrtStdEmitterStdCreateCB(RpAtomic *atomic, RpPrtStdEmitter *emt, void *data); +extern RpPrtStdEmitter * +RpPrtStdEmitterStdDestroyCB(RpAtomic *atomic, + RpPrtStdEmitter *emt, void *data); + extern RpPrtStdEmitter * RpPrtStdEmitterStdBeginUpdateCB(RpAtomic *atomic, RpPrtStdEmitter *emt, void *data); diff --git a/rwsdk/include/d3d8/rpprtstd.rpe b/rwsdk/include/d3d8/rpprtstd.rpe index df860d45..d628c6c0 100644 --- a/rwsdk/include/d3d8/rpprtstd.rpe +++ b/rwsdk/include/d3d8/rpprtstd.rpe @@ -160,480 +160,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum e_rwdb_CriterionParticleStandard +enum e_rwdb_CriterionPrtStandard { - e_rwdb_CriterionParticleStandardLAST = RWFORCEENUMSIZEINT + e_rwdb_CriterionPrtStandardLAST = RWFORCEENUMSIZEINT }; -typedef enum e_rwdb_CriterionParticleStandard e_rwdb_CriterionParticleStandard; +typedef enum e_rwdb_CriterionPrtStandard e_rwdb_CriterionPrtStandard; diff --git a/rwsdk/include/d3d8/rpptank.h b/rwsdk/include/d3d8/rpptank.h index 20931f21..d4c1116d 100644 --- a/rwsdk/include/d3d8/rpptank.h +++ b/rwsdk/include/d3d8/rpptank.h @@ -13,12 +13,13 @@ /** * \defgroup rpptank RpPTank - * \ingroup rpplugin + * \ingroup particles * * PTank Plugin for RenderWare. */ /*--- Include files ---*/ + #include #include "rwcore.h" @@ -139,7 +140,7 @@ enum RpPTankInstanceFlags rpPTANKIFLAGCENTER = ((int)0x01000000), /**
publicData.cColor = *col_;\ if( RpGeometryGetMaterial(RpAtomicGetGeometry(atm_),0) )\ {\ - RpMaterialSetColor(\ + (void)RpMaterialSetColor(\ RpGeometryGetMaterial(RpAtomicGetGeometry(atm_),0),\ &RPATOMICPTANKPLUGINDATA(atm_)->publicData.cColor);\ }\ @@ -759,6 +761,14 @@ extern RpAtomic * RpPTankAtomicUnlock(RpAtomic *atomic); +/* + * Stealth functions ********************************************************* + */ +RpAtomic* +_rpPTankAtomicCreateCustom(RwInt32 maxParticleNum, + RwUInt32 dataFlags, RwUInt32 platFlags, + RpPTankCallBacks *callbacks); + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -767,6 +777,41 @@ RpPTankAtomicUnlock(RpAtomic *atomic); /*---- start: c:/daily/rwsdk/plugin/ptank/d3d8/ptankplatform.h----*/ +/** + * \defgroup rpptankd3d8 D3D8 + * \ingroup rpptank + * + * D3D8 specific documentation. + */ + +/** + * \ingroup rpptankd3d8 + * \par D3D8 specific data flags + * + *
    + *
  • rpPTANKD3D8FLAGSUSEPOINTSPRITES selects the D3D8 optimized pipeline. At the + * moment, this pipeline use point sprites when the hardware supports them, + * which don't allow use of all the PTank flags. Only the following flags are + * supported when using the D3D8 optimized pipes: + * + *
      + *
    • rpPTANKDFLAGPOSITION + *
    • rpPTANKDFLAGNORMAL + *
    • rpPTANKDFLAGSIZE (if the hardware supports the D3DFVF_PSIZE vertex format flag) + *
    • rpPTANKDFLAGCOLOR + *
    • rpPTANKDFLAGUSECENTER + *
    • rpPTANKDFLAGARRAY + *
    • rpPTANKDFLAGSTRUCTURE + *
    + * + * The texture coordinates are generated by the hardware and can't be specified. + *
+ * + * If the hardware does not support point sprites, the default pipeline is used + * instead. + * + */ + enum RpPTankD3D8Flags { rpPTANKD3D8FLAGSUSEPOINTSPRITES = 0x00000001, @@ -774,6 +819,8 @@ enum RpPTankD3D8Flags rpPTANKD3D8FLAGFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; +typedef enum RpPTankD3D8Flags RpPTankD3D8Flags; + /*---- end: c:/daily/rwsdk/plugin/ptank/d3d8/ptankplatform.h----*/ #endif /* RPPTANK_H */ diff --git a/rwsdk/include/d3d8/rpptank.rpe b/rwsdk/include/d3d8/rpptank.rpe index 485b5dd8..2a9b45d3 100644 --- a/rwsdk/include/d3d8/rpptank.rpe +++ b/rwsdk/include/d3d8/rpptank.rpe @@ -143,472 +143,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rppvs.h b/rwsdk/include/d3d8/rppvs.h index 29fc2343..08738933 100644 --- a/rwsdk/include/d3d8/rppvs.h +++ b/rwsdk/include/d3d8/rppvs.h @@ -32,7 +32,7 @@ /** * \defgroup rppvs RpPVS - * \ingroup rpplugin + * \ingroup pvs * * Geometric Potentially Visible Set Plugin for RenderWare Graphics. */ @@ -122,11 +122,14 @@ typedef RpWorldSector *(*RpPVSCallBack) (RpWorldSector * worldSector, #define RpPVSCallback RpPVSCallBack typedef struct _RpPVSCallBack _RpPVSCallBack; + +#if (!defined(DOXYGEN)) struct _RpPVSCallBack { RpPVSCallBack callback; void *data; }; +#endif /* (!defined(DOXYGEN)) */ enum _rpPVSPartitionId { @@ -145,6 +148,7 @@ typedef struct _rpPVSPolyList *_rpPVSPolyListPtr; typedef struct _rpPVSPoly _rpPVSPoly; typedef struct _rpPVSPoly *_rpPVSPolyPtr; +#if (!defined(DOXYGEN)) typedef struct _rpPVSPlaneEq _rpPVSPlaneEq; struct _rpPVSPlaneEq { @@ -158,12 +162,13 @@ struct _rpPVSPlaneEq _rpPVSPartitionId lastresult; /* temp: stores result of last polygon wrt this plane */ }; -typedef struct +typedef struct RwV3i RwV3i; +struct RwV3i { RwInt32 x; RwInt32 y; RwInt32 z; -}RwV3i; +}; typedef struct _rpPVSPolyRecord _rpPVSPolyRecord; struct _rpPVSPolyRecord @@ -205,47 +210,45 @@ struct _rpPVSPolyList }; typedef struct RpPVS RpPVS; + struct RpPVS { - RwInt32 sectorID; /* Id of the sector */ - RwInt32 vismaplength; /* Length of vismap */ - RwInt32 sampleKey; /* Currently unused, for future use */ + RwInt32 sectorID; + RwInt32 vismaplength; + RwInt32 sampleKey; RpPVSVisMap *vismap; - _rpPVSPolyListPtr sectailpoly; /* Pointer to last polygon in polygons list that is in this sector */ + _rpPVSPolyListPtr sectailpoly; + _rpPVSPartitionId potential; - _rpPVSPartitionId potential; /* temp: is sector in out or split from current shadow volume - for heirarchical clip */ RwUInt32 numpols; - RwBBox sbox; /* Bounding box of the sector */ - RwBBox gbox; /* Bounding box of the geometry of the sector */ - RwReal diagonal; /* Diagonal size of bounding box of the sector */ - RwV3d centre; /* Centre of the sector */ - RwInt32 axessig[3]; /* sampling significance of the axes of the gbox */ + RwBBox sbox; + RwBBox gbox; + RwReal diagonal; + RwV3d centre; + RwInt32 axessig[3]; }; typedef struct RpPVSCache RpPVSCache; struct RpPVSCache { - RwBool processed; /* flag to indicate exisiting PVS data for the world */ - RwBool formatted; /* flag to indicate exisiting intermediate polygonal data for PVS generation */ + RwBool processed; + RwBool formatted; + RwInt32 NumWorldSectors; - /* stats collection */ RwInt32 ptotal; RwInt32 paccept; - /* pipeline hooking */ RwBool hooked; - /* used during vismap allocation */ RwUInt32 nextID; RwInt32 viscount; - /* Used during construction */ RpPVSProgressCallBack progressCallBack; - _rpPVSPolyListPtr polygons; /* A copy of the input data set of all world polygons */ + _rpPVSPolyListPtr polygons; RpWorldSectorCallBackRender renderCallBack; }; @@ -255,23 +258,23 @@ struct RpPVSGlobalVars { RpWorld *World; - RwInt32 worldOffset; /* Offset into global data */ - RwInt32 sectorOffset; /* Offset into global data */ + RwInt32 worldOffset; + RwInt32 sectorOffset; - RwBool collis; /* Collision detection */ - RwBool bfc; /* Backface culling */ + RwBool collis; + RwBool bfc; - RwInt32 NumWorldSectors; RwInt32 progress_count; RwReal diagonal; RwReal gran; - RwInt32 InSector; /* Current sector id */ - RwV3d ViewPos; /* Current view pos */ - RpPVS *CurrPVS; /* Current PVS sector */ + RwInt32 InSector; + RwV3d ViewPos; + RpPVS *CurrPVS; }; +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** diff --git a/rwsdk/include/d3d8/rppvs.rpe b/rwsdk/include/d3d8/rppvs.rpe index dc060cff..62c983b0 100644 --- a/rwsdk/include/d3d8/rppvs.rpe +++ b/rwsdk/include/d3d8/rppvs.rpe @@ -140,472 +140,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rprandom.h b/rwsdk/include/d3d8/rprandom.h index 8690c69a..aebbfed9 100644 --- a/rwsdk/include/d3d8/rprandom.h +++ b/rwsdk/include/d3d8/rprandom.h @@ -28,7 +28,7 @@ /** * \defgroup rprandom RpRandom - * \ingroup rpplugin + * \ingroup mathtools * * Random Number Generation Plugin for RenderWare Graphics. */ diff --git a/rwsdk/include/d3d8/rprandom.rpe b/rwsdk/include/d3d8/rprandom.rpe index 8e267eee..d3fe964b 100644 --- a/rwsdk/include/d3d8/rprandom.rpe +++ b/rwsdk/include/d3d8/rprandom.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpskin.h b/rwsdk/include/d3d8/rpskin.h index df446c1b..8a6ea204 100644 --- a/rwsdk/include/d3d8/rpskin.h +++ b/rwsdk/include/d3d8/rpskin.h @@ -4,7 +4,7 @@ /** * \defgroup rpskin RpSkin - * \ingroup rpplugin + * \ingroup skinning * * Skin Plugin for RenderWare Graphics. */ @@ -48,7 +48,7 @@ struct RwMatrixWeights /** * \ingroup rpskin - * \typedef RpSkin + * \struct RpSkin * * Skin object. This should be considered an opaque type. * Use the RpSkin API functions to access. @@ -69,6 +69,9 @@ extern "C" /*---------------------------------------------------------------------------* *- Plugin functions -* *---------------------------------------------------------------------------*/ +extern void RpSkinSetFreeListCreateParams( + RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwBool RpSkinPluginAttach(void); @@ -114,6 +117,9 @@ RpSkinGetVertexBoneIndices( RpSkin *skin ); extern const RwMatrix * RpSkinGetSkinToBoneMatrices( RpSkin *skin ); +extern RwBool +RpSkinIsSplit( RpSkin *skin ); + /*---------------------------------------------------------------------------* *- Skin pipeline -* *---------------------------------------------------------------------------*/ @@ -131,7 +137,6 @@ enum RpSkinType rpSKINTYPEGENERIC = 1, /** -#include - -#include "rpstereo.rpe" /* automatically generated header file */ - -/*--- Global Structures ---*/ - -/* Supported Stereo Modes */ - -/** - * \ingroup rpstereo - * \ref RpStereoCameraMode - * Stereo camera mode enumeration. - */ -enum RpStereoCameraMode -{ - rpNASTEREOMODE = 0, - rpSTEREOMONO, /**< Render as Mono camera - single - * image - */ - rpSTEREOLEFTRIGHT, /**< Vertical split screen. Left eye - * image on left of screen. Right eye - * image on right of screen. - */ - rpSTEREORIGHTLEFT, /**< Vertical split screen. Right eye - * image on left of screen. Left eye image - * on right of screen. - */ - - rpSTEREOROTATE90, /**< As for rpSTEREOLEFTRIGHT - with - * the images rotated inwards by 90 degrees - */ - rpSTEREOINTERLACEDLEFTRIGHT, /**< Left and right eye images on - * alternate scanlines. The left eye image - * on the topmost line of the display. - */ - - rpSTEREOINTERLACEDRIGHTLEFT, /**< Left and right eye images on - * alternate scanlines. The right eye - * image is on the topmost line of the - * display. - */ - rpSTEREOLASTMODE, - rpSTEREOCAMERAMODEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT -}; - -/* - * typedef for stereo camera mode enumeration. - */ -typedef enum RpStereoCameraMode RpStereoCameraMode; - -/*--- Constants ---*/ - -/* These may be used to quickly adapt an existing application to a - * stereo version. - */ - -#ifdef RPSTEREO_OVERLOAD -#define RwCameraBeginUpdate RpStereoCameraBeginUpdate -#define RwCameraEndUpdate RpStereoCameraEndUpdate -#undef RpWorldRender -#define RpWorldRender RpStereoWorldRender -#undef RpClumpRender -#define RpClumpRender RpStereoClumpRender -#undef RpAtomicRender -#define RpAtomicRender RpStereoAtomicRender -#undef RpWorldSectorRender -#define RpWorldSectorRender RpStereoWorldSectorRender -#endif - -/*--- Plugin API Functions ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -RwBool RpStereoPluginAttach(void); - -RpWorld *RpStereoWorldRender(RpWorld *world); -RpClump *RpStereoClumpRender(RpClump *clump); -RpAtomic *RpStereoAtomicRender(RpAtomic *atomic); -RpWorldSector *RpStereoWorldSectorRender(RpWorldSector *sector); - -RwCamera *RpStereoCameraBeginUpdate(RwCamera *camera); -RwCamera *RpStereoCameraEndUpdate(RwCamera *stereoCam); - -RwReal RpStereoCameraGetSeparation(RwCamera *stereoCam); -RwReal RpStereoCameraGetFocal(RwCamera *stereoCam); -RpStereoCameraMode RpStereoCameraGetMode(RwCamera *stereoCam); - -RwCamera *RpStereoCameraSetSeparation(RwCamera *stereoCam, RwReal dist); -RwCamera *RpStereoCameraSetFocal(RwCamera *stereoCam, RwReal focal); -RwCamera *RpStereoCameraSetMode(RwCamera *stereoCam, RpStereoCameraMode newMode); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* RPSTEREO_H */ - diff --git a/rwsdk/include/d3d8/rpstereo.rpe b/rwsdk/include/d3d8/rpstereo.rpe deleted file mode 100644 index b89dde2e..00000000 --- a/rwsdk/include/d3d8/rpstereo.rpe +++ /dev/null @@ -1,641 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum e_rwdb_CriterionStereo -{ - - -E_RP_STEREO_INVMODE, - -E_RP_STEREO_INVFOCAL, - - e_rwdb_CriterionStereoLAST = RWFORCEENUMSIZEINT -}; - -typedef enum e_rwdb_CriterionStereo e_rwdb_CriterionStereo; - - diff --git a/rwsdk/include/d3d8/rpusrdat.h b/rwsdk/include/d3d8/rpusrdat.h index 3665e064..92a56e31 100644 --- a/rwsdk/include/d3d8/rpusrdat.h +++ b/rwsdk/include/d3d8/rpusrdat.h @@ -3,7 +3,7 @@ /** * \defgroup rpuserdata RpUserData - * \ingroup rpplugin + * \ingroup scenemanagement * * User Data Plugin for RenderWare Graphics. */ diff --git a/rwsdk/include/d3d8/rpusrdat.rpe b/rwsdk/include/d3d8/rpusrdat.rpe index 31c37fd1..f5879a00 100644 --- a/rwsdk/include/d3d8/rpusrdat.rpe +++ b/rwsdk/include/d3d8/rpusrdat.rpe @@ -139,472 +139,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rpworld.h b/rwsdk/include/d3d8/rpworld.h index 21fdc31b..0d0489ce 100644 --- a/rwsdk/include/d3d8/rpworld.h +++ b/rwsdk/include/d3d8/rpworld.h @@ -22,7 +22,7 @@ /************************************************************************* * * Filename: - * Automatically Generated on: Wed Jul 10 10:45:01 2002 + * Automatically Generated on: Thu Jan 23 11:06:24 2003 * ************************************************************************/ @@ -75,136 +75,33 @@ extern RxNodeDefinition *RxNodeDefinitionGetD3D8AtomicAllInOne(void); extern "C" { #endif /* __cplusplus */ + +extern void RwD3D8VertexBufferManagerChangeDefaultSize(RwUInt32 defaultSize); + +extern RwBool _rxD3D8VertexBufferManagerCreate(RwUInt32 fvf, + RwUInt32 size, + void **vertexBuffer, + RwUInt32 *baseIndex); + +extern void _rxD3D8VertexBufferManagerDestroy(RwUInt32 fvf, + RwUInt32 size, + void *vertexBuffer, + RwUInt32 baseIndex); + +extern RwBool _rxD3D8VertexBufferManagerCreateNoFVF(RwUInt32 stride, + RwUInt32 size, + void **vertexBuffer, + RwUInt32 *baseIndex); + +extern void _rxD3D8VertexBufferManagerDestroyNoFVF(RwUInt32 stride, + RwUInt32 size, + void *vertexBuffer, + RwUInt32 baseIndex); + #ifdef __cplusplus } #endif /* __cplusplus */ -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeWorldSectorInstance.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetWorldSectorInstance(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeWorldSectorEnumerateLights.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetWorldSectorEnumerateLights(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodePreLight.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetPreLight(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodePostLight.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetPostLight(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeMaterialScatter.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetMaterialScatter(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeLight.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetLight(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeFastPathSplitter.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetFastPathSplitter(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeAtomicInstance.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetAtomicInstance(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/nodeAtomicEnumerateLights.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetAtomicEnumerateLights(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - /*--- Automatically derived from: c:/daily/rwsdk/world/bamateri.h ---*/ /* @@ -222,15 +119,17 @@ extern RxNodeDefinition *RxNodeDefinitionGetAtomicEnumerateLights(void); typedef struct RpMaterialChunkInfo RpMaterialChunkInfo; typedef struct RpMaterialChunkInfo _rpMaterial; +#if (!defined(DOXYGEN)) struct RpMaterialChunkInfo { - RwInt32 flags; /**< Material flags - unused currently - - for future expansion */ - RwRGBA color; /**< Colour of material. */ - RwInt32 unused; /**< Not used */ - RwBool textured; /**< Are we textured? */ - RwSurfaceProperties surfaceProps; /**< Surface properties */ + RwInt32 flags; /* Material flags - unused currently - + * for future expansion */ + RwRGBA color; /* Color of material. */ + RwInt32 unused; /* Not used */ + RwBool textured; /* Are we textured? */ + RwSurfaceProperties surfaceProps;/* Surface properties */ }; +#endif /* (!defined(DOXYGEN)) */ #if (!defined(RwMaterialAssign)) #define RwMaterialAssign(_target, _source) \ @@ -238,8 +137,8 @@ struct RpMaterialChunkInfo #endif /* (!defined(RwMaterialAssign)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpMaterial + * \ingroup rpmaterial + * \struct RpMaterial * Material object. This should be * considered an opaque type. Use the RpMaterial API functions to access. */ @@ -258,9 +157,8 @@ struct RpMaterial #endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpMaterialCallBack - \ref RpMaterialCallBack + * \ingroup rpmaterial + * \ref RpMaterialCallBack * represents the function called from \ref RpGeometryForAllMaterials and * \ref RpWorldForAllMaterials for all materials referenced by polygons in a * given geometry. This function should return a pointer to the current @@ -268,7 +166,7 @@ struct RpMaterial * further callbacks on the materials. * * \param material Pointer to the current material - * \param data Pointer to developer-defined data structure. + * \param data Pointer to developer-defined data structure. * * \return Pointer to the current material. */ @@ -346,6 +244,9 @@ extern "C" #endif /* __cplusplus */ +extern void RpMaterialSetFreeListCreateParams( RwInt32 blockSize, + RwInt32 numBlocksToPrealloc ); + /* Creating, destroying and referencing materials */ extern RpMaterial *RpMaterialCreate(void); extern RwBool RpMaterialDestroy(RpMaterial *material); @@ -388,6 +289,8 @@ extern RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, extern RwInt32 RpMaterialSetStreamAlwaysCallBack( RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +extern RwInt32 RpMaterialSetStreamRightsCallBack(RwUInt32 pluginID, + RwPluginDataChunkRightsCallBack rightsCB); extern RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID); extern RwBool RpMaterialValidatePlugins(const RpMaterial *material); @@ -414,12 +317,15 @@ _rpMaterialChunkInfoRead(RwStream *stream, */ typedef struct RpMaterialList RpMaterialList; + +#if (!defined(DOXYGEN)) struct RpMaterialList { RpMaterial **materials; RwInt32 numMaterials; RwInt32 space; }; +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** Function prototypes @@ -531,16 +437,14 @@ extern RwModuleInfo meshModule; Global types */ -/** - * \ingroup rpworlddatatypes - * \typedef RpMeshHeader +/* * typedef for header structure listing all meshes * constituting a single RpGeometry or RpWorldSector */ typedef struct RpMeshHeader RpMeshHeader; /** - * \ingroup rpworlddatatypes + * \ingroup rpmesh * \ref RpMeshHeaderFlags * represents the different types of mesh. * \see RpMeshHeader @@ -549,18 +453,18 @@ enum RpMeshHeaderFlags { /* NOTE: trilists are denoted by absence of any other * primtype flags, so be careful that you test: - * (triListFlag == flags&triListFlag) + * (triListFlag == (flags&triListFlag)) * or: - * (0 == flags&rpMESHHEADERPRIMMASK) + * (0 == (flags&rpMESHHEADERPRIMMASK)) * and not: * (flags&triListFlag) */ rpMESHHEADERTRISTRIP = 0x0001, /**< Render as tristrips */ - rpMESHHEADERTRIFAN = 0x0002, /**< On PS2 these will be converted to trilists */ + rpMESHHEADERTRIFAN = 0x0002, /**< On PlayStation 2 these will be converted to trilists */ rpMESHHEADERLINELIST = 0x0004, /**< Render as linelists */ - rpMESHHEADERPOLYLINE = 0x0008, /**< On PS2 these will be converted to linelists */ + rpMESHHEADERPOLYLINE = 0x0008, /**< On PlayStation 2 these will be converted to linelists */ rpMESHHEADERPOINTLIST = 0x0010, /**< Pointlists are supported only if rendered by - * custom pipelines; there is no default RenderWare + * custom pipelines; there is no default RenderWare * way to render pointlists. */ rpMESHHEADERPRIMMASK = 0x00FF, /**< All bits reserved for specifying primitive type */ @@ -576,6 +480,8 @@ enum RpMeshHeaderFlags typedef enum RpMeshHeaderFlags RpMeshHeaderFlags; typedef struct rpMeshGlobals rpMeshGlobals; + +#if (!defined(DOXYGEN)) struct rpMeshGlobals { RwInt16 nextSerialNum; @@ -583,11 +489,12 @@ struct rpMeshGlobals RwUInt8 meshFlagsToPrimType[rpMESHHEADERPRIMTYPEOR]; RwUInt8 primTypeToMeshFlags[rwPRIMTYPEOR]; }; +#endif /* (!defined(DOXYGEN)) */ typedef struct RpBuildMeshTriangle RpBuildMeshTriangle; /** - * \ingroup rpworlddatatypes + * \ingroup rpmesh * \struct RpBuildMeshTriangle * This type represents an array of indices into * the object vertex array. Used during the construction @@ -613,7 +520,7 @@ struct RpBuildMeshTriangle typedef struct RpBuildMesh RpBuildMesh; /** - * \ingroup rpworlddatatypes + * \ingroup rpmesh * \struct RpBuildMesh * This type represents a mesh ready for tri stripping. * @@ -640,7 +547,7 @@ struct RpBuildMesh typedef struct RpMesh RpMesh; /** - * \ingroup rpworlddatatypes + * \ingroup rpmesh * \struct RpMesh * This type represents a single polygon mesh. * A mesh is defined as a collection of triangles derived from an RpGeometry @@ -659,7 +566,7 @@ struct RpMesh }; /** - * \ingroup rpworlddatatypes + * \ingroup rpmesh * \struct RpMeshHeader * Header for all meshes that constitute a single RpGeometry or RpWorldSector */ @@ -679,9 +586,8 @@ struct RpMeshHeader }; /** - * \ingroup rpworlddatatypes - * \typedef RpMeshCallBack - * \ref RpMeshCallBack is the callback + * \ingroup rpmesh + * \ref RpMeshCallBack is the callback * function supplied to \ref RpGeometryForAllMeshes and * \ref RpWorldSectorForAllMeshes for all meshes in a given geometry. * @@ -689,14 +595,13 @@ struct RpMeshHeader * success. The callback may return NULL to terminate further callbacks * on the meshes. * - * \param mesh Pointer to the current mesh, supplied by - * iterator. - * \param meshHeader Pointer to the meshes header - * \param data Pointer to developer-defined data structure. + * \param mesh Pointer to the current mesh, supplied by + * iterator. + * \param meshHeader Pointer to the meshes header + * \param data Pointer to developer-defined data structure. * - * \return - * Returns a pointer to the current mesh if successful or NULL if an error - * occurred. + * \return Returns a pointer to the current mesh if successful or NULL + * if an error occurred. */ typedef RpMesh *(*RpMeshCallBack) (RpMesh * mesh, RpMeshHeader * meshHeader, @@ -823,29 +728,29 @@ extern RpMeshHeader * _rpMeshHeaderCreate(RwUInt32 size); naTmp[1] = RwRealToFixed((v).y); \ naTmp[2] = RwRealToFixed((v).z); \ \ - if (naTmp[0] >= RwFixedCast(1)) \ + if (naTmp[0] >= RwIntToFixed(1)) \ { \ - naTmp[0] = RwFixedCast(1)-1; \ + naTmp[0] = RwIntToFixed(1)-1; \ } \ - if (naTmp[0] <= RwFixedCast(-1)) \ + if (naTmp[0] <= RwIntToFixed(-1)) \ { \ - naTmp[0] = RwFixedCast(-1)+1; \ + naTmp[0] = RwIntToFixed(-1)+1; \ } \ - if (naTmp[1] >= RwFixedCast(1)) \ + if (naTmp[1] >= RwIntToFixed(1)) \ { \ - naTmp[1] = RwFixedCast(1)-1; \ + naTmp[1] = RwIntToFixed(1)-1; \ } \ - if (naTmp[1] <= RwFixedCast(-1)) \ + if (naTmp[1] <= RwIntToFixed(-1)) \ { \ - naTmp[1] = RwFixedCast(-1)+1; \ + naTmp[1] = RwIntToFixed(-1)+1; \ } \ - if (naTmp[2] >= RwFixedCast(1)) \ + if (naTmp[2] >= RwIntToFixed(1)) \ { \ - naTmp[2] = RwFixedCast(1)-1; \ + naTmp[2] = RwIntToFixed(1)-1; \ } \ - if (naTmp[2] <= RwFixedCast(-1)) \ + if (naTmp[2] <= RwIntToFixed(-1)) \ { \ - naTmp[2] = RwFixedCast(-1)+1; \ + naTmp[2] = RwIntToFixed(-1)+1; \ } \ \ (n).x = (RwInt8)(naTmp[0]>>9); \ @@ -853,37 +758,13 @@ extern RpMeshHeader * _rpMeshHeaderCreate(RwUInt32 size); (n).z = (RwInt8)(naTmp[2]>>9); \ } -/* RpCollSector access macros - for pre v304 data */ -#define RWCOLLSECTORGETTYPE(sect) \ - ((sect).cType&0x80) - -#define RWCOLLSECTORGETPLANE(sect) \ - ((((sect).cType)>>3)&0xc) - -#define RWCOLLSECTORGETON(sect) \ - (((sect).cType)&0x1f) - -#define RWCOLLSECTORGETVERTEX(sect) \ - (sect).vertex - -#define RWCOLLSECTORGETSTART(sect) \ - (sect).start - -#define RWCOLLSECTORGETNOPOLYS(sect) \ - (sect).cType - -#define RWCOLLSECTORSETPOLYGONS(sect,no,st) \ - (sect).cType = (RwUInt8)(no); \ - (sect).start = (RwUInt8)(st) - -#define rwMAXCOLLISIONCUTS 7 - /**************************************************************************** Global types */ typedef struct RpVertexNormal RpVertexNormal; +#if (!defined(DOXYGEN)) struct RpVertexNormal { RwInt8 x; @@ -899,28 +780,11 @@ struct RpPolygon RwUInt16 matIndex; RwUInt16 vertIndex[3]; }; - -/* RpCollSector - for pre v304 data */ -#define RWCOLLSECTORSETPLANE(sect,plane,vert,no,st) \ - (sect).cType = (RwUInt8)(0x80|((plane)<<3)|(no)); \ - (sect).vertex = (RwUInt8)(vert); \ - (sect).start = (RwUInt8)(st) - -typedef struct RpCollSector RpCollSector; - -struct RpCollSector -{ - RwUInt8 cType; /* Bit 7 - 1 plane */ - /* 0 polygons */ - /* Bit 6-5 - plane */ - /* Bit 4-0 - amount ON plane */ - RwUInt8 vertex; /* Vertex index used for the split */ - RwUInt8 start; /* Starting polygon */ -}; +#endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpWorldSector + * \ingroup rpworldsector + * \struct RpWorldSector * World Sector object. This should be * considered an opaque type. Use the RpWorldSector API functions to access. */ @@ -958,9 +822,6 @@ struct RpWorldSector /* Bounding box tightly enclosing geometry */ RwBBox tightBoundingBox; - /* The root of the bsp collision tree for pre v304 data */ - RpCollSector *colSectorRoot; - /* The mesh which groups same material polygons together */ RpMeshHeader *mesh; @@ -981,9 +842,8 @@ struct RpWorldSector #endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpWorldSectorCallBack - \ref RpWorldSectorCallBack + * \ingroup rpworldsector + * \ref RpWorldSectorCallBack * represents the function called from \ref RpWorldForAllWorldSectors, * \ref RpAtomicForAllWorldSectors and \ref RpLightForAllWorldSectors for all * world sectors in a given world or world sectors a given atomic or light lies @@ -991,15 +851,17 @@ struct RpWorldSector * indicate success. The callback may return NULL to terminate further * callbacks on the atomic or light. * + * \param sector Pointer to the current world sector + * \param data Pointer to developer-defined data structure. + * * \return Pointer to the current world sector. * - * \param sector Pointer to the current world sector - * \param data Pointer to developer-defined data structure. */ typedef RpWorldSector *(*RpWorldSectorCallBack)(RpWorldSector *worldSector, void *data); typedef struct RpSector RpSector; +#if (!defined(DOXYGEN)) struct RpSector { RwInt32 type; @@ -1022,7 +884,7 @@ struct RpPlaneSector RwReal leftValue; RwReal rightValue; }; - +#endif /* (!defined(DOXYGEN)) */ #ifdef __cplusplus extern "C" @@ -1101,15 +963,16 @@ extern RwBool RpWorldSectorValidatePlugins(const RpWorldSector *sector); Defines */ +#define RPTRISTRIPPOLYGONMAXEDGES 3 + /** - * \ingroup rpworlddatatypes - * \typedef RpTriStripMeshCallBack + * \ingroup rpmesh * \ref RpTriStripMeshCallBack is the callback to generate triangle strips * when the triangle stripped geometries or world sectors are unlocked. * * \param buildMesh pointer to the mesh which the triangle strip will be - * generated from. - * \param data pointer to user-supplied data to pass to the callback + * generated from. + * \param data pointer to user-supplied data to pass to the callback * function. * * \return a pointer to the constructed mesh header. @@ -1119,10 +982,156 @@ typedef RpMeshHeader * (*RpTriStripMeshCallBack) (RpBuildMesh *buildMesh, void *data); + /**************************************************************************** Global types */ +typedef struct RpTriStripEdge RpTriStripEdge; + +typedef struct RpTriStripPolygon RpTriStripPolygon; +/** + * \ingroup rpmesh + * \struct RpTriStripPolygon + * This type represents a polygon. + * + * \see RpTriStripPolygonFollowStrip + * \see RpBuildMeshGenerateTriStrip + * \see RpTriStripMeshTunnel + */ +struct RpTriStripPolygon +{ + RwLLLink inEndLink; /**< link for list of polygons joined by fewer than + 2 strip edges */ + RwLLLink inUsedLink; /**< link for list of used polygons */ + RwLLLink inFreeLink; /**< link for list of free polygons */ + RwUInt32 numEdges; /**< number of edges */ + RpTriStripEdge *edges[RPTRISTRIPPOLYGONMAXEDGES]; /**< polygon edges */ + RxVertexIndex vertIndex[RPTRISTRIPPOLYGONMAXEDGES]; /**< polygon vertex + indices */ + RwUInt32 testFrame; /**< used to prevent a tri-strip being counted by + the cost function more than once */ +}; + +/** + * \ingroup rpmesh + * \struct RpTriStripEdge + * This type represents a polygon edge which may be part of a tri-strip. + * + * \see RpTriStripPolygonFollowStrip + * \see RpBuildMeshGenerateTriStrip + * \see RpTriStripMeshTunnel + */ +struct RpTriStripEdge +{ + RwLLLink inUsedLink; /**< link for list of used edges */ + RwLLLink inFreeLink; /**< link for list of free edges */ + RpTriStripPolygon *poly1; /**< first polygon including this edge */ + RpTriStripPolygon *poly2; /**< second polygon including this edge or NULL + if this edge is only included in one */ + RxVertexIndex vert1; /**< index of first vertex of edge */ + RxVertexIndex vert2; /**< index of second vertex of edge */ + RwBool strip; /**< TRUE if the edge is part of a tri-strip */ +}; + +typedef struct RpTriStripMesh RpTriStripMesh; +/** + * \ingroup rpmesh + * \struct RpTriStripMesh + * This type represents a mesh and the tri-strips it contains. + * + * \see RpBuildMeshGenerateTriStrip + * \see RpTriStripMeshTunnel + */ +struct RpTriStripMesh +{ + RwUInt32 numPolygons; /**< the number of polygons in the mesh */ + RwLinkList polygonEndList; /**< linked list of polygons joined by fewer + than 2 strip edges. */ + RwLinkList polygonUsedList; /**< linked list of used polygons */ + RwLinkList polygonFreeList; /**< linked list of free polygons */ + RwLinkList edgeUsedList; /**< linked list of used edges */ + RwLinkList edgeFreeList; /**< linked list of free edges */ +}; + +/** + * \ingroup rpmesh + * \ref RpTriStripMeshStripCallBack represents the callback function to + * tri-strip a mesh. + * + * \param mesh Pointer to the mesh to tri-strip. + * \param data Pointer to user-supplied data. + * + * \return Returns a pointer to the current mesh if successful or NULL if an + * error occurred. + */ +typedef RpTriStripMesh * +(*RpTriStripMeshStripCallBack) (RpTriStripMesh *mesh, void *data); + +typedef struct RpTriStripData RpTriStripData; +/** + * \ingroup rpmesh + * \struct RpTriStripData + * This type represents the data required by the + * \ref RpBuildMeshGenerateTriStrip function to tri-strip a mesh. This data must + * be the user-supplied data passed into RpMeshSetTriStripMethod when using + * \ref RpBuildMeshGenerateTriStrip. + * + * \see RpMeshGetTriStripMethod + * \see RpMeshSetTriStripMethod + * \see RpBuildMeshGenerateTriStrip + * \see RpTriStripMeshTunnel + */ +struct RpTriStripData +{ + RwBool ignoreWinding; /**< TRUE to ignore winding order */ + RpTriStripMeshStripCallBack stripCB; /**< callback to tri-strip mesh */ + void *data; /**< data to supply to callback */ +}; + +/** + * \ingroup rpmesh + * \ref RpTriStripCostCallBack represents the callback function used by the + * tunnelling tri-stripper to determine the cost of a tri-strip. + * + * \param startPolygon Pointer to polygon at the start of the tri-strip. + * \param testFrame Value that must be written to the testFrame of all + * polygons in the tri-strip + * \param data Pointer to user-supplied data. + * + * \return Returns the cost of the tri-strip. + */ +typedef RwUInt32 +(*RpTriStripCostCallBack) (RpTriStripPolygon *startPolygon, RwUInt32 testFrame, void *data); + +typedef struct RpTriStripTunnelData RpTriStripTunnelData; +/** + * \ingroup rpmesh + * \struct RpTriStripTunnelData + * This type represents the data required by the + * \ref RpTriStripMeshTunnel function to tri-strip a mesh. This data must + * be the user-supplied data in the RpTriStripData structure passed into + * \ref RpMeshSetTriStripMethod as the user-supplied data when using + * \ref RpTriStripMeshTunnel. + * + * \see RpMeshGetTriStripMethod + * \see RpMeshSetTriStripMethod + * \see RpBuildMeshGenerateTriStrip + * \see RpTriStripMeshTunnel + * \see RpTriStripDefaultCost + */ +struct RpTriStripTunnelData +{ + RwReal quality; /**< the higher the value the better the + output but the longer it will take; + values greater than 1 are unlikely to + be useful */ + RwUInt32 lengthLimit; /**< the maximum tunnel length to use */ + RpTriStripCostCallBack costCB; /**< callback to determine tri-strip cost */ + void *data; /**< data to supply to callbacks */ +}; + + /**************************************************************************** Global Variables @@ -1138,8 +1147,27 @@ extern "C" { #endif /* __cplusplus */ +/* Tri-strip manipulating functions */ +extern RpTriStripPolygon * +RpTriStripPolygonFollowStrip(RpTriStripPolygon *curr, RpTriStripPolygon *prev); -/* Callback mesh generating functions */ +/* Callback strip costing functions */ +extern RwUInt32 +RpTriStripDefaultCost(RpTriStripPolygon *startPolygon, RwUInt32 testFrame, + void *data); + +/* Callback mesh stripping functions */ +extern RpTriStripMesh * +RpTriStripMeshTunnel(RpTriStripMesh *mesh, void *data); + +extern RpTriStripMesh * +RpTriStripMeshQuick(RpTriStripMesh *mesh, void *data); + +/* New callback mesh generating function */ +extern RpMeshHeader * +RpBuildMeshGenerateTriStrip(RpBuildMesh *buildMesh, void *data); + +/* Old callback mesh generating functions. Probably obsolete */ extern RpMeshHeader * RpBuildMeshGenerateTrivialTriStrip(RpBuildMesh *buildMesh, void *data); @@ -1164,7 +1192,7 @@ extern RpMeshHeader * RpBuildMeshGenerateExhaustiveIgnoreWindingTriStrip(RpBuildMesh *buildmesh, void *data); -/* Functions to set and get the global mesh tristrip algorithm */ +/* Functions to set and get the global mesh tri-strip algorithm */ extern RwBool RpMeshSetTriStripMethod(RpTriStripMeshCallBack callback, void *data); @@ -1225,6 +1253,7 @@ _rpMeshOptimise(RpBuildMesh *buildmesh, RwUInt32 flags); typedef struct RpLightChunkInfo RpLightChunkInfo; typedef struct RpLightChunkInfo _rpLight; +#if (!defined(DOXYGEN)) struct RpLightChunkInfo { RwReal radius; /**< radius */ @@ -1234,6 +1263,7 @@ struct RpLightChunkInfo RwReal minusCosAngle; /**< minusCosAngle */ RwUInt32 typeAndFlags; /**< typeAndFlags */ }; +#endif /* (!defined(DOXYGEN)) */ /* Type ID */ #define rpLIGHT 3 @@ -1242,7 +1272,7 @@ struct RpLightChunkInfo #define rpLIGHTPOSITIONINGSTART 0x80 /** - * \ingroup rpworlddatatypes + * \ingroup rplight * \ref RpLightType are * light sub types. This type represents the different * types of light source that can be created using the API function \ref RpLightCreate. @@ -1265,12 +1295,17 @@ enum RpLightType typedef enum RpLightType RpLightType; #define rpLIGHTMINCONEANGLE ((RwReal)0.0f) -#if ((defined(XBOX_DRVMODEL_H)) || (defined(OPENGL_DRVMODEL_H)) || (defined(GCN_DRVMODEL_H))) -/* XBox has Micro$oft-penned drivers, no wonder it crashes... */ -/* OpenGL and GCN clamp to 90 internally, so we mirror that behaviour */ -#define rpLIGHTMAXCONEANGLE ((RwReal)89.9999f) + +#if (defined(XBOX_DRVMODEL_H)) +#define rpLIGHTMAXCONEANGLE (rwPIOVER2) +#elif (defined(OPENGL_DRVMODEL_H)) +#define rpLIGHTMAXCONEANGLE (rwPIOVER2) +#elif (defined(GCN_DRVMODEL_H)) +#define rpLIGHTMAXCONEANGLE (rwPIOVER2) +#elif (defined(D3D8_DRVMODEL_H)) +#define rpLIGHTMAXCONEANGLE (rwPIOVER2) #else -#define rpLIGHTMAXCONEANGLE ((RwReal)180.0f) +#define rpLIGHTMAXCONEANGLE (rwPI) #endif /*************/ @@ -1280,7 +1315,7 @@ typedef enum RpLightType RpLightType; /*************/ /** - * \ingroup rpworlddatatypes + * \ingroup rplight * \ref RpLightFlag defines what geometry is influenced by the light. * The bit-field RpLightFlag specifies the options available for controlling the scope * of a light source (see API function \ref RpLightSetFlags):*/ @@ -1327,10 +1362,10 @@ MACRO_STOP /** - * \ingroup rpworlddatatypes - * \typedef RpLight - * Light. This should be - * considered an opaque type. User the RpLight API functions to access. + * \ingroup rplight + * \struct RpLight + * Light object. This should be + * considered an opaque type. Use the RpLight API functions to access. */ typedef struct RpLight RpLight; @@ -1349,8 +1384,7 @@ struct RpLight #endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpLightCallBack + * \ingroup rplight * \ref RpLightCallBack * represents the function called from \ref RpWorldForAllLights and * \ref RpWorld SectorForAllLights for all lights in a given world or world @@ -1358,25 +1392,34 @@ struct RpLight * indicate success. The callback may return NULL to terminate further * callbacks on the world sector. * + * \param light Pointer to the current light in the world + * sector. + * \param data Pointer to developer-defined data structure. + * * \return Pointer to the current light. - * - * \param light Pointer to the current light in the world - * sector. - * \param data Pointer to developer-defined data structure. */ typedef RpLight *(*RpLightCallBack) (RpLight * light, void *data); typedef struct RpLightTie RpLightTie; +/** + * \ingroup rplight + * \struct RpLightTie + * + * RpLightTie is a linked list of lights inside world sectors. These are + * created when frame hierarchies are updated as part of an \ref RwCameraBeginUpdate. + * This is used for determining which lights influence a world sector and the atomics inside it. + * Creation and destruction of RpLightTies is internal to the world plugin. + */ struct RpLightTie { /* Information for an atomic sector */ - RwLLLink lightInWorldSector; /* Lights IN this ATOMIC SECTOR */ - RpLight *light; + RwLLLink lightInWorldSector; /**< Lights IN this ATOMIC SECTOR */ + RpLight *light; /**< A pointer to a light */ /* Information for a atomic */ - RwLLLink WorldSectorInLight; /* Atomic sectors HOLDING this Light */ - RpWorldSector *sect; + RwLLLink WorldSectorInLight; /**< Atomic sectors HOLDING this Light */ + RpWorldSector *sect; /**< A pointer to a world sector */ }; @@ -1453,6 +1496,7 @@ extern RwUInt32 RpLightGetFlags(const RpLight *light); #endif /* (defined(RWDEBUG) || defined(RWSUPPRESSINLINE)) */ /* API Functions */ +extern void RpLightSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); extern RpLight *RpLightCreate(RwInt32 type); extern RwBool RpLightDestroy(RpLight *light); extern RpLight *RpLightSetRadius(RpLight *light, RwReal radius); @@ -1491,9 +1535,7 @@ extern RwBool RpLightValidatePlugins(const RpLight * light); /*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/d3d8/D3D8lights.h ---*/ -/** - * \ingroup rplightd3d8 - * \typedef RpD3D8AttenuationParams +/* * typedef for struct RpD3D8AttenuationParams */ typedef struct RpD3D8AttenuationParams RpD3D8AttenuationParams; @@ -1546,21 +1588,6 @@ _rwD3D8LightsClose(void); #endif /* __cplusplus */ -/*--- Automatically derived from: C:/daily/rwsdk/world/pipe/p2/p2stdclsw.h ---*/ -typedef RpLight *RxLight; -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxClusterDefinition RxClLights; /* Uses the RxLight type (see above) */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - - /*--- Automatically derived from: c:/daily/rwsdk/world/bageomet.h ---*/ /* @@ -1579,7 +1606,7 @@ extern RxClusterDefinition RxClLights; /* Uses the RxLight type (see above) */ #define rpGEOMETRY 8 /** - * \ingroup rpworlddatatypes + * \ingroup rpgeometry * RpGeometryFlag * Geometry type flags * @@ -1630,7 +1657,7 @@ typedef enum RpGeometryFlag RpGeometryFlag; #define rpGEOMETRYTEXCOORDSETS(_num) ((_num & 0xff) << 16) /** - * \ingroup rpworlddatatypes + * \ingroup rpgeometry * RpGeometryLockMode * Geometry lock flags */ @@ -1665,22 +1692,25 @@ typedef enum RpGeometryLockMode RpGeometryLockMode; */ typedef struct rpGeometryGlobals rpGeometryGlobals; + +#if (!defined(DOXYGEN)) struct rpGeometryGlobals { RwFreeList *geomFreeList; }; +#endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpGeometry + * \ingroup rpgeometry + * \struct RpGeometry * Geometry object. This should be considered an opaque type. * Use the RpGeometry API functions to access. */ typedef struct RpGeometry RpGeometry; /** - * \ingroup rpworlddatatypes - * \typedef RpMorphTarget + * \ingroup rpmorphtarget + * \struct RpMorphTarget * Morph target -- vertex positions and normals. * This should be considered an opaque type. * Use RpMorphTarget API functions to access. @@ -1700,7 +1730,7 @@ struct RpMorphTarget typedef struct RpTriangle RpTriangle; /** - * \ingroup rpworlddatatypes + * \ingroup rpgeometry * \struct RpTriangle * This type represents a triangle in a geometry specified * by three indices into the geometry's vertex list (vertIndex) @@ -1736,18 +1766,12 @@ struct RpGeometry RwTexCoords *texCoords[rwMAXTEXTURECOORDS]; /* Texture coordinates */ - RwSurfaceProperties ignoredSurfaceProps; /* Not used in pp rendering, but present - * so if pipe1 files are read and written these - * values are not lost - */ - RpMeshHeader *mesh; /* The mesh - groups polys of the same material */ RwResEntry *repEntry; /* Information for an instance */ RpMorphTarget *morphTarget; /* The Morph Target */ }; -#endif /* (!defined(DOXYGEN)) */ typedef struct RpGeometryChunkInfo RpGeometryChunkInfo; typedef struct RpGeometryChunkInfo _rpGeometry; @@ -1760,27 +1784,27 @@ struct RpGeometryChunkInfo RwInt32 numVertices; RwInt32 numMorphTargets; - - RwSurfaceProperties ignoredSurfaceProps; }; +#endif /* (!defined(DOXYGEN)) */ /* Callbacks */ /** - * \ingroup rpworlddatatypes - * \typedef RpGeometryCallBack + * \ingroup rpgeometry * \ref RpGeometryCallBack represents the simple callback function for the \ref RpGeometry object. * The callback may return NULL to terminate further callbacks on * the geometry. * * \param geometry Pointer to the current geometry, supplied by iterator. - * \param data Pointer to developer-defined data structure. + * \param data Pointer to developer-defined data structure. + * + * \return */ typedef RpGeometry *(*RpGeometryCallBack)(RpGeometry *geometry, void *data); /** - * \ingroup rpworlddatatypes - * \typedef RpGeometrySortByMaterialCallBack + * \ingroup rpgeometry + * \ref RpGeometrySortByMaterialCallBack * \ref RpGeometrySortByMaterialCallBack is used by * \ref RpGeometrySortByMaterial in order to preserve the validity of plugin * data when the vertices in an \ref RpGeometry are sorted (and some possibly @@ -1790,11 +1814,11 @@ typedef RpGeometry *(*RpGeometryCallBack)(RpGeometry *geometry, void *data); * vertex in the new geometry, the index of the corresponding vertex in the * original geometry. * - * \param oldGeom Pointer to the source geometry. - * \param newGeom Pointer to the new, sorted geometry. - * \param remapTable pointer to the vertex map table + * \param oldGeom Pointer to the source geometry. + * \param newGeom Pointer to the new, sorted geometry. + * \param remapTable Pointer to the vertex map table * \param numberOfEntries Number of vertices in the new - * geometry (size of the map table) + * geometry (size of the map table) */ typedef void (*RpGeometrySortByMaterialCallBack)(const RpGeometry *oldGeom, RpGeometry *newGeom, @@ -2106,25 +2130,10 @@ RpGeometrySetFlags(RpGeometry *geometry, #endif -/* Lighting characteristics */ - -extern const RwSurfaceProperties * -_rpGeometryGetSurfaceProperties(const RpGeometry *geometry); - -extern RpGeometry * -_rpGeometrySetSurfaceProperties(RpGeometry *geometry, - const RwSurfaceProperties *surfaceProperties); - #ifdef __cplusplus } #endif /* __cplusplus */ -#define RpGeometryGetSurfaceProperties(_geometry) \ - _rpGeometryGetSurfaceProperties(_geometry) - -#define RpGeometrySetSurfaceProperties(_geometry, _surfaceProperties) \ - _rpGeometrySetSurfaceProperties(_geometry, _surfaceProperties) - #define rpGeometryAddRef(_geometry) \ _rpGeometryAddRef(_geometry) @@ -2164,7 +2173,7 @@ enum RpInterpolatorFlag typedef enum RpInterpolatorFlag rpInterpolatorFlag; /** - * \ingroup rpworlddatatypes + * \ingroup rpatomic * The bit-field type RpAtomicFlag specifies the options available for * controlling the behavior of atomics. See API function \ref RpAtomicSetFlags. * @@ -2188,7 +2197,7 @@ enum RpAtomicFlag typedef enum RpAtomicFlag RpAtomicFlag; /** - * \ingroup rpworlddatatypes + * \ingroup rpatomic * \ref RpAtomicSetGeomFlag defines how an atomic references a new geometry * * \see RpAtomicSetGeometry @@ -2214,16 +2223,16 @@ typedef enum RpAtomicPrivateFlag rpAtomicPrivateFlag; /** - * \ingroup rpworlddatatypes - * \typedef RpAtomic + * \ingroup rpatomic + * \struct RpAtomic * Atomic Geometry object. This should be * considered an opaque type. Use the RpAtomic API functions to access. */ typedef struct RpAtomic RpAtomic; /** - * \ingroup rpworlddatatypes - * \typedef RpInterpolator + * \ingroup rpinterpolator + * \struct RpInterpolator * Morph Target Interpolator. * This should be considered an opaque type. * Use the RpInterpolator API functions to access. @@ -2245,16 +2254,15 @@ struct RpInterpolator /* More callbacks */ /** - * \ingroup rpworlddatatypes - * \typedef RpClump + * \ingroup rpclump + * \struct RpClump * Clump Geometry object. This should be * considered an opaque type. Use the RpClump API functions to access. */ typedef struct RpClump RpClump; /** - * \ingroup rpworlddatatypes - * \typedef RpClumpCallBack + * \ingroup rpclump * \ref RpClumpCallBack represents the * function called from \ref RwCameraForAllClumpsInFrustum and * \ref RwCameraForAllClumpsNotInFrustum when a clump lies inside the current camera's @@ -2263,8 +2271,8 @@ typedef struct RpClump RpClump; * NULL to terminate further callbacks on the clumps. * * \param clump Pointer to the current clump, supplied by - * iterator. - * \param data Pointer to developer-defined data structure. + * iterator. + * \param data Pointer to developer-defined data structure. * * \return Pointer to the current clump. * @@ -2303,8 +2311,7 @@ struct RpClump #endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpAtomicCallBackRender + * \ingroup rpatomic * \ref RpAtomicCallBackRender represents the function called from * \ref RpAtomicRender when the specified atomic * lies inside the current camera's view frustum. The default callback @@ -2312,10 +2319,13 @@ struct RpClump * return a pointer to the atomic to indicate success. * * \param atomic Pointer to the current atomic, supplied by - * iterator. + * iterator. + * + * \return Returns a pointer to the atomic to indicate success. * * \see RpAtomicRender */ + typedef RpAtomic *(*RpAtomicCallBackRender) (RpAtomic * atomic); #if (!defined(DOXYGEN)) @@ -2356,8 +2366,7 @@ struct RpAtomic #endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rpworlddatatypes - * \typedef RpAtomicCallBack + * \ingroup rpatomic * \ref RpAtomicCallBack represents the function called from \ref RpWorldSectorForAllAtomics and * \ref RpClumpForAllAtomics for all atomics in a given world sector or clump. * This function should return a pointer to the current atomic to indicate @@ -2365,28 +2374,40 @@ struct RpAtomic * the world sector. * * \param atomic Pointer to the current atomic, supplied by - * iterator. - * \param data Pointer to developer-defined data structure. + * iterator. + * \param data Pointer to developer-defined data structure. + * + * \return Returns a pointer to the current atomic */ typedef RpAtomic *(*RpAtomicCallBack) (RpAtomic * atomic, void *data); typedef struct RpTie RpTie; +/** + * \ingroup rpatomic + * \struct RpTie + * + * RpTie is a linked list of atomics inside world sectors. These are + * created when frame hierarchies are updated as part of an \ref RwCameraBeginUpdate. + * This is used for frustum culling atomics by world sector. + * Creation and destruction of RpTies is internal to the world plugin. + */ struct RpTie { /* Information for an atomic sector */ - RwLLLink lAtomicInWorldSector; /* Atomics IN this ATOMIC SECTOR */ - RpAtomic *apAtom; + RwLLLink lAtomicInWorldSector; /**< Atomics IN this ATOMIC SECTOR */ + RpAtomic *apAtom; /**< An atomic */ /* Information for a atomic */ - RwLLLink lWorldSectorInAtomic; /* Atomic sectors HOLDING this atomic */ - RpWorldSector *worldSector; + RwLLLink lWorldSectorInAtomic; /**< Atomic sectors HOLDING this atomic */ + RpWorldSector *worldSector; /**< A world sector */ }; typedef struct RpClumpChunkInfo RpClumpChunkInfo; typedef struct RpClumpChunkInfo _rpClump; typedef struct RpClumpChunkInfo33000 _rpClump33000; +#if (!defined(DOXYGEN)) struct RpClumpChunkInfo { RwInt32 numAtomics; @@ -2398,6 +2419,7 @@ struct RpClumpChunkInfo33000 { RwInt32 numAtomics; }; +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** pipeline), _sector ) -#define RpAtomicGetGenericPipelineMacro() \ - (RXPIPELINEGLOBAL(genericAtomicPipeline)) - #define RpAtomicGetDefaultPipelineMacro() \ (RXPIPELINEGLOBAL(currentAtomicPipeline)) @@ -3473,9 +3479,6 @@ RxD3D8AllInOneGetRenderCallBack(RxPipelineNode *node); #define RpAtomicGetPipelineMacro(_atomic, _pipeline) \ ( (*(_pipeline) = (_atomic)->pipeline), _atomic ) -#define RpMaterialGetGenericPipelineMacro() \ - (RXPIPELINEGLOBAL(genericMaterialPipeline)) - #define RpMaterialGetDefaultPipelineMacro() \ (RXPIPELINEGLOBAL(currentMaterialPipeline)) @@ -3488,19 +3491,16 @@ RxD3D8AllInOneGetRenderCallBack(RxPipelineNode *node); #if !(defined(RWDEBUG) || defined(RWSUPPRESSINLINE)) -#define RpWorldGetGenericSectorPipeline RpWorldGetGenericSectorPipelineMacro #define RpWorldGetDefaultSectorPipeline RpWorldGetDefaultSectorPipelineMacro #define RpWorldSetSectorPipeline RpWorldSetSectorPipelineMacro #define RpWorldGetSectorPipeline RpWorldGetSectorPipelineMacro #define RpWorldSectorSetPipeline RpWorldSectorSetPipelineMacro #define RpWorldSectorGetPipeline RpWorldSectorGetPipelineMacro -#define RpAtomicGetGenericPipeline RpAtomicGetGenericPipelineMacro #define RpAtomicGetDefaultPipeline RpAtomicGetDefaultPipelineMacro #define RpAtomicSetPipeline RpAtomicSetPipelineMacro #define RpAtomicGetPipeline RpAtomicGetPipelineMacro -#define RpMaterialGetGenericPipeline RpMaterialGetGenericPipelineMacro #define RpMaterialGetDefaultPipeline RpMaterialGetDefaultPipelineMacro #define RpMaterialSetPipeline RpMaterialSetPipelineMacro #define RpMaterialGetPipeline RpMaterialGetPipelineMacro @@ -3556,7 +3556,6 @@ extern RpGeometry *RpGeometrySortByMaterial(const RpGeometry * geometry, #endif /* __cplusplus */ /* LEGACY-SUPPORT macros */ -#define RpWorldGetGenericSectorInstancePipeline RpWorldGetGenericSectorPipeline #define RpWorldSetDefaultSectorInstancePipeline RpWorldSetDefaultSectorPipeline #define RpWorldGetDefaultSectorInstancePipeline RpWorldGetDefaultSectorPipeline #define RpWorldSetSectorInstancePipeline RpWorldSetSectorPipeline @@ -3564,13 +3563,11 @@ extern RpGeometry *RpGeometrySortByMaterial(const RpGeometry * geometry, #define RpWorldSectorSetInstancePipeline RpWorldSectorSetPipeline #define RpWorldSectorGetInstancePipeline RpWorldSectorGetPipeline -#define RpAtomicGetGenericInstancePipeline RpAtomicGetGenericPipeline #define RpAtomicGetDefaultInstancePipeline RpAtomicGetDefaultPipeline #define RpAtomicSetDefaultInstancePipeline RpAtomicSetDefaultPipeline #define RpAtomicSetInstancePipeline RpAtomicSetPipeline #define RpAtomicGetInstancePipeline RpAtomicGetPipeline -#define RpMaterialGetGenericRenderPipeline RpMaterialGetGenericPipeline #define RpMaterialSetDefaultRenderPipeline RpMaterialSetDefaultPipeline #define RpMaterialGetDefaultRenderPipeline RpMaterialGetDefaultPipeline #define RpMaterialSetRenderPipeline RpMaterialSetPipeline @@ -3587,6 +3584,9 @@ extern "C" { #endif /* __cplusplus */ +extern void RpTieSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); +extern void RpLightTieSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + /* Adding and removing cameras to/from the world */ extern RpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera); extern RpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera); @@ -3648,6 +3648,7 @@ extern RpWorldSector *RpWorldSectorForAllLights(RpWorldSector *sector, typedef struct RpWorldChunkInfoSector RpWorldSectorChunkInfo; typedef struct RpWorldChunkInfoSector _rpWorldSector; +#if (!defined(DOXYGEN)) struct RpWorldChunkInfoSector { RwInt32 matListWindowBase; @@ -3655,10 +3656,11 @@ struct RpWorldChunkInfoSector RwInt32 numVertices; RwV3d inf; RwV3d sup; - RwBool collSectorPresent; + RwBool collSectorPresent; /* unused but retains same struct size */ RwBool unused; }; + typedef struct RpPlaneSectorChunkInfo RpPlaneSectorChunkInfo; typedef struct RpPlaneSectorChunkInfo _rpPlaneSector; @@ -3681,6 +3683,26 @@ struct RpWorldChunkInfo RwV3d invWorldOrigin; + RwInt32 numPolygons; + RwInt32 numVertices; + RwInt32 numPlaneSectors; + RwInt32 numWorldSectors; + RwInt32 colSectorSize; + + RwInt32 format; /* Flags about the world */ + + /* Added in 34003 */ + RwBBox boundingBox; +}; + +typedef struct rpWorldChunkInfo34000 rpWorldChunkInfo34000; + +struct rpWorldChunkInfo34000 +{ + RwBool rootIsWorldSector; + + RwV3d invWorldOrigin; + RwSurfaceProperties surfaceProps; RwInt32 numPolygons; @@ -3691,6 +3713,7 @@ struct RpWorldChunkInfo RwInt32 format; /* Flags about the world */ }; +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** Function prototypes diff --git a/rwsdk/include/d3d8/rt2d.h b/rwsdk/include/d3d8/rt2d.h index 5bf1faea..0584d3a5 100644 --- a/rwsdk/include/d3d8/rt2d.h +++ b/rwsdk/include/d3d8/rt2d.h @@ -17,7 +17,7 @@ /** * \defgroup rt2d Rt2d - * \ingroup rttool + * \ingroup 2dtools * * 2D Rendering Toolkit for RenderWare. */ @@ -117,6 +117,7 @@ Includes */ +#include "rpworld.h" #include "rt2d.rpe" /* automatically generated header file */ /**************************************************************************** @@ -132,6 +133,13 @@ #define Rt2dCTMReadMacro(_result) \ (RwMatrixCopy((_result), _rt2dCTMGet()), (_result)) +#if defined (GCN_DRVMODEL_H) + #define VERTEXCACHESIZE 64 +#else + #define VERTEXCACHESIZE 256 +#endif + + /**************************************************************************** Global Types */ @@ -152,16 +160,21 @@ typedef struct rt2dShadeParameters rt2dShadeParameters; * rt2dShadeParameters * describes Shade Parameters */ + +#if (!defined(DOXYGEN)) struct rt2dShadeParameters { RwRGBAReal col; /* col */ RwV2d uv; /* uv */ }; +#endif /* (!defined(DOXYGEN)) */ /** * \ingroup rt2ddatatypes - * \typedef Rt2dBrush - * typedef for a structure describing a Brush (opaque) + * \struct Rt2dBrush + * Brush object. + * This should be considered an opaque type. + * Use Rt2dBrush API functions to access. */ typedef struct Rt2dBrush Rt2dBrush; @@ -169,35 +182,37 @@ typedef struct Rt2dBrush Rt2dBrush; * Rt2dBrush * structure describing a Brush */ -#if defined (GCN_DRVMODEL_H) - #define VERTEXCACHESIZE 64 -#else - #define VERTEXCACHESIZE 256 -#endif - +#if (!defined(DOXYGEN)) struct Rt2dBrush { - RWIM3DVERTEX vertex[VERTEXCACHESIZE]; rt2dShadeParameters top; rt2dShadeParameters dtop; rt2dShadeParameters bottom; rt2dShadeParameters dbottom; - RwInt32 calcFields; + RwRGBA colorCache; + RwInt32 flag; RwTexture *texture; + RpMaterial *material; RwReal halfwidth; + RwInt32 refCount; }; +#endif /* (!defined(DOXYGEN)) */ /** * \ingroup rt2ddatatypes - * \typedef Rt2dPath - * typedef for a structure describing a Path (opaque) + * \struct Rt2dPath + * Path object. + * This should be considered an opaque type. + * Use Rt2dPath API functions to access. */ typedef struct Rt2dPath Rt2dPath; /** * \ingroup rt2ddatatypes - * \typedef Rt2dFont - * typedef for a structure describing a Font (opaque) + * \struct Rt2dFont + * Font object. + * This should be considered an opaque type. + * Use Rt2dFont API functions to access. */ typedef struct Rt2dFont Rt2dFont; @@ -206,11 +221,6 @@ typedef struct Rt2dFont Rt2dFont; */ typedef struct _rt2dFontDictionaryNode _rt2dFontDictionaryNode; -/** - * \ingroup rt2ddatatypes - * \typedef Rt2dBBox - * typedef for a structure describing a Bounding Box - */ typedef struct Rt2dBBox Rt2dBBox; /** @@ -228,8 +238,8 @@ struct Rt2dBBox /** * \ingroup rt2ddatatypes - * \typedef Rt2dObject - * typedef for a structure describing a 2d Object + * \struct Rt2dObject + * Structure describing a 2d Object * This should be considered an opaque type. * Use Rt2dObject, Rt2dScene, Rt2dShape, Rt2dPickRegion or Rt2dObjectString * API functions to access. @@ -246,6 +256,7 @@ typedef struct _rt2dScene _rt2dScene; */ typedef struct _rt2dDepthOfObject _rt2dDepthOfObject; +#if (!defined(DOXYGEN)) /* * typedef for a structure describing the depth of an object */ @@ -265,15 +276,47 @@ struct _rt2dScene RwSList *depths; /* depths for depthsort */ RwBool isDirtyDepths; /* depthsort needs updating */ }; +#endif /* (!defined(DOXYGEN)) */ /* * typedef for a structure describing a shape (opaque) */ typedef struct _rt2dShape _rt2dShape; +#if (!defined(DOXYGEN)) +typedef struct _rt2dShapeRep _rt2dShapeRep; +struct _rt2dShapeRep +{ + RwSList *nodes; /* individual stroked/filled regions of the shape */ + RwUInt32 refCount; /* number of shapes referencing this rep */ + RpGeometry *geometry; /* Shareable geometry */ +}; + +extern _rt2dShapeRep * + _rt2dShapeRepCreate(); + +extern RwBool +_rt2dShapeRepDestroy(_rt2dShapeRep *); + +extern RwUInt32 +_rt2dShapeRepAddRef(_rt2dShapeRep *); + +typedef struct _rt2dSceneResourcePool _rt2dSceneResourcePool; +struct _rt2dSceneResourcePool +{ + _rt2dShapeRep **shapeReps; + RwUInt32 numShapeReps; +}; + +extern RwBool +_rt2dSceneResourcePoolFindShapeRep(const _rt2dSceneResourcePool * pool, + const _rt2dShapeRep * rep, RwInt32 * npIndex); + struct _rt2dShape { - RwSList *nodes; /* individual stroked/filled regions of the shape */ + _rt2dShapeRep *rep; + RwRGBA *colorCache; /* Shape's color cache */ + RpAtomic *atomic; /* Atomic repn */ }; /* @@ -295,6 +338,7 @@ struct _rt2dPickRegion /* * structure describing a renderable text string */ + struct _rt2dObjectString { RwChar *textString; /* Text string to be rendered */ @@ -303,6 +347,7 @@ struct _rt2dObjectString RwReal height; /* Font rendering Height */ _rt2dFontDictionaryNode *font; /* Dictionary node identifying font to be used */ }; +#endif /* (!defined(DOXYGEN)) */ /* * typedef for a renderable string @@ -324,6 +369,7 @@ enum Rt2dObjectTypeEnum { typedef union _rt2dObjectdata _rt2dObjectdata; +#if (!defined(DOXYGEN)) union _rt2dObjectdata { _rt2dShape shape; @@ -335,11 +381,13 @@ union _rt2dObjectdata /* * A base structure for forming a hierarchy of 2D shapes */ -#if (!defined(DOXYGEN)) -#define Rt2dObjectIsLocked 0x00000001 -#define Rt2dObjectDirtyLTM 0x00000002 -#define Rt2dObjectVisible 0x00000004 +#define Rt2dObjectIsLocked 0x00000001 +#define Rt2dObjectDirtyLTM 0x00000002 +#define Rt2dObjectVisible 0x00000004 +#define Rt2dObjectDirtyColor 0x00000008 + +#define Rt2dObjectStringGotNoFonts 0x01000000 struct Rt2dObject { @@ -357,11 +405,35 @@ struct Rt2dObject /** * \ingroup rt2ddatatypes - * \typedef Rt2dObjectCallBack - * typedef for a callback on an object + * \ref Rt2dObjectCallBack + * typedef for a callback on an object in a collection + * + * \param object is a specific object + * \param parent is the containing scene + * \param data is user data + * + * \return return value is ignored */ typedef Rt2dObject *(* Rt2dObjectCallBack)(Rt2dObject *object, Rt2dObject *parent, void *data); +/** + * \ingroup rt2ddatatypes + * \ref Rt2dFontCallBackRead + * Rt2dFontCallBackRead represents the function used by Rt2dFontRead to read + * the specified font from a disk file. This function should return a + * pointer to the font to indicate success. The returned font is owned by + * the Rt2d internal font dictionary, and is destroyed on calling + * \ref Rt2dClose + * + * \param name is the name of the font to read + * + * \return return the font if successful, NULL otherwise + * + * \see Rt2dFontSetReadCallBack + * \see Rt2dFontGetReadCallBack + */ +typedef Rt2dFont*(* Rt2dFontCallBackRead)(const RwChar *name); + /** * \ingroup rt2ddatatypes * \ref Rt2dJustificationType @@ -381,6 +453,20 @@ enum Rt2dJustificationType */ typedef enum Rt2dJustificationType Rt2dJustificationType; +/** + * \ingroup rt2ddatatypes + * \ref Rt2dShapeNodeFlag + * Passed to \ref Rt2dShapeAddNode, these flags specify + * the type and properties of the path. + */ +enum Rt2dShapeNodeFlag +{ + rt2dSHAPENODEFLAGNONE = 0x0000, + rt2dSHAPENODEFLAGSOLID = 0x0001, /**< Shape's node is a solid, not outline */ + rt2dSHAPENODEFLAGFORCEENUMSIZEINT = RWFORCEENUMSIZEINT /* Ensure sizeof(enum) == sizeof(RwInt32) */ +}; + + #if (! ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) )) #define Rt2dBrushSetWidth(_brush, _width) \ @@ -397,7 +483,20 @@ typedef enum Rt2dJustificationType Rt2dJustificationType; /**************************************************************************** Function prototypes */ +extern void +Rt2dBrushSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); +extern void +Rt2dFontSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + +extern void +Rt2dFontDictNodeSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + +extern void +Rt2dObjectSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + +extern void +Rt2dPathSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); /* * INITIALIZE @@ -407,6 +506,13 @@ Rt2dOpen(RwCamera *cam); extern void Rt2dClose(void); + +extern void +Rt2dTriVertSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + +extern void +Rt2dTriPolySetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + /* * PATHS */ @@ -518,6 +624,12 @@ Rt2dFontSetPath(const RwChar *path); extern Rt2dFont * Rt2dFontRead(const RwChar *name); +extern RwBool +Rt2dFontSetReadCallBack(Rt2dFontCallBackRead fpCallBack); + +extern Rt2dFontCallBackRead +Rt2dFontGetReadCallBack (void); + extern RwUInt32 _rt2dFontStreamGetSize(Rt2dFont *font); @@ -695,6 +807,10 @@ Rt2dObjectIsObjectString(Rt2dObject *object); extern Rt2dObject * Rt2dObjectCopy(Rt2dObject *dst, Rt2dObject *src); +/* in-place dst version, destruction not req */ +extern Rt2dObject * +_rt2dObjectCopy(Rt2dObject *dst, Rt2dObject *src); + /* * HIERARCHICAL SCENE FUNCTIONS - SCENE */ @@ -766,14 +882,8 @@ Rt2dShapeCreate(void); extern RwBool Rt2dShapeDestroy(Rt2dObject * shape); -extern Rt2dBrush * -Rt2dShapeGetNewBrush(Rt2dObject *shape); - -extern Rt2dPath * -Rt2dShapeGetNewPath(Rt2dObject *shape); - extern Rt2dObject * -Rt2dShapeAddNode(Rt2dObject *shape, Rt2dPath *path, Rt2dBrush *fill, Rt2dBrush *stroke ); +Rt2dShapeAddNode(Rt2dObject *shape, RwUInt32 flag, Rt2dPath *path, Rt2dBrush *brush ); extern RwInt32 Rt2dShapeGetNodeCount(Rt2dObject *shape); @@ -792,9 +902,15 @@ Rt2dShapeRender(Rt2dObject *object); extern Rt2dObject * Rt2dShapeMorph(Rt2dObject *result, - Rt2dObject *source, - Rt2dObject *destination, - RwReal alpha); + Rt2dObject *source, + Rt2dObject *destination, + RwReal alpha); + +extern Rt2dObject * +Rt2dShapeLock(Rt2dObject * shape); + +extern Rt2dObject * +Rt2dShapeUnlock(Rt2dObject * shape); /* * HIERARCHICAL SCENE FUNCTIONS - PICK REGION @@ -895,6 +1011,7 @@ Rt2dCTMRead(RwMatrix * result); #endif /* ( defined(RWDEBUG) || defined(RWSUPPRESSINLINE) ) */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/rwsdk/include/d3d8/rt2d.rpe b/rwsdk/include/d3d8/rt2d.rpe index 1f9f8881..b18db155 100644 --- a/rwsdk/include/d3d8/rt2d.rpe +++ b/rwsdk/include/d3d8/rt2d.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -620,6 +154,7 @@ enum e_rwdb_Criterion2D { +E_RW_FONTNOTFOUND, e_rwdb_Criterion2DLAST = RWFORCEENUMSIZEINT }; diff --git a/rwsdk/include/d3d8/rt2danim.h b/rwsdk/include/d3d8/rt2danim.h index cd593a8e..996262af 100644 --- a/rwsdk/include/d3d8/rt2danim.h +++ b/rwsdk/include/d3d8/rt2danim.h @@ -10,8 +10,8 @@ #define RT2DANIM_H /** - * \defgroup rt2danim Rt2dAnim - * \ingroup rttool + * \defgroup rt2danim Rt2dAnim (inc. Maestro) + * \ingroup 2dtools * * A toolkit to coordinate the display, storage and manipulation of 2D * animations. @@ -166,101 +166,132 @@ typedef enum Rt2dStringLabelType Rt2dStringLabelType; /** * \ingroup rt2danimsub - * \typedef Rt2dAnimProps - * typedef for a structure describing the current state of a scene (opaque) + * \struct Rt2dAnimProps + * Structure describing the current state of a scene. + * This should be considered an opaque type. Use the + * Rt2dAnim API functions to access. */ typedef struct Rt2dAnimProps Rt2dAnimProps; /** * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameList - * typedef for a structure describing a list of keyframes + * \struct Rt2dKeyFrameList + * Structure describing an entire list of keyframes + * This should be considered an opaque type. Use the + * Rt2dKeyFrameList API functions to access. */ typedef struct Rt2dKeyFrameList Rt2dKeyFrameList; /** * \ingroup rt2danimsub - * \typedef Rt2dAnimObjectUpdate - * typedef for a structure describing a set of changes to a 2d object (opaque) + * \struct Rt2dKeyFrameSet + * structure describing a set of keyframe actions to be applied to a 2D object. + * This should be considered an opaque type. Use the + * Rt2dAnim API functions to access. + */ +typedef struct Rt2dKeyFrameSet Rt2dKeyFrameSet; + +/** + * \ingroup rt2danimsub + * \struct Rt2dAnimObjectUpdate + * Structure describing an unoptimized update to an object + * This should be considered an opaque type. Use the + * Rt2dAnim API functions to access. */ typedef struct Rt2dAnimObjectUpdate Rt2dAnimObjectUpdate; /** * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameTransform - * typedef for a structure describing a transform change to a 2d object (opaque) + * \struct Rt2dKeyFrameTransform + * Structure describing a transform change to a 2d object. + * This should be considered an opaque type. Use the + * Rt2dAnim API functions to access. */ typedef struct Rt2dKeyFrameTransform Rt2dKeyFrameTransform; -/** - * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameColor - * typedef for a structure describing a color change to a 2d object (opaque) +/* + * Typedef for struct Rt2dKeyFrameColor describing a color + * change to a 2d object. */ typedef struct Rt2dKeyFrameColor Rt2dKeyFrameColor; -/** - * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameShow - * typedef for a structure describing a displayable or depth change to a 2d object (opaque) +/* + * Structure describing a displayable or depth change to a 2d object. */ typedef struct Rt2dKeyFrameShow Rt2dKeyFrameShow; -/** - * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameMorph - * typedef for a structure describing a morph change to a 2d object (opaque) +/* + * Structure describing a morph change to a 2d object. */ typedef struct Rt2dKeyFrameMorph Rt2dKeyFrameMorph; /** * \ingroup rt2danimsub - * \typedef Rt2dAnim - * typedef for a structure describing a 2d animation (opaque) + * \struct Rt2dAnim + * Structure describing a 2d animation. + * This should be considered an opaque type. Use the + * Rt2dAnim API functions to access. */ typedef struct Rt2dAnim Rt2dAnim; /** * \ingroup rt2dbutton - * \typedef Rt2dButton - * typedef for a structure describing a button (opaque) + * \struct Rt2dButton + * Structure describing a button. + * This should be considered an opaque type. Use the + * Rt2dButton API functions to access. */ typedef struct Rt2dButton Rt2dButton; /** * \ingroup rt2dcel - * \typedef Rt2dCel - * typedef for a structure describing a cel (opaque) + * \struct Rt2dCel + * Structure describing a cel. + * This should be considered an opaque type. Use the + * Rt2dCel API functions to access. */ typedef struct Rt2dCel Rt2dCel; /** * \ingroup rt2dcel - * \typedef Rt2dCelList - * typedef for a structure describing a cel list (opaque) + * \struct Rt2dCelList + * Structure describing a cel list. + * This should be considered an opaque type. Use the + * Rt2dCel API functions to access. */ typedef struct Rt2dCelList Rt2dCelList; /** * \ingroup rt2dmaestro - * \typedef Rt2dMaestro - * typedef for a structure describing a maestro (opaque) + * \struct Rt2dMaestro + * Structure describing a maestro. + * This should be considered an opaque type. Use the + * Rt2dMaestro API functions to access. */ typedef struct Rt2dMaestro Rt2dMaestro; -/** - * \ingroup rt2dmessage - * \typedef Rt2dMessage - * typedef for a structure describing a message (opaque) +/* + * Structure describing a message. */ typedef struct Rt2dMessage Rt2dMessage; +/** + * \ingroup rt2dmessage + * \struct Rt2dMessageList + * Structure describing a message. + * This should be considered an opaque type. Use the + * Rt2dMessage API functions to access. + */ typedef struct Rt2dMessageList Rt2dMessageList; /** * \ingroup rt2dstringlabel - * \typedef Rt2dStringLabel - * typedef for a structure describing a string label (opaque) + * \struct Rt2dStringLabel + * Structure used to store and access named data, either internal or user. + * A type and a name may be used to access internal and user data. + * + * This should be considered an opaque type. Use the + * Rt2dStringLabel API functions to access. */ typedef struct Rt2dStringLabel Rt2dStringLabel; @@ -277,7 +308,8 @@ struct Rt2dKeyFrameTransform /** * \ingroup rt2danimsub * \struct Rt2dKeyFrameColor - * structure describing a color setting action + * Structure describing a color + * change to a 2d object. */ struct Rt2dKeyFrameColor { @@ -287,7 +319,7 @@ struct Rt2dKeyFrameColor /** * \ingroup rt2danimsub * \struct Rt2dKeyFrameShow - * structure describing a show/hide action + * Structure describing a show/hide change and a depth change to a 2d object. */ struct Rt2dKeyFrameShow { @@ -299,7 +331,7 @@ struct Rt2dKeyFrameShow /** * \ingroup rt2danimsub * \struct Rt2dKeyFrameMorph - * structure describing a morph action + * Structure describing a morph change to a 2d object. */ struct Rt2dKeyFrameMorph { @@ -355,69 +387,73 @@ MACRO_START \ } \ MACRO_STOP -/** - * \ingroup rt2dstringlabel - * \struct Rt2dStringLabel - * structure containing label information. The enitityType identifies the type +/* + * structure containing label information. The entityType identifies the type * of the label. The label's name is stored as an index * in common storage area. The entityType and name of the label are used as keys * during a search. Additional internal and user data can be stored with the * label. */ + +#if (!defined(DOXYGEN)) struct Rt2dStringLabel { - RwUInt32 entityType; /**< type of the label - (\ref Rt2dStringLabelType) */ - RwInt32 nameIndex; /**< index of name in internal data + RwUInt32 entityType; /* type of the label + (see Rt2dStringLabelType) */ + RwInt32 nameIndex; /* index of name in internal data area */ - void *internalData; /**< internal data */ - void *userData; /**< customizable data */ + void *internalData; /* internal data */ + void *userData; /* customizable data */ }; +#endif /* (!defined(DOXYGEN)) */ + #define _rt2dStringLabelGetStringLabelTypeMacro(_strLabel) \ - ((_strLabel)->entityType); + ((_strLabel)->entityType) #define _rt2dStringLabelSetStringLabelTypeMacro(_strLabel, _entityType) \ - ((_strLabel)->entityType = (_entityType)); + ((_strLabel)->entityType = (_entityType)) #define _rt2dStringLabelGetNameIndexMacro(_strLabel) \ - ((_strLabel)->nameIndex); + ((_strLabel)->nameIndex) #define _rt2dStringLabelSetNameIndexMacro(_strLabel, _index) \ - ((_strLabel)->nameIndex = (_index)); + ((_strLabel)->nameIndex = (_index)) #define _rt2dStringLabelGetInternalDataMacro(_strLabel) \ - ((_strLabel)->internalData); + ((_strLabel)->internalData) #define _rt2dStringLabelSetInternalDataMacro(_strLabel, _internalData) \ - ((_strLabel)->internalData = (_internalData)); + ((_strLabel)->internalData = (_internalData)) #define _rt2dStringLabelGetUserDataMacro(_strLabel) \ - ((_strLabel)->userData); + ((_strLabel)->userData) #define _rt2dStringLabelSetUserDataMacro(_strLabel, _userData) \ - ((_strLabel)->userData = (_userData)); + ((_strLabel)->userData = (_userData)) -/** - * \ingroup rt2dcel - * \struct Rt2dCel +/* * structure containing cel information. The name of the cel is stored as an * index into a label table. The buttons in the cel are stored as indices. These - * reference a list of buttons held by the cel's parent maestro. Any messages + * reference a list of buttons held by the cel's parent maestro. Any messages * to be process when the cel is active is stored as index into the parent's * maestro's message storage area. */ + +#if (!defined(DOXYGEN)) struct Rt2dCel { - RwInt32 strLabelIndex; /**< Frame label */ - RwInt32 celIndex; /**< Frame number */ - RwSList *buttonIndices; /**< List of buttons active in - this frame */ - RwInt32 messageListIndex; /**< Messages to be posted after - displaying this frame */ + RwInt32 strLabelIndex; /* Frame label */ + RwInt32 celIndex; /* Frame number */ + RwSList *buttonIndices; /* List of buttons active in + this frame */ + RwInt32 messageListIndex; /* Messages to be posted after + displaying this frame */ }; +#endif /* (!defined(DOXYGEN)) */ + #define _rt2dCelGetStringLabelIndexMacro(_cel) \ ((_cel)->strLabelIndex); @@ -443,14 +479,16 @@ typedef Rt2dAnim *(*Rt2dAnimCallBack)(Rt2dAnim *object, void *data); /** * \ingroup rt2danimsub - * \typedef Rt2dKeyFrameListCallBack + * \ref Rt2dKeyFrameListCallBack * This typedef defines a callback function to apply to a frame list. * - * \param anim Pointer to the animation - * \param props Pointer to the props that the animation acts upon - * \param keyframeList The key frame list + * \param anim Pointer to the animation + * \param props Pointer to the props that the animation acts upon + * \param keyframeList The key frame list * \param keyframeListTime The key frame list time - * \param data User defined data + * \param data User defined data + * + * \return return value is ignored */ typedef Rt2dKeyFrameList *(Rt2dKeyFrameListCallBack)( Rt2dAnim *anim, @@ -461,12 +499,14 @@ typedef Rt2dKeyFrameList *(Rt2dKeyFrameListCallBack)( /** * \ingroup rt2danimsub - * \typedef Rt2dAnimOnEndReachedCallBack + * \ref Rt2dAnimOnEndReachedCallBack * This typedef defines a callback function called at the end of an animation. * - * \param anim Pointer to the animation ending - * \param props Pointer to the props that the animation acts upon + * \param anim Pointer to the animation ending + * \param props Pointer to the props that the animation acts upon * \param remainingDeltaTime Remaining time + * + * \return return value is ignored */ typedef Rt2dAnim *(*Rt2dAnimOnEndReachedCallBack)(Rt2dAnim *anim, Rt2dAnimProps *props, @@ -474,14 +514,14 @@ typedef Rt2dAnim *(*Rt2dAnimOnEndReachedCallBack)(Rt2dAnim *anim, /** * \ingroup rt2dmaestro - * \typedef Rt2dMaestroAnimationsCallBack + * \ref Rt2dMaestroAnimationsCallBack * \ref Rt2dMaestroAnimationsCallBack represents the function called from * \ref Rt2dMaestroForAllAnimations for all animations in the maestro. * This function * should return the current maestro to indicate success. The callback may * return NULL to terminate further callbacks on the maestro. * - * \param maestro Pointer to parent maestro. + * \param maestro Pointer to parent maestro. * \param anim Pointer to the animation. * \param props Pointer to the anim's props. * \param pData Pointer to private data. @@ -494,7 +534,6 @@ typedef Rt2dMaestro *(*Rt2dMaestroAnimationsCallBack) /** * \ingroup rt2dmessage - * \typedef Rt2dMessageHandlerCallBack * \ref Rt2dMessageHandlerCallBack represents the function called from * \ref Rt2dMaestroProcessMessages for all messages in the maestro's * process message queue. The maestro does not filter any messages. The @@ -504,7 +543,7 @@ typedef Rt2dMaestro *(*Rt2dMaestroAnimationsCallBack) * callback may return NULL to terminate further callbacks on the maestro. * * \param maestro Pointer to parent maestro. - * \param message Pointer to the message. + * \param message Pointer to the message. * * \return Pointer to the message. */ @@ -530,6 +569,18 @@ typedef Rt2dMessage * * Data access macros. */ +/* + * Toolkit-level initialization / finalization + */ +/* + * INITIALIZE + */ +extern void +Rt2dAnimOpen(void); + +extern void +Rt2dAnimClose(void); + /* * Rt2dAnim */ @@ -747,7 +798,7 @@ Rt2dMaestroAddButton(Rt2dMaestro *maestro, RwInt32 strLabelIdx, RwInt32 objectId extern Rt2dCel * Rt2dCelCreate(Rt2dMaestro *maestro, - RwChar *name, + const RwChar *name, RwInt32 celIndex, RwInt32 messageListIndex); extern Rt2dCelList * @@ -966,7 +1017,7 @@ Rt2dMessageHandlerDefaultCallBack(Rt2dMaestro *maestro, Rt2dMessage *message); */ extern Rt2dStringLabel * Rt2dMaestroFindStringLabel(Rt2dMaestro *maestro, - Rt2dStringLabelType entityType, RwChar *lookupName, + Rt2dStringLabelType entityType, const RwChar *lookupName, RwInt32 *index); extern Rt2dStringLabel * @@ -974,7 +1025,7 @@ Rt2dMaestroGetStringLabelByIndex(Rt2dMaestro *maestro, RwInt32 index); extern Rt2dMaestro * Rt2dMaestroAddStringLabel(Rt2dMaestro *maestro, - Rt2dStringLabelType entityType, RwChar *name, + Rt2dStringLabelType entityType, const RwChar *name, void *internalData, RwInt32 *index); extern const RwChar * @@ -985,28 +1036,28 @@ Rt2dMaestroGetStringLabelName(Rt2dMaestro *maestro, #if !(defined(RWDEBUG) || defined(RWSUPPRESSINLINE)) #define Rt2dStringLabelGetStringLabelType(_strLabel) \ - _rt2dStringLabelGetStringLabelTypeMacro((_strLabel)); + _rt2dStringLabelGetStringLabelTypeMacro((_strLabel)) #define Rt2dStringLabelSetStringLabelType(_strLabel, _entityType) \ - _rt2dStringLabelSetStringLabelTypeMacro((_strLabel), (_entityType)); + _rt2dStringLabelSetStringLabelTypeMacro((_strLabel), (_entityType)) #define Rt2dStringLabelGetNameIndex(_strLabel) \ - _rt2dStringLabelGetNameIndexMacro((_strLabel)); + _rt2dStringLabelGetNameIndexMacro((_strLabel)) #define Rt2dStringLabelSetNameIndex(_strLabel, _index) \ - _rt2dStringLabelSetNameIndexMacro((_strLabel), (_index)); + _rt2dStringLabelSetNameIndexMacro((_strLabel), (_index)) #define Rt2dStringLabelGetInternalData(_strLabel) \ - _rt2dStringLabelGetInternalDataMacro((_strLabel)); + _rt2dStringLabelGetInternalDataMacro((_strLabel)) #define Rt2dStringLabelSetInternalData(_strLabel, _internalData) \ - _rt2dStringLabelSetInternalDataMacro((_strLabel), (_internalData)); + _rt2dStringLabelSetInternalDataMacro((_strLabel), (_internalData)) #define Rt2dStringLabelGetUserData(_strLabel) \ - _rt2dStringLabelGetUserDataMacro((_strLabel)); + _rt2dStringLabelGetUserDataMacro((_strLabel)) #define Rt2dStringLabelSetUserData(_strLabel, _userData) \ - _rt2dStringLabelSetUserDataMacro((_strLabel), (_userData)); + _rt2dStringLabelSetUserDataMacro((_strLabel), (_userData)) #else /* !(defined(RWDEBUG) || defined(RWSUPPRESSINLINE)) */ diff --git a/rwsdk/include/d3d8/rt2danim.rpe b/rwsdk/include/d3d8/rt2danim.rpe index 82a9dac9..0e61ec5c 100644 --- a/rwsdk/include/d3d8/rt2danim.rpe +++ b/rwsdk/include/d3d8/rt2danim.rpe @@ -150,480 +150,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum rwPLUGIN_ERRENUM +enum e_rwdb_Criterion2DAnim { - rwPLUGIN_ERRENUMLAST = RWFORCEENUMSIZEINT + e_rwdb_Criterion2DAnimLAST = RWFORCEENUMSIZEINT }; -typedef enum rwPLUGIN_ERRENUM rwPLUGIN_ERRENUM; +typedef enum e_rwdb_Criterion2DAnim e_rwdb_Criterion2DAnim; diff --git a/rwsdk/include/d3d8/rtbary.h b/rwsdk/include/d3d8/rtbary.h index 61c39b07..2531914d 100644 --- a/rwsdk/include/d3d8/rtbary.h +++ b/rwsdk/include/d3d8/rtbary.h @@ -11,7 +11,7 @@ /** * \defgroup rtbary RtBary - * \ingroup rttool + * \ingroup mathtools * * Barycentric Toolkit for RenderWare. */ @@ -32,7 +32,7 @@ /** * \ingroup rtbary - * \typedef RtBaryV4d + * \ref RtBaryV4d * typedef for the 4 element homogeneous row of a transform matrix mapping * a point from Cartesian space to the barycentric space defined by a triangle. */ @@ -40,7 +40,7 @@ typedef RwReal RtBaryV4d[4]; /** * \ingroup rtbary - * \typedef RtBaryTransform + * \ref RtBaryTransform * typedef for the 4x4 homogeneous transform matrix mapping a point * from Cartesian space to the barycentric space defined by a triangle. */ diff --git a/rwsdk/include/d3d8/rtbary.rpe b/rwsdk/include/d3d8/rtbary.rpe index fdfe3afe..0fec6a77 100644 --- a/rwsdk/include/d3d8/rtbary.rpe +++ b/rwsdk/include/d3d8/rtbary.rpe @@ -145,472 +145,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtbezpat.h b/rwsdk/include/d3d8/rtbezpat.h index 8a5960cb..f25f5ce9 100644 --- a/rwsdk/include/d3d8/rtbezpat.h +++ b/rwsdk/include/d3d8/rtbezpat.h @@ -8,17 +8,12 @@ /** * \defgroup rtbezpatch RtBezPat - * \ingroup rttool + * \ingroup mathtools * * The Bezier Patch Toolkit is a group of functions that support the way * RenderWare processes patches. */ -/** - * \ingroup rtbezpatch - * \typedef RtBezierV4d - * typedef for struct RtBezierV4d. - */ typedef struct RtBezierV4d RtBezierV4d; /** @@ -42,7 +37,7 @@ struct RtBezierV4d /** * \ingroup rtbezpatch - * \typedef RtBezierRow + * \ref RtBezierRow * typedef for a row of vectors. * RtBezierRow is an array of 4 vectors */ @@ -50,7 +45,7 @@ typedef RtBezierV4d RtBezierRow[4]; /** * \ingroup rtbezpatch - * \typedef RtBezierMatrix + * \ref RtBezierMatrix * typedef for a matrix of 4*4 vectors. * RtBezierMatrix is an array of 4 rows. */ diff --git a/rwsdk/include/d3d8/rtbezpat.rpe b/rwsdk/include/d3d8/rtbezpat.rpe index e49b65b4..0f6dc700 100644 --- a/rwsdk/include/d3d8/rtbezpat.rpe +++ b/rwsdk/include/d3d8/rtbezpat.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtbmp.h b/rwsdk/include/d3d8/rtbmp.h index 37b5c97b..c3bb5c95 100644 --- a/rwsdk/include/d3d8/rtbmp.h +++ b/rwsdk/include/d3d8/rtbmp.h @@ -12,7 +12,7 @@ /** * \defgroup rtbmp RtBMP - * \ingroup rttool + * \ingroup imageconversiontools * * BMP Image Format Toolkit for RenderWare. * diff --git a/rwsdk/include/d3d8/rtbmp.rpe b/rwsdk/include/d3d8/rtbmp.rpe index 29dad089..37c546f9 100644 --- a/rwsdk/include/d3d8/rtbmp.rpe +++ b/rwsdk/include/d3d8/rtbmp.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtcharse.h b/rwsdk/include/d3d8/rtcharse.h index 4fdc2568..6c7a3902 100644 --- a/rwsdk/include/d3d8/rtcharse.h +++ b/rwsdk/include/d3d8/rtcharse.h @@ -16,7 +16,7 @@ /** * \defgroup rtcharset RtCharset - * \ingroup rttool + * \ingroup 2dtools * * Character Set/Foot Toolkit for RenderWare. */ @@ -61,7 +61,7 @@ struct RtCharsetDesc /** * \ingroup rtcharset - * \typedef RtCharset + * \ref RtCharset * typedef for a structure defining a character set (opaque). * \see RtCharsetCreate */ diff --git a/rwsdk/include/d3d8/rtcharse.rpe b/rwsdk/include/d3d8/rtcharse.rpe index 39c37312..30c5ff4d 100644 --- a/rwsdk/include/d3d8/rtcharse.rpe +++ b/rwsdk/include/d3d8/rtcharse.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtimport.h b/rwsdk/include/d3d8/rtimport.h index cf4e6283..2cc6383b 100644 --- a/rwsdk/include/d3d8/rtimport.h +++ b/rwsdk/include/d3d8/rtimport.h @@ -10,15 +10,15 @@ #define RTIMPORT_H /** - * \defgroup rtimport RtWorldImport - * \ingroup rttool + * \defgroup rtworldimport RtWorldImport + * \ingroup basicgeometry * - * World Import Toolkit for Renderware. + * World Import Toolkit for RenderWare. */ /** * \defgroup selectors RtWorldImportPartitionSelectors - * \ingroup rtimport + * \ingroup rtworldimport * * The set of provided RtWorldImportPartitionSelectors: * Selects a good partition by calling one of the @@ -29,7 +29,7 @@ /** * \defgroup iterators RtWorldImportPartitionIterators - * \ingroup rtimport + * \ingroup rtworldimport * * The set of provided RtWorldImportPartitionIterators: * Iterates through a set of candidate partitions, possibly @@ -39,7 +39,7 @@ /** * \defgroup evaluators RtWorldImportPartitionEvaluators - * \ingroup rtimport + * \ingroup rtworldimport * * The set of provided RtWorldImportPartitionEvaluators: * Uses a combination of statistics, build sector, build status, and @@ -51,7 +51,7 @@ /** * \defgroup terminators RtWorldImportPartitionTerminators - * \ingroup rtimport + * \ingroup rtworldimport * * The set of provided RtWorldImportPartitionTerminators: * Checks given criteria about the statistics, build sector, build status, and @@ -61,7 +61,7 @@ /** * \defgroup kd RtWorldImportGuideKD - * \ingroup rtimport + * \ingroup rtworldimport * * Tools to manipulate the \ref RtWorldImportGuideKDTree that is used to * manually build the sectors of a world. @@ -69,7 +69,7 @@ /** * \defgroup hints RtWorldImportHints - * \ingroup rtimport + * \ingroup rtworldimport * * Tools to aid the build process by giving hints as to what geometry should * not be split, and what geometry makes for a good partitioning guide. @@ -96,7 +96,7 @@ #define rtWORLDIMPORTPROGRESSBSPCOMPRESSEND 5 /** - * \ingroup rtimport + * \ingroup rtworldimport * \def rtWORLDIMPORTINVALIDPARTITION * * This value means that no partition was found, or that the partition was @@ -104,51 +104,61 @@ */ #define rtWORLDIMPORTINVALIDPARTITION RwRealMAXVAL +/* maintained in Bin-tree */ +#define CONGRUENTVERTEXCHILDREN 2 + +/* maintained in Quad-tree */ +#define WELDVERTEXCHILDREN 4 + /**************************************************************************** Global types */ - -/** - * Internal use only - */ -typedef union RtWorldImportVertexState RtWorldImportVertexState; - - -/** - * \ingroup rtimport - * \typedef RtWorldImportVertex - * - * typedef for struct \ref RtWorldImportVertex - */ +#if (!defined(DOXYGEN)) typedef struct RtWorldImportVertex RtWorldImportVertex; -/** - * \ingroup rtimport - * \typedef RtWorldImportWeldVertex - * - * typedef for struct \ref RtWorldImportWeldVertex - */ typedef struct RtWorldImportWeldVertex RtWorldImportWeldVertex; -/** - * \ingroup rtimport - * \typedef RtWorldImportBuildVertex - * - * typedef for struct \ref RtWorldImportBuildVertex - */ typedef struct RtWorldImportBuildVertex RtWorldImportBuildVertex; +/* Internal use only */ +typedef union RtWorldImportVertexState RtWorldImportVertexState; +/* Internal use only */ +union RtWorldImportVertexState +{ + /* clipFlags, two types, first is based on partition only, 2nd is + * also based on partition, but takes overlaps into consideration. i.e. + * number splits is usually higher in clipFlags[0] than [1] */ + RwInt32 clipFlags[2]; /* Internal use only */ + RwInt32 forwardingAddress; /* Internal use only */ + RtWorldImportVertex *vpVert; /* Internal use only */ + RtWorldImportWeldVertex *vpWeldVert; /* Internal use only */ + RtWorldImportBuildVertex *vpBuildVert; /* Internal use only */ + RwSList *slist; /* Internal use only */ +}; +#endif /* (!defined(DOXYGEN)) */ /** - * \ingroup rtimport - * \typedef RtWorldImportBuildPolyInfo + * \ingroup rtworldimport + * \struct RtWorldImportVertex + * Holds data for each vertex in the import world. * - * typedef for struct \ref RtWorldImportBuildPolyInfo */ +struct RtWorldImportVertex +{ + RwV3d OC; /**< World space vertex position */ + RwV3d normal; /**< World space vertex normal */ + RwRGBA preLitCol; /**< Vertex Prelight color */ + RwTexCoords texCoords[rwMAXTEXTURECOORDS]; + /**< Vertex texture coordinates */ + RtWorldImportVertexState state; /**< Internal use only */ + RwInt32 matIndex; /**< Vertex material index */ + void *pUserdata; /**< Pointer to unspecified per vertex user data */ +}; + typedef struct RtWorldImportBuildPolyInfo RtWorldImportBuildPolyInfo; /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildPolyInfo * * Information about a polygon @@ -167,7 +177,7 @@ struct RtWorldImportBuildPolyInfo typedef union RtWorldImportBuildVertexMode RtWorldImportBuildVertexMode; /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildVertexMode * * Mode of the vertex. @@ -182,7 +192,7 @@ union RtWorldImportBuildVertexMode }; /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildVertex * * A list of polygons as a list of vertices where the end of poly boundary @@ -198,30 +208,16 @@ struct RtWorldImportBuildVertex /**< we store some poly info in the end marker of a boundary */ }; - - -/** - * \ingroup rtimport - * \typedef RtWorldImportGuideKDTree - * - * typedef for struct \ref RtWorldImportGuideKDTree - */ -typedef struct RtWorldImportGuideKDTree RtWorldImportGuideKDTree; - /* NB Merged RtWorldImportPartition with RtWorldImportBuildClipStatistics because * there was a unique one-to-one relationship between them, and it made things easier * just updating one stucture, without having to update both in sequence... */ -/** - * \ingroup rtimport - * \typedef RtWorldImportBuildClipStatistics - * - * typedef for struct \ref RtWorldImportBuildClipStatistics - */ + typedef struct RtWorldImportBuildClipStatistics RtWorldImportBuildClipStatistics; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildClipStatistics * * Holds statistics about a partition or candidate partition during @@ -231,15 +227,15 @@ struct RtWorldImportBuildClipStatistics { RwInt32 numPotentialSplit; /**< The number of polygons split by the partition, - * disgregarding overlaps */ + * disregarding overlaps */ RwInt32 numPotentialLeft; /**< The number of potential polygons and fragments on the - * left of the partition, disgregarding overlaps */ + * left of the partition, disregarding overlaps */ RwInt32 numPotentialRight; /**< The number of potential polygons and fragments on the - * right of the partition, disgregarding overlaps */ + * right of the partition, disregarding overlaps */ RwInt32 numActualSplit; @@ -276,15 +272,13 @@ struct RtWorldImportBuildClipStatistics /**< The actual, relative size of the overlap on the right of the partition */ }; -/** - * \ingroup rtimport - * \typedef RtWorldImportPartition - * - * typedef for struct \ref RtWorldImportPartition +/* + * typedef for struct RtWorldImportPartition */ typedef struct RtWorldImportPartition RtWorldImportPartition; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportPartition * * A partitioning plane. @@ -311,8 +305,14 @@ struct RtWorldImportPartition /**< The statistics for the partition */ }; +/* + * typedef for struct \ref RtWorldImportGuideKDTree + */ +typedef struct RtWorldImportGuideKDTree RtWorldImportGuideKDTree; + + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportGuideKDTree * Represents the structure of a binary tree with * no contents per se. It is used to build a BSP in a user specified @@ -342,6 +342,7 @@ struct RtWorldImportGuideKDTree typedef struct _rtWorldImportGuideKDStackElement _rtWorldImportGuideKDStackElement; +#if (!defined(DOXYGEN)) struct _rtWorldImportGuideKDStackElement { RwBool terminal; @@ -357,16 +358,15 @@ struct _rtWorldImportGuideKDStack _rtWorldImportGuideKDStackElement *current; _rtWorldImportGuideKDStackElement *bottom; }; +#endif /* (!defined(DOXYGEN)) */ -/** - * \ingroup rtimport - * \typedef RtWorldImportBuildSector - * - * typedef for struct \ref RtWorldImportBuildSector +/* + * typedef for struct RtWorldImportBuildSector */ typedef struct RtWorldImportBuildSector RtWorldImportBuildSector; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildSector * * Holds information about the sector that is being subdivided @@ -401,15 +401,13 @@ struct RtWorldImportBuildSector /**< Maximum number of materials in the in the world */ }; -/** - * \ingroup rtimport - * \typedef RtWorldImportBuildStatus - * - * typedef for struct \ref RtWorldImportBuildStatus +/* + * typedef for struct RtWorldImportBuildStatus */ typedef struct RtWorldImportBuildStatus RtWorldImportBuildStatus; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildStatus * World Import Build Status Structure * Used to store the current tree's build status @@ -419,50 +417,41 @@ struct RtWorldImportBuildStatus RwInt32 depth; /**< current depth in the tree */ }; -/** - * Internal use only - */ -union RtWorldImportVertexState +typedef struct RwRGBAUInt32 RwRGBAUInt32; + +#if (!defined(DOXYGEN)) +struct RwRGBAUInt32 { - /* clipFlags, two types, first is based on partition only, 2nd is - * also based on partition, but takes overlaps into consideration. i.e. - * number splits is usually higher in clipFlags[0] than [1] */ - RwInt32 clipFlags[2]; /**< Internal use only */ - RwInt32 forwardingAddress; /**< Internal use only */ - RtWorldImportVertex *vpVert; /**< Internal use only */ - RtWorldImportWeldVertex *vpWeldVert; /**< Internal use only */ - RtWorldImportBuildVertex *vpBuildVert; /**< Internal use only */ - RwSList *slist; /**< Internal use only */ + RwUInt32 red, green, blue, alpha; }; -/** - * \ingroup rtimport - * \struct RtWorldImportVertex - * Holds data for each vertex in the import world. - * - */ -struct RtWorldImportVertex +typedef struct RtWorldImportCongruentVertex RtWorldImportCongruentVertex; + +struct RtWorldImportCongruentVertex { - RwV3d OC; /**< World space vertex position */ - RwV3d normal; /**< World space vertex normal */ - RwRGBA preLitCol; /**< Vertex Prelight color */ - RwTexCoords texCoords[rwMAXTEXTURECOORDS]; - /**< Vertex texture coordinates */ - RtWorldImportVertexState state; /**< Internal use only */ - RwInt32 matIndex; /**< Vertex material index */ - void *pUserdata; /**< Pointer to unspecified per vertex user data */ + RwInt32 destIdx; + RtWorldImportVertex vertex; + RtWorldImportVertex Mean; + RwRGBAUInt32 preLitMean; + RwInt32 refCount; + RtWorldImportCongruentVertex *child[CONGRUENTVERTEXCHILDREN]; }; -/** - * \ingroup rtimport - * \typedef RtWorldImportTriangle +struct RtWorldImportWeldVertex +{ + RtWorldImportVertex *sourcePtr; + RtWorldImportCongruentVertex *CongruentVertex; + RtWorldImportWeldVertex *child[WELDVERTEXCHILDREN]; +}; +#endif /* (!defined(DOXYGEN)) */ + +/* * Holds data for each triangle in the import world. - * - * \see RtWorldImportTriangle */ typedef struct RtWorldImportTriangle RtWorldImportTriangle; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportTriangle * Holds data for each triangle in the import world. * @@ -476,38 +465,69 @@ struct RtWorldImportTriangle }; + + +/* + * typedef for struct RtWorldImportBBoxHintDesc + */ +typedef struct RtWorldImportBBoxHintDesc RtWorldImportBBoxHintDesc; /** - * \ingroup rtimport - * \typedef RtWorldImportHints - * - * typedef for struct \ref RtWorldImportHints + * \ingroup rtworldimport + * \struct RtWorldImportBBoxHintDesc + * Bounding box hints and (priority) values used to control the world + * sectorization process. + */ +struct RtWorldImportBBoxHintDesc +{ + RwBBox bBox; /**< The (necessarily orthogonal) bounding box */ + RwReal value; /**< The value or priority of the hint (highest is most important) */ +}; + +/* + * typedef for struct RtWorldImportHints */ typedef struct RtWorldImportHints RtWorldImportHints; /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportHints * Bounding box hints used to control the world sectorization process. * \see RtWorldImportHintsSet */ struct RtWorldImportHints { - /** The bounding box hints */ - RwBBox *boundingBoxes; - /** The number of bounding box hints */ - RwInt32 numBoundingBoxes; + RtWorldImportBBoxHintDesc *boundingBoxes; /**< The bounding box hints */ + RwInt32 numBoundingBoxes; /**< The number of bounding box hints */ }; + /** - * \ingroup rtimport - * \typedef RtWorldImportParameters + * \ingroup rtworldimport + * \ref RtWorldImportHintGroup * + * An enumeration that can be passed to + * \ref RtWorldImportHintsSetGroup and \ref RtWorldImportHintsGetGroup to determine + * whether hints will contribute towards the shield hint group or partition hint group + */ +typedef enum +{ + rtWORLDIMPORTSHIELDHINT = 0, + rtWORLDIMPORTPARTITIONHINT, + + rtWORLDIMPORTFORCEENUMSIZEINT = RWFORCEENUMSIZEINT +} +RtWorldImportHintGroup; + + + + +/* * typedef for struct \ref RtWorldImportParameters */ typedef struct RtWorldImportParameters RtWorldImportParameters; /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportParameters * Parameters used with \ref RtWorldImportCreateWorld. * They are initialized to default values using \ref RtWorldImportParametersInit. @@ -563,15 +583,13 @@ struct RtWorldImportParameters /**< If TRUE the world will be checked for validity during the build process. */ }; -/** - * \ingroup rtimport - * \typedef RtWorldImport - * - * typedef for struct \ref RtWorldImport +/* + * typedef for struct RtWorldImport */ typedef struct RtWorldImport RtWorldImport; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImport * World Import State Structure */ @@ -583,14 +601,10 @@ struct RtWorldImport RtWorldImportTriangle *polygons; /**< Triangle array */ RwInt32 numPolygons; /**< Triangle count */ - - - RwSurfaceProperties surfaceProps; /**< The world's surface - lighting properties */ }; /** - * \ingroup rtimport + * \ingroup rtworldimport * \ref RtWorldImportProgressCallBack is the type for the callback function supplied to * \ref RtWorldImportSetProgressCallBack. * @@ -626,65 +640,102 @@ struct RtWorldImport typedef RwBool (*RtWorldImportProgressCallBack)(RwInt32 msg, RwReal value); /** - * \ingroup rtimport - * \typedef RtWorldImportDestroyVertexUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportDestroyVertexUserdataCallBack * * A pointer to the CallBack function that will be called during * vertex destruction. + * + * \param pUserdata + * + * \return */ typedef RwBool (*RtWorldImportDestroyVertexUserdataCallBack)(void **pUserdata); /** - * \ingroup rtimport - * \typedef RtWorldImportCloneVertexUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportCloneVertexUserdataCallBack * * A pointer to the CallBack function that will be called during * vertex cloning. + * + * \param pUserdataDst + * \param pUserdataSrc + * + * \return */ typedef RwBool (*RtWorldImportCloneVertexUserdataCallBack)(void **pUserdataDst, void **pUserdataSrc); /** - * \ingroup rtimport - * \typedef RtWorldImportInterpVertexUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportInterpVertexUserdataCallBack * * A pointer to the CallBack function that will be called during * vertex interpolation. + * + * \param pUserdataDst + * \param pUserdata1 + * \param pUserdata2 + * \param delta + * + * \return */ typedef RwBool (*RtWorldImportInterpVertexUserdataCallBack)(void **pUserdataDst, void **pUserdata1, void **pUserdata2, RwReal delta); /** - * \ingroup rtimport - * \typedef RtWorldImportDestroyPolygonUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportDestroyPolygonUserdataCallBack * * A pointer to the CallBack function that will be called during * polygon destruction. + * + * \param pUserdata + * + * \return */ typedef RwBool (*RtWorldImportDestroyPolygonUserdataCallBack)(void **pUserdata); /** - * \ingroup rtimport - * \typedef RtWorldImportSplitPolygonUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportSplitPolygonUserdataCallBack * * A pointer to the CallBack function that will be called during * polygon division. + * + * \param pUserdataDst + * \param pUserdataSrc + * + * \return */ typedef RwBool (*RtWorldImportSplitPolygonUserdataCallBack)(void **pUserdataDst, void **pUserdataSrc); /** - * \ingroup rtimport - * \typedef RtWorldImportSectorSetVertexUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportSectorSetVertexUserdataCallBack * * A pointer to the CallBack function that will be called during * the setting of the vertex user data. + * + * \param pUserdata + * \param sector + * \param index + * + * \return */ typedef RwBool (*RtWorldImportSectorSetVertexUserdataCallBack)(void **pUserdata, RpWorldSector *sector, RwInt32 index); /** - * \ingroup rtimport - * \typedef RtWorldImportSectorSetPolygonUserdataCallBack + * \ingroup rtworldimport + * \ref RtWorldImportSectorSetPolygonUserdataCallBack * * A pointer to the CallBack function that will be called during * the setting of the polygon user data. + * + * \param pUserdata + * \param sector + * \param index + * + * \return */ typedef RwBool (*RtWorldImportSectorSetPolygonUserdataCallBack)(void **pUserdata, RpWorldSector *sector, RwInt32 index); @@ -692,12 +743,18 @@ typedef RwBool (*RtWorldImportSectorSetPolygonUserdataCallBack)(void **pUserdata /** - * \ingroup rtimport - * \typedef RtWorldImportTerminationBuildCallBack + * \ingroup rtworldimport + * \ref RtWorldImportTerminationBuildCallBack * * A pointer to the function that will be called during the * build process to determine whether the current sector should * be subdivided further, or terminated. + * + * \param buildSector + * \param buildStatus + * \param pData + * + * \return */ typedef RwBool (*RtWorldImportTerminationBuildCallBack) (RtWorldImportBuildSector *buildSector, @@ -705,11 +762,17 @@ typedef RwBool (*RtWorldImportTerminationBuildCallBack) void *pData); /** - * \ingroup rtimport - * \typedef RtWorldImportPartitionBuildCallBack + * \ingroup rtworldimport + * \ref RtWorldImportPartitionBuildCallBack * * A pointer to the function that will be called during the * build process to select a suitable sector partition. + * + * \param buildSector + * \param buildStatus + * \param partition + * + * \return */ typedef RwReal (*RtWorldImportPartitionBuildCallBack) (RtWorldImportBuildSector *buildSector, @@ -717,15 +780,13 @@ typedef RwReal (*RtWorldImportPartitionBuildCallBack) RtWorldImportPartition *partition, void *pData); -/** - * \ingroup rtimport - * \typedef RtWorldImportBuildCallBacks - * +/* * typedef for struct \ref RtWorldImportBuildCallBacks */ typedef struct RtWorldImportBuildCallBacks RtWorldImportBuildCallBacks; /* MAYBE: rename to SectorCallBacks ?*/ + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportBuildCallBacks * Sectorization callbacks */ @@ -741,15 +802,13 @@ struct RtWorldImportBuildCallBacks /**< Termination callback user data */ }; -/** - * \ingroup rtimport - * \typedef RtWorldImportUserdataCallBacks - * +/* * typedef for struct \ref RtWorldImportUserdataCallBacks */ typedef struct RtWorldImportUserdataCallBacks RtWorldImportUserdataCallBacks; + /** - * \ingroup rtimport + * \ingroup rtworldimport * \struct RtWorldImportUserdataCallBacks * Bundle of callbacks */ @@ -772,8 +831,8 @@ struct RtWorldImportUserdataCallBacks }; /** - * \ingroup rtimport - * \typedef RtWorldImportBuildPartitionSelector + * \ingroup rtworldimport + * \ref RtWorldImportBuildPartitionSelector * * An enumeration that can be passed to * \ref RtWorldImportSetStandardBuildPartitionSelector to determine @@ -821,8 +880,6 @@ extern "C" extern RwBool _rtImportBuildSectorFindBBox(RtWorldImportBuildSector *buildSector, RwBBox *bbpOut); -/* TODO: decide where these scheme functions are going and which ones are public and - whether _rt or RT should be used */ extern void _rtWorldImportGuideKDCopy(RtWorldImportGuideKDTree *KD, RpSector *spSector, RwInt32 depth); extern void _rtWorldImportGuideKDStackDestroy(_rtWorldImportGuideKDStack *stack); @@ -862,6 +919,12 @@ RtWorldImportMaterialSeparatePartitionSelector(RtWorldImportBuildSector *buildSe RtWorldImportBuildStatus *buildStatus, RtWorldImportPartition *partition, void *userData); +extern RwReal +RtWorldImportPartitionHintPartitionSelector(RtWorldImportBuildSector *buildSector, + RtWorldImportBuildStatus *buildStatus, + RtWorldImportPartition *partition, + void * __RWUNUSED__ userData); + extern RwReal RtWorldImportMaximumOccluderPartitionSelector(RtWorldImportBuildSector *buildSector, @@ -1109,14 +1172,13 @@ RtWorldImportSectorAspectSizePartitionTerminator(RtWorldImportBuildSector * buil -/* END TODO */ /* WorldImport hints */ extern void -RtWorldImportHintsSet(RtWorldImportHints *hints); +RtWorldImportHintsSetGroup(RtWorldImportHints *hints, RtWorldImportHintGroup group); extern RtWorldImportHints * -RtWorldImportHintsGet(void); +RtWorldImportHintsGetGroup(RtWorldImportHintGroup group); extern RtWorldImportHints * RtWorldImportHintsCreate(void); @@ -1175,14 +1237,6 @@ extern RwInt32 RtWorldImportGetNumTriangles(RtWorldImport * nohsworld); extern RtWorldImportTriangle * RtWorldImportGetTriangles(RtWorldImport * nohsworld); -/* Surface lighting characteristics */ -extern RtWorldImport * -RtWorldImportSetSurfaceProperties(RtWorldImport * world, - RwSurfaceProperties * - surface); - -extern RwSurfaceProperties * -RtWorldImportGetSurfaceProperties(RtWorldImport * world); /* Progress callbacks */ extern void @@ -1254,6 +1308,12 @@ RtWorldImportSetStandardBuildPartitionSelector(RtWorldImportBuildPartitionSelect #define RtWorldImportParametersInitialize(_paramsPtr) \ *(_paramsPtr) = *RtWorldImportParametersInit(); +/* Back compatibility with former hints which only permitted type zero (shield) hints... */ +#define RtWorldImportHintsSet(_hints) \ +RtWorldImportHintsSetGroup(_hints, rtWORLDIMPORTSHIELDHINT); + +#define RtWorldImportHintsGet() \ +RtWorldImportHintsGetGroup(rtWORLDIMPORTSHIELDHINT); #endif /* RTIMPORT_H */ diff --git a/rwsdk/include/d3d8/rtimport.rpe b/rwsdk/include/d3d8/rtimport.rpe index d4b7ad2b..ff8d3d5c 100644 --- a/rwsdk/include/d3d8/rtimport.rpe +++ b/rwsdk/include/d3d8/rtimport.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtintel.h b/rwsdk/include/d3d8/rtintel.h deleted file mode 100644 index c11329df..00000000 --- a/rwsdk/include/d3d8/rtintel.h +++ /dev/null @@ -1,1206 +0,0 @@ -/** - * Intel specific support toolkit - */ - -/********************************************************************** - * - * File : rtintel.h - * - * Abstract : Intel specific support/emulation - * - ********************************************************************** - * - * This file is a product of Criterion Software Ltd. - * - * This file is provided as is with no warranties of any kind and is - * provided without any obligation on Criterion Software Ltd. or - * Canon Inc. to assist in its use or modification. - * - * Criterion Software Ltd. will not, under any - * circumstances, be liable for any lost revenue or other damages arising - * from the use of this file. - * - * Copyright (c) 1998 Criterion Software Ltd. - * All Rights Reserved. - * - * RenderWare is a trademark of Canon Inc. - * - ************************************************************************/ - -#ifndef RTINTEL_H -#define RTINTEL_H - -/** - * \defgroup rtintel RtIntel - * \ingroup rttool - * - * Intel CPU Toolkit for RenderWare. - */ - -/**************************************************************************** - Include files - */ - -/* - * Pick up - * typedef struct _rwResEntryTag RwResEntry; - * from baresour.h (internal) / rwcore.h (external) - */ - -/**************************************************************************** - Global Types - */ - -#include "rtintel.rpe" /* automatically generated header file */ - -#if (!defined(RW_FIXED_64)) -typedef struct RwFixed64 RwFixed64; -struct RwFixed64 -{ - RwInt32 msb; - RwUInt32 lsb; -}; - -#define RW_FIXED_64 -#endif /* (!defined(RW_FIXED_64)) */ - -#define doubleFromRwFixed64(x) \ - ( ((double)((x).msb))*((double)(1<<16))*((double)(1<<16)) \ - + ((double)((x).lsb)) ) - -#if (!defined(RPINTELTIMEFUNCTION)) -typedef RwBool(*RtIntelTimeFunction) (void *data); - -#define RPINTELTIMEFUNCTION -#endif /* (!defined(RPINTELTIMEFUNCTION)) */ - -typedef struct RtIntelOverload RtIntelOverload; - -typedef void (*RwTransformFunction) (RwResEntry * repEntry); - -struct RtIntelOverload -{ - rwMatrixMultFn MatrixMultiplyFunction; - rwVectorMultFn VectorMultPointFunction; - rwVectorMultFn VectorMultVectorFunction; - RwTransformFunction TransformFunction; -}; - -#if (defined(__ICL)) -#define DEFINED__ICL " __ICL" -#define UNDEFINED__ICL "" -#else /* (defined(__ICL)) */ -#define DEFINED__ICL "" -#define UNDEFINED__ICL " __ICL" -#endif /* (defined(__ICL)) */ - -#if (defined(_MSC_VER)) - -# pragma comment ( user, "comment:" __FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : " "DEFINED " DEFINED__ICL " ; UNDEFINED " UNDEFINED__ICL ) -/* # pragma message (__FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : " "DEFINED " DEFINED__ICL " ; UNDEFINED " UNDEFINED__ICL ) */ -/* # pragma comment ( user, "comment:" __FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : " "DEFINED " DEFINED__ICL " ; UNDEFINED " UNDEFINED__ICL ) */ -#if (! (defined(__ICL) || defined(XBOX_DRVMODEL_H)) ) -#pragma message (__DATE__ " " __TIME__ " " __FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : No MMX intrinsics - defaulting to software emulation") -#pragma message (__DATE__ " " __TIME__ " " __FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : No SSE intrinsics - defaulting to software emulation") -#pragma comment ( user, "comment:" __FILE__ "(" RW_STRINGIFY_EXPANDED(__LINE__) ") : No MMX intrinsics - defaulting to software emulation") -#endif /* (! (defined(__ICL) || defined(XBOX_DRVMODEL_H)) ) */ -#endif /* (defined(_MSC_VER)) */ - -/* - * MMX - */ - -#if (defined(__ICL)) - -#if (!defined(MMINTRIN_H)) -#include "mmintrin.h" -#define MMINTRIN_H -#endif /* (!defined(MMINTRIN_H)) */ - -#else /* (defined(__ICL)) */ - -#if (defined(_MSC_VER)) - -#if (!defined(__M64)) -typedef __int64 Rt_m64; - -#define __M64 -#endif /* (!defined(__M64)) */ - -#else /* (defined(_MSC_VER)) -- e.g. __GNUC__ */ - -#if (!defined(__M64)) - -typedef RwInt64 Rt_m64; - -#define __M64 - -#endif /* (!defined(__M64)) */ - -#endif /* (defined(_MSC_VER)) */ - -#endif /* (defined(__ICL)) */ - -/* - * SSE - */ - -/* - * From - * ccomp.pdf - * 12 Intel C/C++ Compiler User's Guide - * for Win32 Systems With Katmai New Instruction Support - * -------------------------------------------------------- - * Functionality Intrinsics Usage - * You need only define one preprocessor symbol and include the header file - * xmmintrin.h in your application to use the following functionality - * intrinsics: - * #define _MM_FUNCTIONALITY - * #include "xmmintrin.h" - * To encourage the compiler to inline the functionality intrinsic functions for - * better performance, consider using the -Qip and -Qipo compiler switches. - */ - -#if (defined(__ICL)) - -/* #define _MM2_FUNCTIONALITY */ - -/* #define _MM_FUNCTIONALITY */ - -/* #define _MM_NO_ABORT */ - -/* #define _MM_NO_ACCURACY */ - -/* #define _MM_NO_ALIGN_CHECK */ - -/* #define _MM_NO_INLINE */ - -/* - * Undefine "or", since this is valid assembler; e.g. in - * SDK10/include/xmm_func.h - * _asm { - * push eax - * fld f - * fstcw saved_cw - * mov eax, saved_cw - * or eax, 3072 - * mov new_cw, eax - * fldcw new_cw - * fistp ret - * fldcw saved_cw - * pop eax - * } - */ - -#if (!defined(XMMINTRIN_H)) -#include "xmmintrin.h" -#define XMMINTRIN_H -#endif /* (!defined(XMMINTRIN_H)) */ - -typedef __m64 Rt_m64; -typedef __m128 Rt_m128; - -#if (450 <= __ICL) -#if (!defined(EMMINTRIN_H)) -#include "emmintrin.h" -#define EMMINTRIN_H -typedef __m128d Rt_m128d; -typedef __m128i Rt_m128i; -#endif /* (!defined(EMMINTRIN_H)) */ -#else /* (450 <= __ICL) */ -typedef __m128 Rt_m128d; -typedef __m128 Rt_m128i; -#endif /* (450 <= __ICL) */ - -/* - * Report SSE options as compiler messages and object file comments - */ - -#ifdef _MM2_FUNCTIONALITY -#define DEFINED__MM2_FUNCTIONALITY " _MM2_FUNCTIONALITY" -#define UNDEFINED__MM2_FUNCTIONALITY "" -#else /* _MM2_FUNCTIONALITY */ -#define DEFINED__MM2_FUNCTIONALITY "" -#define UNDEFINED__MM2_FUNCTIONALITY " _MM2_FUNCTIONALITY" -#endif /* _MM2_FUNCTIONALITY */ - -#ifdef _MM_FUNCTIONALITY -#define DEFINED__MM_FUNCTIONALITY DEFINED__MM2_FUNCTIONALITY ## " _MM_FUNCTIONALITY" -#define UNDEFINED__MM_FUNCTIONALITY UNDEFINED__MM2_FUNCTIONALITY -#else /* _MM_FUNCTIONALITY */ -#define DEFINED__MM_FUNCTIONALITY DEFINED__MM2_FUNCTIONALITY -#define UNDEFINED__MM_FUNCTIONALITY UNDEFINED__MM2_FUNCTIONALITY ## " _MM_FUNCTIONALITY" -#endif /* _MM_FUNCTIONALITY */ - -#ifdef _MM_NO_ABORT -#define DEFINED__MM_NO_ABORT DEFINED__MM_FUNCTIONALITY ## " _MM_NO_ABORT" -#define UNDEFINED__MM_NO_ABORT UNDEFINED__MM_FUNCTIONALITY -#else /* _MM_NO_ABORT */ -#define DEFINED__MM_NO_ABORT DEFINED__MM_FUNCTIONALITY -#define UNDEFINED__MM_NO_ABORT UNDEFINED__MM_FUNCTIONALITY ## " _MM_NO_ABORT" -#endif /* _MM_NO_ABORT */ - -#ifdef _MM_NO_ACCURACY -#define DEFINED__MM_NO_ACCURACY DEFINED__MM_NO_ABORT ## " _MM_NO_ACCURACY" -#define UNDEFINED__MM_NO_ACCURACY UNDEFINED__MM_NO_ABORT -#else /* _MM_NO_ACCURACY */ -#define DEFINED__MM_NO_ACCURACY DEFINED__MM_NO_ABORT -#define UNDEFINED__MM_NO_ACCURACY UNDEFINED__MM_NO_ABORT ## " _MM_NO_ACCURACY" -#endif /* _MM_NO_ACCURACY */ - -#ifdef _MM_NO_ALIGN_CHECK -#define DEFINED__MM_NO_ALIGN_CHECK DEFINED__MM_NO_ACCURACY ## " _MM_NO_ALIGN_CHECK" -#define UNDEFINED__MM_NO_ALIGN_CHECK UNDEFINED__MM_NO_ACCURACY -#else /* _MM_NO_ALIGN_CHECK */ -#define DEFINED__MM_NO_ALIGN_CHECK DEFINED__MM_NO_ACCURACY -#define UNDEFINED__MM_NO_ALIGN_CHECK UNDEFINED__MM_NO_ACCURACY ## " _MM_NO_ALIGN_CHECK" -#endif /* _MM_NO_ALIGN_CHECK */ - -#ifdef _MM_NO_INLINE -#define DEFINED__MM_NO_INLINE DEFINED__MM_NO_ALIGN_CHECK ## " _MM_NO_INLINE" -#define UNDEFINED__MM_NO_INLINE UNDEFINED__MM_NO_ALIGN_CHECK -#else /* _MM_NO_INLINE */ -#define DEFINED__MM_NO_INLINE DEFINED__MM_NO_ALIGN_CHECK -#define UNDEFINED__MM_NO_INLINE UNDEFINED__MM_NO_ALIGN_CHECK ## " _MM_NO_INLINE" -#endif /* _MM_NO_INLINE */ - -#pragma comment ( user, "comment:" __DATE__" " __TIME__ " - " __FILE__ ":" RW_STRINGIFY_EXPANDED(__LINE__) ) -#pragma comment ( user, "comment:" "DEFINED :" DEFINED__MM_NO_INLINE ) -#pragma comment ( user, "comment:" "UNDEFINED:" UNDEFINED__MM_NO_INLINE ) - -#pragma message (__DATE__" " __TIME__ " - " __FILE__ ":" RW_STRINGIFY_EXPANDED(__LINE__) ) -#pragma message ("DEFINED :" DEFINED__MM_NO_INLINE ) -#pragma message ("UNDEFINED:" UNDEFINED__MM_NO_INLINE ) - -#else /* (defined(__ICL)) */ - -#define _MM_HINT_T0 1 -#define _MM_HINT_T1 2 -#define _MM_HINT_T2 3 -#define _MM_HINT_NTA 0 - -#if (defined(__R5900__)) -typedef RwInt128 Rt_m128; -#else /* (defined(__R5900__)) */ -#if (!defined(_PAIR__M64)) -struct Rt_m128 -{ - Rt_m64 lo; - Rt_m64 hi; -}; -#define _PAIR__M64 -typedef struct Rt_m128 Rt_m128; -#endif /* (!defined(_PAIR__M64)) */ -#endif /* (defined(__R5900__)) */ - -typedef Rt_m128 Rt_m128d; -typedef Rt_m128 Rt_m128i; -#endif /* (defined(__ICL)) */ - -typedef struct RtIntelV4d RtIntelV4d; -struct RtIntelV4d -{ - RwReal w; - RwV3d v3d; -}; - -typedef union _RpSSEOverlayM128 RpSSEOverlayM128; - -union _RpSSEOverlayM128 -{ - float _f[4]; - RwInt32 _d[4]; - RwUInt32 ud[4]; - RwInt16 _w[8]; - RwUInt16 uw[8]; - RwInt8 _b[16]; - RwUInt8 ub[16]; - Rt_m64 m64[2]; - Rt_m128 m128; - RtIntelV4d v4d; - RwSplitBits bits[4]; -}; - -typedef RpSSEOverlayM128 RpWNIOverlayM128; - -typedef union _RpWNIOverlayM128d RpWNIOverlayM128d; - -union _RpWNIOverlayM128d -{ - double df[2]; - float _f[4]; - RwInt32 _d[4]; - RwUInt32 ud[4]; - RwInt16 _w[8]; - RwUInt16 uw[8]; - RwInt8 _b[16]; - RwUInt8 ub[16]; - Rt_m64 m64[2]; - Rt_m128d m128d; - RtIntelV4d v4d; - RwSplitBits bits[4]; -}; - -typedef union _RpWNIOverlayM128i RpWNIOverlayM128i; - -union _RpWNIOverlayM128i -{ - double df[2]; - float _f[4]; - RwInt32 _d[4]; - RwUInt32 ud[4]; - RwInt16 _w[8]; - RwUInt16 uw[8]; - RwInt8 _b[16]; - RwUInt8 ub[16]; - Rt_m64 m64[2]; - Rt_m128i m128i; - RtIntelV4d v4d; - RwSplitBits bits[4]; -}; - -#define RWUNALIGNED16BYTE(ptr) (0x0000000FUL & ((RwUInt32)(ptr))) - -/*--- Plugin API Functions ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* - * MMX - */ - -/* General support intrinsics */ -extern void Rt_m_empty(void); -extern Rt_m64 Rt_m_from_int(int i); -extern int Rt_m_to_int(Rt_m64 m); -extern Rt_m64 Rt_m_packsswb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_packssdw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_packuswb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpckhbw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpckhwd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpckhdq(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpcklbw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpcklwd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_punpckldq(Rt_m64 m1, Rt_m64 m2); - -/* Packed arithmetic intrinsics */ -extern Rt_m64 Rt_m_paddb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddsb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddsw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddusb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_paddusw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubsb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubsw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubusb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_psubusw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pmaddwd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pmulhw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pmullw(Rt_m64 m1, Rt_m64 m2); - -/* Shift intrinsics */ -extern Rt_m64 Rt_m_psllw(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psllwi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_pslld(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_pslldi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psllq(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psllqi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psraw(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psrawi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psrad(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psradi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psrlw(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psrlwi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psrld(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psrldi(Rt_m64 m, int count); -extern Rt_m64 Rt_m_psrlq(Rt_m64 m, Rt_m64 count); -extern Rt_m64 Rt_m_psrlqi(Rt_m64 m, int count); - -/* Logical intrinsics */ -extern Rt_m64 Rt_m_pand(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pandn(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_por(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pxor(Rt_m64 m1, Rt_m64 m2); - -/* Comparision intrinsics */ -extern Rt_m64 Rt_m_pcmpeqb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pcmpeqw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pcmpeqd(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pcmpgtb(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pcmpgtw(Rt_m64 m1, Rt_m64 m2); -extern Rt_m64 Rt_m_pcmpgtd(Rt_m64 m1, Rt_m64 m2); - -/* - * SSE - */ - -/* - * Arithmetic Operations - */ - -extern Rt_m128 Rt_mm_add_ss(Rt_m128 a, Rt_m128 b) /* ADDSS */ ; -extern Rt_m128 Rt_mm_add_ps(Rt_m128 a, Rt_m128 b) /* ADDPS */ ; -extern Rt_m128 Rt_mm_sub_ss(Rt_m128 a, Rt_m128 b) /* SUBSS */ ; -extern Rt_m128 Rt_mm_sub_ps(Rt_m128 a, Rt_m128 b) /* SUBPS */ ; -extern Rt_m128 Rt_mm_mul_ss(Rt_m128 a, Rt_m128 b) /* MULSS */ ; -extern Rt_m128 Rt_mm_mul_ps(Rt_m128 a, Rt_m128 b) /* MULPS */ ; -extern Rt_m128 Rt_mm_div_ss(Rt_m128 a, Rt_m128 b) /* DIVSS */ ; -extern Rt_m128 Rt_mm_div_ps(Rt_m128 a, Rt_m128 b) /* DIVPS */ ; -extern Rt_m128 Rt_mm_sqrt_ss(Rt_m128 a) /* SQRTSS */ ; -extern Rt_m128 Rt_mm_sqrt_ps(Rt_m128 a) /* SQRTPS */ ; -extern Rt_m128 Rt_mm_rcp_ss(Rt_m128 a) /* RCPSS */ ; -extern Rt_m128 Rt_mm_rcp_ps(Rt_m128 a) /* RCPPS */ ; -extern Rt_m128 Rt_mm_rsqrt_ss(Rt_m128 a) /* RSQRTSS */ ; -extern Rt_m128 Rt_mm_rsqrt_ps(Rt_m128 a) /* RSQRTPS */ ; -extern Rt_m128 Rt_mm_min_ss(Rt_m128 a, Rt_m128 b) /* MINSS */ ; -extern Rt_m128 Rt_mm_min_ps(Rt_m128 a, Rt_m128 b) /* MINPS */ ; -extern Rt_m128 Rt_mm_max_ss(Rt_m128 a, Rt_m128 b) /* MAXSS */ ; -extern Rt_m128 Rt_mm_max_ps(Rt_m128 a, Rt_m128 b) /* MAXPS */ ; - -/* - * Logical Operations - */ - -extern Rt_m128 Rt_mm_and_ps(Rt_m128 a, Rt_m128 b) /* ANDPS */ ; -extern Rt_m128 Rt_mm_andnot_ps(Rt_m128 a, - Rt_m128 b) /* ANDNPS */ ; -extern Rt_m128 Rt_mm_or_ps(Rt_m128 a, Rt_m128 b) /* ORPS */ ; -extern Rt_m128 Rt_mm_xor_ps(Rt_m128 a, Rt_m128 b) /* XORPS */ ; - -/* - * Comparisons - */ - -extern Rt_m128 Rt_mm_cmpeq_ss(Rt_m128 a, - Rt_m128 b) /* CMPEQSS */ ; -extern Rt_m128 Rt_mm_cmpeq_ps(Rt_m128 a, - Rt_m128 b) /* CMPEQPS */ ; -extern Rt_m128 Rt_mm_cmplt_ss(Rt_m128 a, - Rt_m128 b) /* CMPLTSS */ ; -extern Rt_m128 Rt_mm_cmplt_ps(Rt_m128 a, - Rt_m128 b) /* CMPLTPS */ ; -extern Rt_m128 Rt_mm_cmple_ss(Rt_m128 a, - Rt_m128 b) /* CMPLESS */ ; -extern Rt_m128 Rt_mm_cmple_ps(Rt_m128 a, - Rt_m128 b) /* CMPLEPS */ ; -extern Rt_m128 Rt_mm_cmpgt_ss(Rt_m128 a, Rt_m128 b) /* CMPLTSS r */ - ; -extern Rt_m128 Rt_mm_cmpgt_ps(Rt_m128 a, Rt_m128 b) /* CMPLTPS r */ - ; -extern Rt_m128 Rt_mm_cmpge_ss(Rt_m128 a, Rt_m128 b) /* CMPLESS r */ - ; -extern Rt_m128 Rt_mm_cmpge_ps(Rt_m128 a, Rt_m128 b) /* CMPLEPS r */ - ; -extern Rt_m128 Rt_mm_cmpneq_ss(Rt_m128 a, - Rt_m128 b) /* CMPNEQSS */ ; -extern Rt_m128 Rt_mm_cmpneq_ps(Rt_m128 a, - Rt_m128 b) /* CMPNEQPS */ ; -extern Rt_m128 Rt_mm_cmpnlt_ss(Rt_m128 a, - Rt_m128 b) /* CMPNLTSS */ ; -extern Rt_m128 Rt_mm_cmpnlt_ps(Rt_m128 a, - Rt_m128 b) /* CMPNLTPS */ ; -extern Rt_m128 Rt_mm_cmpnle_ss(Rt_m128 a, - Rt_m128 b) /* CMPNLESS */ ; -extern Rt_m128 Rt_mm_cmpnle_ps(Rt_m128 a, - Rt_m128 b) /* CMPNLEPS */ ; -extern Rt_m128 Rt_mm_cmpngt_ss(Rt_m128 a, Rt_m128 b) - /* CMPNLTSS r */ ; -extern Rt_m128 Rt_mm_cmpngt_ps(Rt_m128 a, Rt_m128 b) - /* CMPNLTPS r */ ; -extern Rt_m128 Rt_mm_cmpnge_ss(Rt_m128 a, Rt_m128 b) - /* CMPNLESS r */ ; -extern Rt_m128 Rt_mm_cmpnge_ps(Rt_m128 a, Rt_m128 b) - /* CMPNLEPS r */ ; -extern Rt_m128 Rt_mm_cmpord_ss(Rt_m128 a, - Rt_m128 b) /* CMPORDSS */ ; -extern Rt_m128 Rt_mm_cmpord_ps(Rt_m128 a, - Rt_m128 b) /* CMPORDPS */ ; -extern Rt_m128 Rt_mm_cmpunord_ss(Rt_m128 a, - Rt_m128 b) /* CMPUNORDSS */ ; -extern Rt_m128 Rt_mm_cmpunord_ps(Rt_m128 a, - Rt_m128 b) /* CMPUNORDPS */ ; -extern int Rt_mm_comieq_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_comilt_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_comile_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_comigt_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_comige_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_comineq_ss(Rt_m128 a, - Rt_m128 b) /* COMISS */ ; -extern int Rt_mm_ucomieq_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; -extern int Rt_mm_ucomilt_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; -extern int Rt_mm_ucomile_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; -extern int Rt_mm_ucomigt_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; -extern int Rt_mm_ucomige_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; -extern int Rt_mm_ucomineq_ss(Rt_m128 a, - Rt_m128 b) /* UCOMISS */ ; - -/* - * Conversion Operations - */ - -extern int Rt_mm_cvt_ss2si(Rt_m128 a) /* CVTSS2SI */ ; -extern Rt_m64 Rt_mm_cvt_ps2pi(Rt_m128 a) /* CVTPS2PI */ ; -extern int Rt_mm_cvtt_ss2si(Rt_m128 a) /* CVTTSS2SI */ ; -extern Rt_m64 Rt_mm_cvtt_ps2pi(Rt_m128 a) /* CVTTPS2PI */ ; -extern Rt_m128 Rt_mm_cvt_si2ss(Rt_m128 a, - int b) /* CVTSI2SS */ ; -extern Rt_m128 Rt_mm_cvt_pi2ps(Rt_m128 a, - Rt_m64 b) /* CVTPI2PS */ ; - -/* - * Miscellaneous - */ - -extern Rt_m128 Rt_mm_shuffle_ps(Rt_m128 a, Rt_m128 b, - int i) /* SHUFPS */ ; -extern Rt_m128 Rt_mm_unpackhi_ps(Rt_m128 a, - Rt_m128 b) /* UNPCKHPS */ ; -extern Rt_m128 Rt_mm_unpacklo_ps(Rt_m128 a, - Rt_m128 b) /* UNPCKLPS */ ; -extern Rt_m128 Rt_mm_loadh_pi(Rt_m128 a, Rt_m64 * p) /* MOVHPS reg, mem */ - ; -extern void Rt_mm_storeh_pi(Rt_m64 * p, Rt_m128 a) /* MOVHPS mem, reg */ - ; -extern Rt_m128 Rt_mm_movehl_ps(Rt_m128 a, - Rt_m128 b) /* MOVHLPS */ ; -extern Rt_m128 Rt_mm_movelh_ps(Rt_m128 a, - Rt_m128 b) /* MOVLHPS */ ; -extern Rt_m128 Rt_mm_loadl_pi(Rt_m128 a, Rt_m64 * p) - /* MOVLPS reg, mem */ ; -extern void Rt_mm_storel_pi(Rt_m64 * p, Rt_m128 a) /* MOVLPS mem, reg */ - ; -extern int Rt_mm_movemask_ps(Rt_m128 a) /* MOVMSKPS */ ; -extern unsigned int Rt_mm_getcsr(void) /* STMXCSR */ ; -extern void Rt_mm_setcsr(unsigned int i) /* LDMXCSR */ ; - -/* - * Load Operations - */ - -extern Rt_m128 Rt_mm_load_ss(float *p) /* MOVSS */ ; -extern Rt_m128 Rt_mm_load_ps1(float *p) /* MOVSS + shuffling */ - ; -extern Rt_m128 Rt_mm_load_ps(float *p) /* MOVAPS */ ; -extern Rt_m128 Rt_mm_loadu_ps(float *p) /* MOVUPS */ ; -extern Rt_m128 Rt_mm_loadr_ps(float *p) - /* MOVAPS + shuffling */ ; - -/* - * Set Operations - */ - -extern Rt_m128 Rt_mm_set_ss(float w) /* (composite) */ ; -extern Rt_m128 Rt_mm_set_ps1(float w) /* (composite) */ ; -extern Rt_m128 Rt_mm_set_ps(float z, float y, float x, - float w) /* (composite) */ ; -extern Rt_m128 Rt_mm_setr_ps(float z, float y, float x, - float w) /* (composite) */ ; -extern Rt_m128 Rt_mm_setzero_ps(void) /* (composite) */ ; - -/* - * Store Operations - */ - -extern void Rt_mm_store_ss(float *p, - Rt_m128 a) /* MOVSS */ ; -extern void Rt_mm_store_ps1(float *p, Rt_m128 a) - /* MOVSS + shuffling */ ; -extern void Rt_mm_store_ps(float *p, - Rt_m128 a) /* MOVAPS */ ; -extern void Rt_mm_storeu_ps(float *p, - Rt_m128 a) /* MOVUPS */ ; -extern void Rt_mm_storer_ps(float *p, Rt_m128 a) - /* MOVAPS + shuffling */ ; -extern Rt_m128 Rt_mm_move_ss(Rt_m128 a, - Rt_m128 b) /* MOVSS */ ; - -/* - * Integer Intrinsics - */ - -extern int Rt_m_pextrw(Rt_m64 a, int n) /* PEXTRW */ ; -extern Rt_m64 Rt_m_pinsrw(Rt_m64 a, int d, - int n) /* PINSRW */ ; -extern Rt_m64 Rt_m_pmaxsw(Rt_m64 a, Rt_m64 b) /* PMAXSW */ ; -extern Rt_m64 Rt_m_pmaxub(Rt_m64 a, Rt_m64 b) /* PMAXUB */ ; -extern Rt_m64 Rt_m_pminsw(Rt_m64 a, Rt_m64 b) /* PMINSW */ ; -extern Rt_m64 Rt_m_pminub(Rt_m64 a, Rt_m64 b) /* PMINUB */ ; -extern int Rt_m_pmovmskb(Rt_m64 a) /* PMOVMSKB */ ; -extern Rt_m64 Rt_m_pmulhuw(Rt_m64 a, Rt_m64 b) /* PMULHUW */ ; -extern Rt_m64 Rt_m_pshufw(Rt_m64 a, int n) /* PSHUFW */ ; -extern void Rt_m_lwmaskmovq(Rt_m64 d, Rt_m64 n, - char *p) /* MASKMOVQ */ ; - -/* - * Cacheability Support - */ - -extern void Rt_mm_prefetch(char *p, int i) /* PREFETCH */ ; -extern void Rt_mm_stream_pi(Rt_m64 * p, - Rt_m64 a) /* MOVNTQ */ ; -extern void Rt_mm_stream_ps(float *p, - Rt_m128 a) /* MOVNTPS */ ; -extern void Rt_mm_sfence(void) /* SFENCE */ ; - -/* - * WNI - */ - -/* Arithmetic Operations */ - -extern Rt_m128d Rt_mm_add_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_add_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_div_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_div_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_max_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_max_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_min_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_min_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_mul_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_mul_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_sqrt_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_sqrt_pd(Rt_m128d a); -extern Rt_m128d Rt_mm_sub_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_sub_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_andnot_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_and_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_or_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_xor_pd(Rt_m128d a, Rt_m128d b); - -/* Comparisons */ - -extern Rt_m128d Rt_mm_cmpeq_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmplt_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmple_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpgt_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpge_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpord_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpunord_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpneq_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnlt_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnle_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpngt_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnge_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpeq_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmplt_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmple_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpgt_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpge_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpord_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpunord_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpneq_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnlt_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnle_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpngt_sd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_cmpnge_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comieq_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comilt_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comile_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comigt_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comige_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_comineq_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomieq_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomilt_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomile_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomigt_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomige_sd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_ucomineq_sd(Rt_m128d a, Rt_m128d b); - -/* Conversion Operations */ - -extern Rt_m128 Rt_mm_cvtpd_ps(Rt_m128d a); -extern Rt_m128d Rt_mm_cvtps_pd(Rt_m128 a); -extern Rt_m128d Rt_mm_cvtepi32_pd(Rt_m128i a); -extern Rt_m128i Rt_mm_cvtpd_epi32(Rt_m128d a); -extern int Rt_mm_cvtsd_si32(Rt_m128d a); -extern Rt_m128 Rt_mm_cvtsd_ss(Rt_m128 a, Rt_m128d b); -extern Rt_m128d Rt_mm_cvtsi32_sd(Rt_m128d a, int b); -extern Rt_m128d Rt_mm_cvtss_sd(Rt_m128d a, Rt_m128 b); -extern Rt_m128i Rt_mm_cvttpd_epi32(Rt_m128d a); -extern int Rt_mm_cvttsd_si32(Rt_m128d a); -extern Rt_m128 Rt_mm_cvtepi32_ps(Rt_m128i a); -extern Rt_m128i Rt_mm_cvtps_epi32(Rt_m128 a); -extern Rt_m128i Rt_mm_cvttps_epi32(Rt_m128 a); -extern Rt_m64 Rt_mm_cvtpd_pi32(Rt_m128d a); -extern Rt_m64 Rt_mm_cvttpd_pi32(Rt_m128d a); -extern Rt_m128d Rt_mm_cvtpi32_pd(Rt_m64 a); - -/* Miscellaneous Operations */ - -extern Rt_m128d Rt_mm_unpackhi_pd(Rt_m128d a, Rt_m128d b); -extern Rt_m128d Rt_mm_unpacklo_pd(Rt_m128d a, Rt_m128d b); -extern int Rt_mm_movemask_pd(Rt_m128d a); -extern Rt_m128d Rt_mm_shuffle_pd(Rt_m128d a, Rt_m128d b, int i); -extern Rt_m128d Rt_mm_load_pd(const double *p); -extern Rt_m128d Rt_mm_load1_pd(const double *p); -extern Rt_m128d Rt_mm_loadr_pd(const double *p); -extern Rt_m128d Rt_mm_loadu_pd(const double *p); -extern Rt_m128d Rt_mm_load_sd(const double *p); -extern Rt_m128d Rt_mm_loadh_pd(Rt_m128d a, const double *p); -extern Rt_m128d Rt_mm_loadl_pd(Rt_m128d a, const double *p); -extern Rt_m128d Rt_mm_set_sd(double w); -extern Rt_m128d Rt_mm_set1_pd(double w); -extern Rt_m128d Rt_mm_set_pd(double w, double x); -extern Rt_m128d Rt_mm_setr_pd(double w, double x); -extern Rt_m128d Rt_mm_setzero_pd(void); -extern Rt_m128d Rt_mm_move_sd(Rt_m128d a, Rt_m128d b); -extern void Rt_mm_stream_pd(double *p, Rt_m128d a); -extern void Rt_mm_store_sd(double *p, Rt_m128d a); -extern void Rt_mm_store1_pd(double *p, Rt_m128d a); -extern void Rt_mm_store_pd(double *p, Rt_m128d a); -extern void Rt_mm_storeu_pd(double *p, Rt_m128d a); -extern void Rt_mm_storer_pd(double *p, Rt_m128d a); -extern void Rt_mm_storeh_pd(double *p, Rt_m128d a); -extern void Rt_mm_storel_pd(double *p, Rt_m128d a); -extern Rt_m128i Rt_mm_add_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_add_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_add_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m64 Rt_mm_add_si64(Rt_m64 a, Rt_m64 b); -extern Rt_m128i Rt_mm_add_epi64(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_adds_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_adds_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_adds_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_adds_epu16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_avg_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_avg_epu16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_madd_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_max_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_max_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_min_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_min_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_mulhi_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_mulhi_epu16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_mullo_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m64 Rt_mm_mul_su32(Rt_m64 a, Rt_m64 b); -extern Rt_m128i Rt_mm_mul_epu32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_sad_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_sub_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_sub_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_sub_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m64 Rt_mm_sub_si64(Rt_m64 a, Rt_m64 b); -extern Rt_m128i Rt_mm_sub_epi64(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_subs_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_subs_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_subs_epu8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_subs_epu16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_and_si128(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_andnot_si128(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_or_si128(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_xor_si128(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_slli_si128(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_slli_epi16(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_sll_epi16(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_slli_epi32(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_sll_epi32(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_slli_epi64(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_sll_epi64(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_srai_epi16(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_sra_epi16(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_srai_epi32(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_sra_epi32(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_srli_si128(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_srli_epi16(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_srl_epi16(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_srli_epi32(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_srl_epi32(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_srli_epi64(Rt_m128i a, int count); -extern Rt_m128i Rt_mm_srl_epi64(Rt_m128i a, Rt_m128i count); -extern Rt_m128i Rt_mm_cmpeq_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmpeq_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmpeq_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmpgt_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmpgt_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmpgt_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmplt_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmplt_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cmplt_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_cvtsi32_si128(int a); -extern int Rt_mm_cvtsi128_si32(Rt_m128i a); - -/* Miscellaneous Operations */ - -extern Rt_m64 Rt_mm_movepi64_pi64(Rt_m128i a); -extern Rt_m128i Rt_mm_movpi64_epi64(Rt_m64 a); -extern Rt_m128i Rt_mm_move_epi64(Rt_m128i a); -extern Rt_m128i Rt_mm_packs_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_packs_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_packus_epi16(Rt_m128i a, Rt_m128i b); -extern int Rt_mm_extract_epi16(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_insert_epi16(Rt_m128i a, int b, int imm); -extern int Rt_mm_movemask_epi8(Rt_m128i a); -extern Rt_m128i Rt_mm_shuffle_epi32(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_shufflehi_epi16(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_shufflelo_epi16(Rt_m128i a, int imm); -extern Rt_m128i Rt_mm_unpackhi_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpackhi_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpackhi_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpackhi_epi64(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpacklo_epi8(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpacklo_epi16(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpacklo_epi32(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_unpacklo_epi64(Rt_m128i a, Rt_m128i b); -extern Rt_m128i Rt_mm_loadl_epi64(Rt_m128i const *p); -extern Rt_m128i Rt_mm_load_si128(const Rt_m128i * p); -extern Rt_m128i Rt_mm_loadu_si128(const Rt_m128i * p); -extern Rt_m128i Rt_mm_set_epi64(Rt_m64 q1, Rt_m64 q0); -extern Rt_m128i Rt_mm_set_epi32(int i3, int i2, int i1, int i0); -extern Rt_m128i - Rt_mm_set_epi16(short w7, short w6, - short w5, short w4, short w3, short w2, - short w1, short w0); -extern Rt_m128i Rt_mm_set_epi8(char b15, char b14, - char b13, char b12, - char b11, char b10, - char b9, char b8, - char b7, char b6, - char b5, char b4, - char b3, char b2, - char b1, char b0); -extern Rt_m128i Rt_mm_set1_epi64(Rt_m64 q); -extern Rt_m128i Rt_mm_set1_epi32(int i); -extern Rt_m128i Rt_mm_set1_epi16(short w); -extern Rt_m128i Rt_mm_set1_epi8(char b); -extern Rt_m128i Rt_mm_setr_epi64(Rt_m64 q0, Rt_m64 q1); -extern Rt_m128i Rt_mm_setr_epi32(int i0, int i1, int i2, - int i3); -extern Rt_m128i Rt_mm_setr_epi16(short w0, short w1, - short w2, short w3, - short w4, short w5, - short w6, short w7); -extern Rt_m128i Rt_mm_setr_epi8(char b0, char b1, - char b2, char b3, - char b4, char b5, - char b6, char b7, - char b8, char b9, - char b10, char b11, - char b12, char b13, - char b14, char b15); -extern Rt_m128i Rt_mm_setzero_si128(void); - -/* Store Operations */ - -extern void Rt_mm_store_si128(Rt_m128i * p, Rt_m128i a); -extern void Rt_mm_storeu_si128(Rt_m128i * p, Rt_m128i a); -extern void Rt_mm_maskmoveu_si128(Rt_m128i s, Rt_m128i n, - char *p); -extern void Rt_mm_storel_epi64(Rt_m128i * p, Rt_m128i a); -extern void Rt_mm_stream_si128(Rt_m128i * p, Rt_m128i a); -extern void Rt_mm_stream_si32(int *p, int a); -extern void Rt_mm_clflush(void const *p); -extern void Rt_mm_lfence(void); -extern void Rt_mm_mfence(void); - -/* - * API - */ -extern RwUInt32 RtIntelRDTSC(void); -extern RwUInt32 RtIntelToggleEFLAGS(int mask); -extern RwUInt32 RtIntelCPUID(RwUInt32 level, - void *pb, void *pc, void *pd); -extern RwUInt32 RtIntelHaveCPUID(void); -extern RwUInt32 RtIntelHaveRDTSC(void); -extern RwUInt32 RtIntelHaveMMX(void); -extern RwUInt32 RtIntelHaveSSE(void); -extern RwUInt32 RtIntelHaveWNI(void); -extern RwUInt32 RtIntelCpuType(void); - -extern RwBool RtIntelStartTiming(void * data); -extern RwBool RtIntelStopTiming(void *data); -extern RwBool RtIntelTime(RwFixed64 * result, - RtIntelTimeFunction func, - void *data); - -extern RwBool RtIntelPluginAttach(void); - -extern RtIntelOverload *_rtIntelOverloadGetHandle(void); - -extern RxNodeDefinition *RxNodeDefinitionGetSSETransformCSL(void); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -/* - * LEGACY-SUPPORT -- e.g. - * rwsdk/driver/d3d/baintd3d.c - * is locked at time of writing - */ - -#define RpIntelRDTSC() RtIntelRDTSC() -#define RpIntelToggleEFLAGS(_mask) RtIntelToggleEFLAGS(_mask) -#define RpIntelCPUID(_level, _pb, _pc, _pd) \ - RtIntelCPUID(_level, _pb, _pc, _pd) -#define RpIntelHaveCPUID() RtIntelHaveCPUID() -#define RpIntelHaveRDTSC() RtIntelHaveRDTSC() -#define RpIntelHaveMMX() RtIntelHaveMMX() -#define RpIntelHaveSSE() RtIntelHaveSSE() -#define RpIntelHaveWNI() RtIntelHaveWNI() -#define RpIntelCpuType() RtIntelCpuType() -#define RpIntelStartTiming(_data) RtIntelStartTiming(_data) -#define RpIntelStopTiming(_data) RtIntelStopTiming(_data) -#define RpIntelTime(_result, _func, _data) \ - RtIntelTime(_result, _func, _data) -#define RpIntelPluginAttach() RtIntelPluginAttach() -#define RpNodeDefinitionGetSSETransformCSL() \ - RxNodeDefinitionGetSSETransformCSL() - -typedef RtIntelOverload RwIntelOverload; -typedef RtIntelOverload RpIntelOverload; - -#define _rwIntelOverloadGetHandle() _rtIntelOverloadGetHandle() -#define _rpIntelOverloadGetHandle() _rtIntelOverloadGetHandle() -#define RwIntelHaveSSE() RtIntelHaveSSE() -#define RpIntelHaveSSE() RtIntelHaveSSE() - -#if (defined(RWEMULATEINTELSIMD) || !defined(__ICL)) - -/* - * MMX - */ - -/* General support intrinsics */ -#define _m_empty() Rt_m_empty() -#define _m_from_int(i) Rt_m_from_int(i) -#define _m_to_int(m) Rt_m_to_int(m) -#define _m_packsswb(m1, m2) Rt_m_packsswb(m1, m2) -#define _m_packssdw(m1, m2) Rt_m_packssdw(m1, m2) -#define _m_packuswb(m1, m2) Rt_m_packuswb(m1, m2) -#define _m_punpckhbw(m1, m2) Rt_m_punpckhbw(m1, m2) -#define _m_punpckhwd(m1, m2) Rt_m_punpckhwd(m1, m2) -#define _m_punpckhdq(m1, m2) Rt_m_punpckhdq(m1, m2) -#define _m_punpcklbw(m1, m2) Rt_m_punpcklbw(m1, m2) -#define _m_punpcklwd(m1, m2) Rt_m_punpcklwd(m1, m2) -#define _m_punpckldq(m1, m2) Rt_m_punpckldq(m1, m2) - -/* Packed arithmetic intrinsics */ -#define _m_paddb(m1, m2) Rt_m_paddb(m1, m2) -#define _m_paddw(m1, m2) Rt_m_paddw(m1, m2) -#define _m_paddd(m1, m2) Rt_m_paddd(m1, m2) -#define _m_paddsb(m1, m2) Rt_m_paddsb(m1, m2) -#define _m_paddsw(m1, m2) Rt_m_paddsw(m1, m2) -#define _m_paddusb(m1, m2) Rt_m_paddusb(m1, m2) -#define _m_paddusw(m1, m2) Rt_m_paddusw(m1, m2) -#define _m_psubb(m1, m2) Rt_m_psubb(m1, m2) -#define _m_psubw(m1, m2) Rt_m_psubw(m1, m2) -#define _m_psubd(m1, m2) Rt_m_psubd(m1, m2) -#define _m_psubsb(m1, m2) Rt_m_psubsb(m1, m2) -#define _m_psubsw(m1, m2) Rt_m_psubsw(m1, m2) -#define _m_psubusb(m1, m2) Rt_m_psubusb(m1, m2) -#define _m_psubusw(m1, m2) Rt_m_psubusw(m1, m2) -#define _m_pmaddwd(m1, m2) Rt_m_pmaddwd(m1, m2) -#define _m_pmulhw(m1, m2) Rt_m_pmulhw(m1, m2) -#define _m_pmullw(m1, m2) Rt_m_pmullw(m1, m2) - -/* Shift intrinsics */ -#define _m_psllw(m, count) Rt_m_psllw(m, count) -#define _m_psllwi(m, count) Rt_m_psllwi(m, count) -#define _m_pslld(m, count) Rt_m_pslld(m, count) -#define _m_pslldi(m, count) Rt_m_pslldi(m, count) -#define _m_psllq(m, count) Rt_m_psllq(m, count) -#define _m_psllqi(m, count) Rt_m_psllqi(m, count) -#define _m_psraw(m, count) Rt_m_psraw(m, count) -#define _m_psrawi(m, count) Rt_m_psrawi(m, count) -#define _m_psrad(m, count) Rt_m_psrad(m, count) -#define _m_psradi(m, count) Rt_m_psradi(m, count) -#define _m_psrlw(m, count) Rt_m_psrlw(m, count) -#define _m_psrlwi(m, count) Rt_m_psrlwi(m, count) -#define _m_psrld(m, count) Rt_m_psrld(m, count) -#define _m_psrldi(m, count) Rt_m_psrldi(m, count) -#define _m_psrlq(m, count) Rt_m_psrlq(m, count) -#define _m_psrlqi(m, count) Rt_m_psrlqi(m, count) - -/* Logical intrinsics */ -#define _m_pand(m1, m2) Rt_m_pand(m1, m2) -#define _m_pandn(m1, m2) Rt_m_pandn(m1, m2) -#define _m_por(m1, m2) Rt_m_por(m1, m2) -#define _m_pxor(m1, m2) Rt_m_pxor(m1, m2) - -/* Comparison intrinsics */ -#define _m_pcmpeqb(m1, m2) Rt_m_pcmpeqb(m1, m2) -#define _m_pcmpeqw(m1, m2) Rt_m_pcmpeqw(m1, m2) -#define _m_pcmpeqd(m1, m2) Rt_m_pcmpeqd(m1, m2) -#define _m_pcmpgtb(m1, m2) Rt_m_pcmpgtb(m1, m2) -#define _m_pcmpgtw(m1, m2) Rt_m_pcmpgtw(m1, m2) -#define _m_pcmpgtd(m1, m2) Rt_m_pcmpgtd(m1, m2) - -/* - * SSE - */ - -/* - * Arithmetic Operations - */ - -#define _mm_add_ss(a, b) Rt_mm_add_ss(a, b) -#define _mm_add_ps(a, b) Rt_mm_add_ps(a, b) -#define _mm_sub_ss(a, b) Rt_mm_sub_ss(a, b) -#define _mm_sub_ps(a, b) Rt_mm_sub_ps(a, b) -#define _mm_mul_ss(a, b) Rt_mm_mul_ss(a, b) -#define _mm_mul_ps(a, b) Rt_mm_mul_ps(a, b) -#define _mm_div_ss(a, b) Rt_mm_div_ss(a, b) -#define _mm_div_ps(a, b) Rt_mm_div_ps(a, b) -#define _mm_sqrt_ss(a) Rt_mm_sqrt_ss(a) -#define _mm_sqrt_ps(a) Rt_mm_sqrt_ps(a) -#define _mm_rcp_ss(a) Rt_mm_rcp_ss(a) -#define _mm_rcp_ps(a) Rt_mm_rcp_ps(a) -#define _mm_rsqrt_ss(a) Rt_mm_rsqrt_ss(a) -#define _mm_rsqrt_ps(a) Rt_mm_rsqrt_ps(a) -#define _mm_min_ss(a, b) Rt_mm_min_ss(a, b) -#define _mm_min_ps(a, b) Rt_mm_min_ps(a, b) -#define _mm_max_ss(a, b) Rt_mm_max_ss(a, b) -#define _mm_max_ps(a, b) Rt_mm_max_ps(a, b) - -/* - * Logical Operations - */ - -#define _mm_and_ps(a, b) Rt_mm_and_ps(a, b) -#define _mm_andnot_ps(a, b) Rt_mm_andnot_ps(a, b) -#define _mm_or_ps(a, b) Rt_mm_or_ps(a, b) -#define _mm_xor_ps(a, b) Rt_mm_xor_ps(a, b) - -/* - * Comparisons - */ - -#define _mm_cmpeq_ss(a, b) Rt_mm_cmpeq_ss(a, b) -#define _mm_cmpeq_ps(a, b) Rt_mm_cmpeq_ps(a, b) -#define _mm_cmplt_ss(a, b) Rt_mm_cmplt_ss(a, b) -#define _mm_cmplt_ps(a, b) Rt_mm_cmplt_ps(a, b) -#define _mm_cmple_ss(a, b) Rt_mm_cmple_ss(a, b) -#define _mm_cmple_ps(a, b) Rt_mm_cmple_ps(a, b) -#define _mm_cmpgt_ss(a, b) Rt_mm_cmpgt_ss(a, b) -#define _mm_cmpgt_ps(a, b) Rt_mm_cmpgt_ps(a, b) -#define _mm_cmpge_ss(a, b) Rt_mm_cmpge_ss(a, b) -#define _mm_cmpge_ps(a, b) Rt_mm_cmpge_ps(a, b) -#define _mm_cmpneq_ss(a, b) Rt_mm_cmpneq_ss(a, b) -#define _mm_cmpneq_ps(a, b) Rt_mm_cmpneq_ps(a, b) -#define _mm_cmpnlt_ss(a, b) Rt_mm_cmpnlt_ss(a, b) -#define _mm_cmpnlt_ps(a, b) Rt_mm_cmpnlt_ps(a, b) -#define _mm_cmpnle_ss(a, b) Rt_mm_cmpnle_ss(a, b) -#define _mm_cmpnle_ps(a, b) Rt_mm_cmpnle_ps(a, b) -#define _mm_cmpngt_ss(a, b) Rt_mm_cmpngt_ss(a, b) -#define _mm_cmpngt_ps(a, b) Rt_mm_cmpngt_ps(a, b) -#define _mm_cmpnge_ss(a, b) Rt_mm_cmpnge_ss(a, b) -#define _mm_cmpnge_ps(a, b) Rt_mm_cmpnge_ps(a, b) -#define _mm_cmpord_ss(a, b) Rt_mm_cmpord_ss(a, b) -#define _mm_cmpord_ps(a, b) Rt_mm_cmpord_ps(a, b) -#define _mm_cmpunord_ss(a, b) Rt_mm_cmpunord_ss(a, b) -#define _mm_cmpunord_ps(a, b) Rt_mm_cmpunord_ps(a, b) -#define _mm_comieq_ss(a, b) Rt_mm_comieq_ss(a, b) -#define _mm_comilt_ss(a, b) Rt_mm_comilt_ss(a, b) -#define _mm_comile_ss(a, b) Rt_mm_comile_ss(a, b) -#define _mm_comigt_ss(a, b) Rt_mm_comigt_ss(a, b) -#define _mm_comige_ss(a, b) Rt_mm_comige_ss(a, b) -#define _mm_comineq_ss(a, b) Rt_mm_comineq_ss(a, b) -#define _mm_ucomieq_ss(a, b) Rt_mm_ucomieq_ss(a, b) -#define _mm_ucomilt_ss(a, b) Rt_mm_ucomilt_ss(a, b) -#define _mm_ucomile_ss(a, b) Rt_mm_ucomile_ss(a, b) -#define _mm_ucomigt_ss(a, b) Rt_mm_ucomigt_ss(a, b) -#define _mm_ucomige_ss(a, b) Rt_mm_ucomige_ss(a, b) -#define _mm_ucomineq_ss(a, b) Rt_mm_ucomineq_ss(a, b) - -/* - * Conversion Operations - */ - -#define _mm_cvt_ss2si(a) Rt_mm_cvt_ss2si(a) -#define _mm_cvt_ps2pi(a) Rt_mm_cvt_ps2pi(a) -#define _mm_cvtt_ss2si(a) Rt_mm_cvtt_ss2si(a) -#define _mm_cvtt_ps2pi(a) Rt_mm_cvtt_ps2pi(a) -#define _mm_cvt_si2ss(a, b) Rt_mm_cvt_si2ss(a, b) -#define _mm_cvt_pi2ps(a, b) Rt_mm_cvt_pi2ps(a, b) - -/* - * Miscellaneous - */ - -#define _mm_shuffle_ps(a, b, i) Rt_mm_shuffle_ps(a, b, i) -#define _mm_unpackhi_ps(a, b) Rt_mm_unpackhi_ps(a, b) -#define _mm_unpacklo_ps(a, b) Rt_mm_unpacklo_ps(a, b) -#define _mm_loadh_pi(a, p) Rt_mm_loadh_pi(a, p) -#define _mm_storeh_pi(p, a) Rt_mm_storeh_pi(p, a) -#define _mm_movehl_ps(a, b) Rt_mm_movehl_ps(a, b) -#define _mm_movelh_ps(a, b) Rt_mm_movelh_ps(a, b) -#define _mm_loadl_pi(a, p) Rt_mm_loadl_pi(a, p) -#define _mm_storel_pi(p, a) Rt_mm_storel_pi(p, a) -#define _mm_movemask_ps(a) Rt_mm_movemask_ps(a) -#define _mm_getcsr() Rt_mm_getcsr() -#define _mm_setcsr(i) Rt_mm_setcsr(i) - -/* - *Load Operations - */ - -#define _mm_load_ss(p) Rt_mm_load_ss(p) -#define _mm_load_ps1(p) Rt_mm_load_ps1(p) -#define _mm_load_ps(p) Rt_mm_load_ps(p) -#define _mm_loadu_ps(p) Rt_mm_loadu_ps(p) -#define _mm_loadr_ps(p) Rt_mm_loadr_ps(p) - -/* - * Set Operations - */ - -#define _mm_set_ss(w) Rt_mm_set_ss(w) -#define _mm_set_ps1(w) Rt_mm_set_ps1(w) -#define _mm_set_ps(z, y, x, w) Rt_mm_set_ps(z, y, x, w) -#define _mm_setr_ps(z, y, x, w) Rt_mm_setr_ps(z, y, x, w) -#define _mm_setzero_ps() Rt_mm_setzero_ps() - -/* - * Store Operations - */ - -#define _mm_store_ss(p, a) Rt_mm_store_ss(p, a) -#define _mm_store_ps1(p, a) Rt_mm_store_ps1(p, a) -#define _mm_store_ps(p, a) Rt_mm_store_ps(p, a) -#define _mm_storeu_ps(p, a) Rt_mm_storeu_ps(p, a) -#define _mm_storer_ps(p, a) Rt_mm_storer_ps(p, a) -#define _mm_move_ss(a, b) Rt_mm_move_ss(a, b) - -/* - * Integer Intrinsics - */ - -#define _m_pextrw(a, n) Rt_m_pextrw(a, n) -#define _m_pinsrw(a, d, n) Rt_m_pinsrw(a, d, n) -#define _m_pmaxsw(a, b) Rt_m_pmaxsw(a, b) -#define _m_pmaxub(a, b) Rt_m_pmaxub(a, b) -#define _m_pminsw(a, b) Rt_m_pminsw(a, b) -#define _m_pminub(a, b) Rt_m_pminub(a, b) -#define _m_pmovmskb(a) Rt_m_pmovmskb(a) -#define _m_pmulhuw(a, b) Rt_m_pmulhuw(a, b) -#define _m_pshufw(a, n) Rt_m_pshufw(a, n) -#define _m_lwmaskmovq(d, n, p) Rt_m_lwmaskmovq(d, n, p) - -/* - * Cacheability Support - */ - -#define _mm_prefetch(p, i) Rt_mm_prefetch(p, i) -#define _mm_stream_pi(p, a) Rt_mm_stream_pi(p, a) -#define _mm_stream_ps(p, a) Rt_mm_stream_ps(p, a) -#define _mm_sfence() Rt_mm_sfence() - -#endif /* (defined(RWEMULATEINTELSIMD) || !defined(__ICL)) */ - -#endif /* RTINTEL_H */ diff --git a/rwsdk/include/d3d8/rtintel.rpe b/rwsdk/include/d3d8/rtintel.rpe deleted file mode 100644 index bf297ca0..00000000 --- a/rwsdk/include/d3d8/rtintel.rpe +++ /dev/null @@ -1,645 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum e_rwdb_CriterionIntel -{ - - - - e_rwdb_CriterionIntelLAST = RWFORCEENUMSIZEINT -}; - -typedef enum e_rwdb_CriterionIntel e_rwdb_CriterionIntel; - - diff --git a/rwsdk/include/d3d8/rtintsec.h b/rwsdk/include/d3d8/rtintsec.h index cb482b17..a2e4c3d6 100644 --- a/rwsdk/include/d3d8/rtintsec.h +++ b/rwsdk/include/d3d8/rtintsec.h @@ -10,8 +10,8 @@ #define RTINTSEC_H /** - * \defgroup rtintersect RtIntersection - * \ingroup rttool + * \defgroup rtintersection RtIntersection + * \ingroup mathtools * * Object Intersection Toolkit for RenderWare. */ diff --git a/rwsdk/include/d3d8/rtintsec.rpe b/rwsdk/include/d3d8/rtintsec.rpe index 7b2ce6e1..3c7f7bf3 100644 --- a/rwsdk/include/d3d8/rtintsec.rpe +++ b/rwsdk/include/d3d8/rtintsec.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtltmap.h b/rwsdk/include/d3d8/rtltmap.h index 1a53b185..8ee15a43 100644 --- a/rwsdk/include/d3d8/rtltmap.h +++ b/rwsdk/include/d3d8/rtltmap.h @@ -1,7 +1,7 @@ /** * \defgroup rtltmap RtLtMap - * \ingroup rttool + * \ingroup lighting * * Lightmap Generation Toolkit for RenderWare. */ @@ -21,7 +21,6 @@ /** * \ingroup rtltmap - * \typedef RtLtMapIlluminateSampleCallBack * \ref RtLtMapIlluminateSampleCallBack is the callback to be called, from * within \ref RtLtMapIlluminate, for groups of samples in the objects * currently being illuminated. @@ -32,7 +31,7 @@ * * This callback will receive an array of color values to fill in, each * representing one sample in the current object - this may correspond to - * a texel in the current object's lightmap or the prelight colour of a + * a texel in the current object's lightmap or the prelight color of a * vertex, depending on whether the object is lightmapped and/or vertex-lit. * It will receive positions (in world-space) for each sample and the normal * vector (again, in world-space) of each sample (normals are interpolated @@ -44,7 +43,7 @@ * The barycentric coordinates may be used, for example, to allow a callback * to easily import existing lighting data (e.g from previously generated * lightmaps in a different format, or from an art package with lighting - * functionality). + * functionality). * * NOTE: The alpha channel of the RwRGBA results array must NOT be modified. * These values are used internally and their modification may result in @@ -82,7 +81,6 @@ typedef RwRGBA *(*RtLtMapIlluminateSampleCallBack)(RwRGBA *results, /** * \ingroup rtltmap - * \typedef RtLtMapIlluminateVisCallBack * \ref RtLtMapIlluminateVisCallBack is the callback to be called, from * within \ref RtLtMapIlluminate, to determine the visibility between a * sample and a light. @@ -94,7 +92,7 @@ typedef RwRGBA *(*RtLtMapIlluminateSampleCallBack)(RwRGBA *results, * Each sample may represent a texel in the current object's lightmap * or the prelight color of a vertex, depending on whether the object * is lightmapped and/or vertex-lit (see \ref RtLtMapObjectFlags). - * + * * The callback will receive a pointer to the world of the current * \ref RtLtMapLightingSession (this may be used to perform intersection * tests), the world-space position of the sample, the world-space @@ -111,15 +109,15 @@ typedef RwRGBA *(*RtLtMapIlluminateSampleCallBack)(RwRGBA *results, * expressed by modifying the RwRGBAReal value. This defaults to bright * white but may be reduced to signify that the light from the light * source should be attenuated. This could be used to take into account - * light-filtering objects in the scene (such as coloured glass or fog). + * light-filtering objects in the scene (such as colored glass or fog). * * The default RtLtMapIlluminateVisCallBack supplied with RtLtMap is * \ref RtLtMapDefaultVisCallBack. This callback performs visibility - * tests using the line-intersection tests from \ref rtintersect. It tests + * tests using the line-intersection tests from \ref rtintersection. It tests * for occlusion by RpWorldSectors and RpAtomics and it respects the * relevant \ref RtLtMapObjectFlags and \ref RtLtMapMaterialFlags but it * does not filter light; visibility is determined to be either one or zero. - * + * * \param world The world of the current RtLtMapLightingSession * \param result An RwRGBAReal value to attentuate this light's * contribution to the current sample @@ -141,7 +139,6 @@ typedef RwBool (*RtLtMapIlluminateVisCallBack)(RpWorld *world, /** * \ingroup rtltmap - * \typedef RtLtMapIlluminateProgressCallBack * \ref RtLtMapIlluminateProgressCallBack is the callback to be called, from * within \ref RtLtMapIlluminate, to allow a user to track lighting progress. * @@ -214,17 +211,17 @@ typedef enum RtLtMapProgressMessage RtLtMapProgressMessage; typedef struct RtLtMapLightingSession RtLtMapLightingSession; /** * \ingroup rtltmap - * \typedef RtLtMapLightingSession - * The \ref RtLtMapLightingSession structure holds information to be passed to + * \struct RtLtMapLightingSession + * The RtLtMapLightingSession structure holds information to be passed to * \ref RtLtMapIlluminate. It is used to parameterize the lighting process. * - * The \ref RtLtMapLightingSession structure encapsulates a set of objects and + * The RtLtMapLightingSession structure encapsulates a set of objects and * keeps track of the proportion of samples, within that set, that have already * been lit by calls to \ref RtLtMapIlluminate. Each call performs lighting for * one 'slice' of the whole 'session'. If the camera member is non-NULL, it is * important that the camera is not moved between lighting slices. * - * The \ref RtLtMapLightingSession is also passed to + * The RtLtMapLightingSession is also passed to * \ref RtLtMapLightMapsCreate, \ref RtLtMapLightMapsClear, * \ref RtLtMapLightMapsDestroy and \ref RtLtMapAreaLightGroupCreate, * though not all of the session structure's member will be used in @@ -327,7 +324,7 @@ typedef enum RtLtMapMaterialFlags RtLtMapMaterialFlags; /** * \ingroup rtltmap - * \ref RtLtMapObjectFlags is an enumerated type specifying the different + * RtLtMapObjectFlags is an enumerated type specifying the different * lightmap-related flags which may be applied to world sectors and * atomics. These values will be taken into consideration within * \ref RtLtMapLightMapsCreate and \ref RtLtMapIlluminate. @@ -345,11 +342,11 @@ enum RtLtMapObjectFlags rtLTMAPOBJECTNAFLAG = 0, rtLTMAPOBJECTLIGHTMAP = 1, /**< This object is to be lightmapped */ - rtLTMAPOBJECTVERTEXLIGHT = 2, /**< This object's vertex prelight colours should - * be lit within \ref RtLtMapIlluminate. */ + rtLTMAPOBJECTVERTEXLIGHT = 2, /**< This object's vertex prelight colors should + be lit within \ref RtLtMapIlluminate. */ rtLTMAPOBJECTNOSHADOW = 4, /**< This object does not cast shadows (useful, for - * example, for moving objects for which dynamic - * shadows are to be rendered - such as doors) */ + example, for moving objects for which dynamic + shadows are to be rendered - such as doors) */ rtLTMAPOBJECTFLAGFORCEENUMSIZEINT = 0x7FFFFFFF }; @@ -358,10 +355,13 @@ typedef enum RtLtMapObjectFlags RtLtMapObjectFlags; /* Area-lighting stuff:* ***********************/ + +typedef struct RtLtMapAreaLightGroup RtLtMapAreaLightGroup; + /** * \ingroup rtltmap - * \typedef RtLtMapAreaLightGroup - * \ref RtLtMapAreaLightGroup is a structure which acts as a container + * \struct RtLtMapAreaLightGroup + * RtLtMapAreaLightGroup is a structure which acts as a container * for area lights created by a call to \ref RtLtMapAreaLightGroupCreate. * The containers may be chained and passed to \ref RtLtMapIlluminate. * Each container has an optional pointer to a RwFrame which is used to @@ -376,7 +376,6 @@ typedef enum RtLtMapObjectFlags RtLtMapObjectFlags; * \see RtLtMapIlluminate * \see RtLtMapIlluminateVisCallBack */ -typedef struct RtLtMapAreaLightGroup RtLtMapAreaLightGroup; struct RtLtMapAreaLightGroup { RwSList *meshes; /**< A list of hierarchically-grouped area lights */ @@ -388,13 +387,15 @@ struct RtLtMapAreaLightGroup /* Area light triangles are grouped by source mesh (this may change) */ typedef struct LtMapAreaLightMesh LtMapAreaLightMesh; + +#if (!defined(DOXYGEN)) struct LtMapAreaLightMesh { RwUInt32 flags; /* To hold hierarchical visibility culling flags, * relevant to the object/triangle *currently* being lit. */ - RpMaterial *material; /* The emitter material, containing colour, etc */ + RpMaterial *material; /* The emitter material, containing color, etc */ RwSphere sphere; /* Each mesh has an associated center and radius */ - RwReal ROI; /* Centred on the above sphere, the R.O.I. of the + RwReal ROI; /* Centered on the above sphere, the R.O.I. of the * samples in this mesh (a conservative estimate) */ RwSList *triangles; /* A list of the area light triangles in this mesh */ }; @@ -412,6 +413,37 @@ struct LtMapAreaLight * not worth storing 3 points, coarse culling is fine) */ RwV3d *lights; /* Array of area light sample positions (in world-space) */ }; +#endif /* (!defined(DOXYGEN)) */ + +#if (defined(SKY2_DRVMODEL_H) || defined(NULLSKY_DRVMODEL_H)) + +/** + * \ingroup rtltmapps2 + * \ref RtLtMapSkyLumCalcCallBack is the callback to be called, from + * within \ref RtLtMapSkyBaseTextureProcess, to allow a user to select the + * function to process the textures for rendering on the PlayStation 2. + * + * The function is called for each span of a full color image, or for the + * CLUT in a palettised image, to compute the luminance and stores it in + * the alpha component of the texel. + * + * \param scanline A pointer to a scanline of \ref RwRGBA data. + * \param width Width of the scanline, in pixels. + * + * \return A pointer to the scanline on success, NULL otherwise. + * + * \see RtLtMapSkyBaseTextureProcess + * \see RtLtMapSkyLightingSessionBaseTexturesProcess + * \see RtLtMapSkyLightMapMakeDarkMap + * \see RtLtMapSkyLumCalcMaxCallBack + * \see RtLtMapSkyLumCalcSigmaCallBack + * \see RtLtMapSkySetLumCalcCallBack + * \see RtLtMapSkyGetLumCalcCallBack + */ +typedef RwRGBA *(*RtLtMapSkyLumCalcCallBack)(RwRGBA *scanline, + RwUInt32 width ); + +#endif /* (defined(SKY2_DRVMODEL_H) || defined(NULLSKY_DRVMODEL_H)) */ #ifdef __cplusplus @@ -487,6 +519,12 @@ RtLtMapDefaultVisCallBack(RpWorld *world, RwV3d *lightPos, RpLight __RWUNUSED__ *light); +extern void +RtLtMapSetVisCallBackCollisionScalar(RwReal scalar); + +extern RwReal +RtLtMapGetVisCallBackCollisionScalar(void); + extern RtLtMapLightingSession * RtLtMapLightingSessionInitialize(RtLtMapLightingSession *session, RpWorld *world); @@ -562,7 +600,6 @@ extern RwBool RtLtMapSetAreaLightErrorCutoff(RwReal tolerance); - /* Texture-saving functionality: */ extern RwTexDictionary * RtLtMapTexDictionaryCreate(RtLtMapLightingSession *session); @@ -588,7 +625,13 @@ extern RpAtomic *RtLtMapSkyAtomicBaseTexturesProcess(RpAtomic *atomic); extern RpWorldSector * RtLtMapSkyWorldSectorBaseTexturesProcess(RpWorldSector *sector); extern RtLtMapLightingSession * -RtLtMapSkyBaseTexturesProcess(RtLtMapLightingSession *session); +RtLtMapSkyLightingSessionBaseTexturesProcess(RtLtMapLightingSession *session); + +extern RwRGBA *RtLtMapSkyLumCalcMaxCallBack( RwRGBA *scanline, RwUInt32 width ); +extern RwRGBA *RtLtMapSkyLumCalcSigmaCallBack( RwRGBA *scanline, RwUInt32 width ); + +extern RwBool RtLtMapSkySetLumCalcCallBack(RtLtMapSkyLumCalcCallBack cback); +extern RtLtMapSkyLumCalcCallBack RtLtMapSkyGetLumCalcCallBack( void ); #endif /* (defined(SKY2_DRVMODEL_H) || defined(NULLSKY_DRVMODEL_H)) */ diff --git a/rwsdk/include/d3d8/rtltmap.rpe b/rwsdk/include/d3d8/rtltmap.rpe index e510d78b..fb171c51 100644 --- a/rwsdk/include/d3d8/rtltmap.rpe +++ b/rwsdk/include/d3d8/rtltmap.rpe @@ -138,472 +138,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtmipk.h b/rwsdk/include/d3d8/rtmipk.h index c06a3879..6c777b41 100644 --- a/rwsdk/include/d3d8/rtmipk.h +++ b/rwsdk/include/d3d8/rtmipk.h @@ -15,9 +15,9 @@ /** * \defgroup rtmipk RtMipmapK - * \ingroup rttool + * \ingroup mipmapping * - * Ps2/Mipmap K Value Toolkit for RenderWare. + * PlayStation 2 / Mipmap K Value Toolkit for RenderWare. */ /**************************************************************************** diff --git a/rwsdk/include/d3d8/rtmipk.rpe b/rwsdk/include/d3d8/rtmipk.rpe index 24e1fd33..04500e1d 100644 --- a/rwsdk/include/d3d8/rtmipk.rpe +++ b/rwsdk/include/d3d8/rtmipk.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtpick.h b/rwsdk/include/d3d8/rtpick.h index 5ea78058..62f564a3 100644 --- a/rwsdk/include/d3d8/rtpick.h +++ b/rwsdk/include/d3d8/rtpick.h @@ -11,7 +11,7 @@ /** * \defgroup rtpick RtPick - * \ingroup rttool + * \ingroup collisiondetection * * Picking Toolkit for RenderWare. */ diff --git a/rwsdk/include/d3d8/rtpick.rpe b/rwsdk/include/d3d8/rtpick.rpe index 055ea9ff..779e2f9a 100644 --- a/rwsdk/include/d3d8/rtpick.rpe +++ b/rwsdk/include/d3d8/rtpick.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtpitexd.h b/rwsdk/include/d3d8/rtpitexd.h index 39287bcd..602c608a 100644 --- a/rwsdk/include/d3d8/rtpitexd.h +++ b/rwsdk/include/d3d8/rtpitexd.h @@ -11,7 +11,7 @@ /** * \defgroup rtpitexd RtPITexD - * \ingroup rttool + * \ingroup texturedictionaries * * Platform Independent Texture Dictionaries * diff --git a/rwsdk/include/d3d8/rtpitexd.rpe b/rwsdk/include/d3d8/rtpitexd.rpe index 0650ea5c..290ac864 100644 --- a/rwsdk/include/d3d8/rtpitexd.rpe +++ b/rwsdk/include/d3d8/rtpitexd.rpe @@ -182,472 +182,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtpng.h b/rwsdk/include/d3d8/rtpng.h index 694c8400..4ba8cf0f 100644 --- a/rwsdk/include/d3d8/rtpng.h +++ b/rwsdk/include/d3d8/rtpng.h @@ -12,7 +12,7 @@ /** * \defgroup rtpng RtPNG - * \ingroup rttool + * \ingroup imageconversiontools * * PNG/Portable Network Graphics Image Format Toolkit for RenderWare. * diff --git a/rwsdk/include/d3d8/rtpng.rpe b/rwsdk/include/d3d8/rtpng.rpe index 7a6b6cc2..e3f6f0d7 100644 --- a/rwsdk/include/d3d8/rtpng.rpe +++ b/rwsdk/include/d3d8/rtpng.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtquat.h b/rwsdk/include/d3d8/rtquat.h index 05e971d0..a0a6e89d 100644 --- a/rwsdk/include/d3d8/rtquat.h +++ b/rwsdk/include/d3d8/rtquat.h @@ -10,7 +10,7 @@ /** * \defgroup rtquat RtQuat - * \ingroup rttool + * \ingroup mathtools * * Quaternion Toolkit for RenderWare. * @@ -392,7 +392,7 @@ MACRO_START \ \ /* Matrix is orthogonal */ \ rwMatrixSetFlags((mpMatrix), \ - (rwMATRIXTYPEORTHOGANAL & \ + (rwMATRIXTYPEORTHOGONAL & \ ~rwMATRIXINTERNALIDENTITY) ); \ \ } \ diff --git a/rwsdk/include/d3d8/rtquat.rpe b/rwsdk/include/d3d8/rtquat.rpe index e43bb50c..b239aba0 100644 --- a/rwsdk/include/d3d8/rtquat.rpe +++ b/rwsdk/include/d3d8/rtquat.rpe @@ -145,472 +145,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtras.h b/rwsdk/include/d3d8/rtras.h index 0a9064a8..957e21e6 100644 --- a/rwsdk/include/d3d8/rtras.h +++ b/rwsdk/include/d3d8/rtras.h @@ -11,7 +11,7 @@ /** * \defgroup rtras RtRAS - * \ingroup rttool + * \ingroup imageconversiontools * * RAS/Sun Raster Fule Format Image Format Toolkit for RenderWare. * diff --git a/rwsdk/include/d3d8/rtras.rpe b/rwsdk/include/d3d8/rtras.rpe index 3398c3cc..a242ef49 100644 --- a/rwsdk/include/d3d8/rtras.rpe +++ b/rwsdk/include/d3d8/rtras.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtray.h b/rwsdk/include/d3d8/rtray.h index 4bf0a343..b2f3d4bc 100644 --- a/rwsdk/include/d3d8/rtray.h +++ b/rwsdk/include/d3d8/rtray.h @@ -11,7 +11,7 @@ /** * \defgroup rtray RtRay - * \ingroup rttool + * \ingroup mathtools * * Line Toolkit for RenderWare. */ @@ -46,7 +46,9 @@ extern "C" /* Line intersections */ extern RwReal RtLineTriangleIntersectionTest(RwLine *line, RwV3d *normal, RwV3d *v0, RwV3d *v1, RwV3d *v2); -extern RwReal RtLineSphereIntersectionTest(RwLine *line, RwSphere *sphere); +extern RwBool RtLineSphereIntersectionTest(RwLine *line, + RwSphere *sphere, + RwReal *centerDist); /* Line clipping */ extern RwLine *RtLineClipPlane(RwLine *line, RwPlane *plane); diff --git a/rwsdk/include/d3d8/rtray.rpe b/rwsdk/include/d3d8/rtray.rpe index 27788d94..c1ff4458 100644 --- a/rwsdk/include/d3d8/rtray.rpe +++ b/rwsdk/include/d3d8/rtray.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtslerp.h b/rwsdk/include/d3d8/rtslerp.h index ec41752c..4262b894 100644 --- a/rwsdk/include/d3d8/rtslerp.h +++ b/rwsdk/include/d3d8/rtslerp.h @@ -18,7 +18,7 @@ /** * \defgroup rtslerp RtSlerp - * \ingroup rttool + * \ingroup mathtools * * Slerp/Spherical Linear Interpolations Toolkit for RenderWare. * diff --git a/rwsdk/include/d3d8/rtslerp.rpe b/rwsdk/include/d3d8/rtslerp.rpe index 847ccb00..64bd7571 100644 --- a/rwsdk/include/d3d8/rtslerp.rpe +++ b/rwsdk/include/d3d8/rtslerp.rpe @@ -146,472 +146,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtsplpvs.h b/rwsdk/include/d3d8/rtsplpvs.h index 38ae118f..419717a1 100644 --- a/rwsdk/include/d3d8/rtsplpvs.h +++ b/rwsdk/include/d3d8/rtsplpvs.h @@ -12,7 +12,7 @@ /** * \defgroup rtsplinepvs RtSplinePVS - * \ingroup rttool + * \ingroup pvs * * Spline PVS Toolkit for RenderWare. */ diff --git a/rwsdk/include/d3d8/rtsplpvs.rpe b/rwsdk/include/d3d8/rtsplpvs.rpe index d436b610..9736cbbc 100644 --- a/rwsdk/include/d3d8/rtsplpvs.rpe +++ b/rwsdk/include/d3d8/rtsplpvs.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rttiff.h b/rwsdk/include/d3d8/rttiff.h index 9dbf22c8..b5d0ec00 100644 --- a/rwsdk/include/d3d8/rttiff.h +++ b/rwsdk/include/d3d8/rttiff.h @@ -11,7 +11,7 @@ /** * \defgroup rttiff RtTIFF - * \ingroup rttool + * \ingroup imageconversiontools * * TIFF/Tag Image File Format Image Format Toolkit for RenderWare. * diff --git a/rwsdk/include/d3d8/rttiff.rpe b/rwsdk/include/d3d8/rttiff.rpe index f82c7d82..260b2329 100644 --- a/rwsdk/include/d3d8/rttiff.rpe +++ b/rwsdk/include/d3d8/rttiff.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rttilerd.h b/rwsdk/include/d3d8/rttilerd.h index f11b703b..7cb8f887 100644 --- a/rwsdk/include/d3d8/rttilerd.h +++ b/rwsdk/include/d3d8/rttilerd.h @@ -11,7 +11,7 @@ /** * \defgroup rttilerender RtTileRender - * \ingroup rttool + * \ingroup cameras * * Tile renderer - e.g. grabbing screen shots - Toolkit for RenderWare. */ diff --git a/rwsdk/include/d3d8/rttilerd.rpe b/rwsdk/include/d3d8/rttilerd.rpe index 78222d06..15c929f9 100644 --- a/rwsdk/include/d3d8/rttilerd.rpe +++ b/rwsdk/include/d3d8/rttilerd.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rttoc.h b/rwsdk/include/d3d8/rttoc.h index 02893aa8..88926062 100644 --- a/rwsdk/include/d3d8/rttoc.h +++ b/rwsdk/include/d3d8/rttoc.h @@ -1,37 +1,38 @@ -/*************************************************************************** - * * - * Module : rttoc.h * - * * - * Purpose : Table Of Contents (TOC) * - * * - **************************************************************************/ +/****************************************************************************** + * * + * Module : rttoc.h * + * * + * Purpose : Table Of Contents (TOC) * + * * + ******************************************************************************/ #ifndef RTTOC_H #define RTTOC_H /** * \defgroup rttoc RtTOC - * \ingroup rttool + * \ingroup streaming * - * Table Of Contents (TOC) - e.g. creating a TOC for a RwStream. + * Table Of Contents (TOC) - creating a TOC for a stream. */ -/**************************************************************************** +/****************************************************************************** Includes */ #include "rwcore.h" #include "rpcriter.h" -/**************************************************************************** +/****************************************************************************** Defines */ -/**************************************************************************** +/****************************************************************************** Global Types */ typedef struct _rtTOCGUID _rtTOCGUID; +#if (!defined(DOXYGEN)) struct _rtTOCGUID { RwUInt32 data1; @@ -39,20 +40,22 @@ struct _rtTOCGUID RwUInt16 data3; RwUInt8 data4[8]; }; +#endif /* (!defined(DOXYGEN)) */ typedef struct RtTOCEntry RtTOCEntry; /** * \ingroup rttoc * \struct RtTOCEntry * - * BLAH + * A Table Of Contents (TOC) entry structure. */ struct RtTOCEntry { - RwCorePluginID id; /**< Chunk ID */ - RwUInt32 offset;/**< Offset of chunk from the start of the file - * including TOC */ - _rtTOCGUID guid; /**< GUID */ + RwCorePluginID id; /**< Chunk ID */ + RwUInt32 gid; /**< Game ID */ + RwUInt32 offset; /**< Offset of chunk from the start of the file + including TOC */ + _rtTOCGUID guid; /**< GUID */ }; typedef struct RtTOC RtTOC; @@ -60,16 +63,16 @@ typedef struct RtTOC RtTOC; /** * \ingroup rttoc * \struct RtTOC - * - * BLAH + * + * Table Of Contents (TOC) structure. */ struct RtTOC { - RwInt32 numEntries; /**< Number of entries*/ - RtTOCEntry entry[1]; /**< Entry*/ + RwInt32 numEntries; /**< Number of entries */ + RtTOCEntry entry[1]; /**< Entry */ }; -/**************************************************************************** +/****************************************************************************** Function prototypes */ diff --git a/rwsdk/include/d3d8/rttoc.rpe b/rwsdk/include/d3d8/rttoc.rpe index 796f8de5..706372f2 100644 --- a/rwsdk/include/d3d8/rttoc.rpe +++ b/rwsdk/include/d3d8/rttoc.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtvcat.rpe b/rwsdk/include/d3d8/rtvcat.rpe index 464ca886..ef5e286e 100644 --- a/rwsdk/include/d3d8/rtvcat.rpe +++ b/rwsdk/include/d3d8/rtvcat.rpe @@ -129,472 +129,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rtworld.h b/rwsdk/include/d3d8/rtworld.h index fef3e17c..727d8122 100644 --- a/rwsdk/include/d3d8/rtworld.h +++ b/rwsdk/include/d3d8/rtworld.h @@ -14,7 +14,7 @@ /** * \defgroup rtworld RtWorld - * \ingroup rttool + * \ingroup basicgeometry * * World Import Toolkit for RenderWare. */ diff --git a/rwsdk/include/d3d8/rtworld.rpe b/rwsdk/include/d3d8/rtworld.rpe index bc20947e..83449720 100644 --- a/rwsdk/include/d3d8/rtworld.rpe +++ b/rwsdk/include/d3d8/rtworld.rpe @@ -128,472 +128,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rwsdk/include/d3d8/rwcore.h b/rwsdk/include/d3d8/rwcore.h index b9214c63..583de35f 100644 --- a/rwsdk/include/d3d8/rwcore.h +++ b/rwsdk/include/d3d8/rwcore.h @@ -22,7 +22,7 @@ /************************************************************************* * * Filename: - * Automatically Generated on: Wed Jul 10 10:45:00 2002 + * Automatically Generated on: Thu Jan 23 11:06:24 2003 * ************************************************************************/ @@ -94,6 +94,7 @@ typedef struct rxHeapSuperBlockDescriptor rxHeapSuperBlockDescriptor; typedef struct RxHeap RxHeap; typedef struct rxHeapBlockHeader rxHeapBlockHeader; +#if (!defined(DOXYGEN)) struct rxHeapFreeBlock { RwUInt32 size; @@ -106,6 +107,7 @@ struct rxHeapSuperBlockDescriptor RwUInt32 size; rxHeapSuperBlockDescriptor *next; }; +#endif /* (!defined(DOXYGEN)) */ /** * \ingroup rwcoregeneric @@ -124,6 +126,7 @@ struct RxHeap * the heap needs resetting or not. */ }; +#if (!defined(DOXYGEN)) struct rxHeapBlockHeader { /* present in all blocks (used & unused) */ @@ -132,6 +135,7 @@ struct rxHeapBlockHeader rxHeapFreeBlock *freeEntry; /* (or null) */ RwUInt32 pad[4]; /* alignment padding to 32 bytes */ }; +#endif /* (!defined(DOXYGEN)) */ /* This wrapper cheaply early-outs when a heap doesn't *need* resetting */ #define RxHeapReset(heap) \ @@ -356,8 +360,7 @@ struct RxIoSpec /** * \ingroup rwcoregeneric - * \typedef RxNodeBodyFn - * is the callback to be + * \ref RxNodeBodyFn is the callback to be * called during pipeline execution -- and, typically, process * \ref RxPacket's -- for the owning pipeline node. * @@ -373,7 +376,7 @@ typedef RwBool (*RxNodeBodyFn) (RxPipelineNode * self, /** * \ingroup rwcoregeneric - * \typedef RxNodeInitFn + * \ref RxNodeInitFn * is the callback to be called, * for the owning node definition, the first time an \ref RxPipeline * referencing that node definition is unlocked. @@ -388,7 +391,7 @@ typedef RwBool (*RxNodeInitFn) (RxNodeDefinition * self); /** * \ingroup rwcoregeneric - * \typedef RxNodeTermFn + * \ref RxNodeTermFn * is the callback to be called, * for the owning node definition, the last time an \ref RxPipeline * referencing that node definition is destroyed or locked. @@ -403,7 +406,7 @@ typedef void (*RxNodeTermFn) (RxNodeDefinition * self); /** * \ingroup rwcoregeneric - * \typedef RxPipelineNodeInitFn + * \ref RxPipelineNodeInitFn * is the callback to be called, for the owning pipeline node, whenever a * \ref RxPipeline containing that that pipeline node is unlocked. * @@ -417,7 +420,7 @@ typedef RwBool (*RxPipelineNodeInitFn) (RxPipelineNode * self); /** * \ingroup rwcoregeneric - * \typedef RxPipelineNodeTermFn + * \ref RxPipelineNodeTermFn * is the callback to be called, for the owning pipeline node, whenever a * \ref RxPipeline containing that that pipeline node is locked or * destroyed. @@ -432,14 +435,14 @@ typedef void (*RxPipelineNodeTermFn) (RxPipelineNode * self); /** * \ingroup rwcoregeneric - * \typedef RxPipelineNodeConfigFn + * \ref RxPipelineNodeConfigFn * is the callback to be called, for the owning pipeline node, whenever a * \ref RxPipeline containing that that pipeline node is unlocked, * *after* all \ref RxPipelineNodeInitFn's have been called for the * pipeline in question. This func is to be used as described in * RxPipelineNodeSendConfigMsg. * - * \param self A pointer to the pipeline node + * \param self A pointer to the pipeline node * \param pipeline A pointer to the containing pipeline * * \return TRUE on success, FALSE otherwise. @@ -449,21 +452,22 @@ typedef void (*RxPipelineNodeTermFn) (RxPipelineNode * self); typedef RwBool (*RxPipelineNodeConfigFn) (RxPipelineNode * self, RxPipeline * pipeline); -/* - removed from the API Reference January 2002 - - typedef RxConfigMsgHandlerFn - is the callback to be called, for the owning pipeline node, whenever - a message is sent to it by the ref RxPipelineNodeConfigFn of another - pipeline node in the same pipeline. See ref RxPipelineNodeSendConfigMsg. - - param self A pointer to the pipeline node - param msg Message ID - param intparam Meaning is message-specific - param ptrparam Meaning is message-specific - - return A RwInt32 value, 0: unserviced; -ve: error; +ve: informative success - - see RxNodeMethods - */ +/** + * \ingroup rwcoregeneric + * \ref RxConfigMsgHandlerFn + * is the callback to be called, for the owning pipeline node, whenever + * a message is sent to it by the \ref RxPipelineNodeConfigFn of another + * pipeline node in the same pipeline. See \ref RxPipelineNodeSendConfigMsg. + * + * \param self A pointer to the pipeline node + * \param msg Message ID + * \param intparam Meaning is message-specific + * \param ptrparam Meaning is message-specific + * + * \return A RwInt32 value, 0: unserviced; -ve: error; +ve: informative success + * + * \see RxNodeMethods + */ typedef RwUInt32 (*RxConfigMsgHandlerFn) (RxPipelineNode * self, RwUInt32 msg, RwUInt32 intparam, @@ -706,7 +710,7 @@ struct RxPipeline /** * \ingroup rwcoregeneric - * \typedef RxPipelineNodeOutputCallBack + * \ref RxPipelineNodeOutputCallBack * is the callback function supplied * to \ref RxPipelineNodeForAllConnectedOutputs. * @@ -716,11 +720,11 @@ struct RxPipeline * data structure (callbackdata). If no such structure was specified, this * will be NULL. * - * \param node A pointer to the pipeline node whose outputs - * are being traversed + * \param node A pointer to the pipeline node whose outputs + * are being traversed * \param outputnode A pointer to the current output - * pipeline node - * \param callbackdata A pointer to optional user-supplied data + * pipeline node + * \param callbackdata A pointer to optional user-supplied data * * \return Returns a pointer to the \ref RxPipelineNode whose outputs are being * traversed, or NULL to terminate traversal @@ -744,6 +748,9 @@ extern "C" { #endif /* __cplusplus */ +extern void +RxPipelineSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwBool _rxPipelineOpen(void); @@ -988,19 +995,19 @@ MACRO_STOP /** * \ingroup rwcoregeneric - * \typedef RxNodeOutput + * \ref RxNodeOutput * typedef for a reference to an output of a pipeline node */ typedef RwUInt32 *RxNodeOutput; /** * \ingroup rwcoregeneric - * \typedef RxNodeInput + * \ref RxNodeInput * typedef for a reference to the input of a pipeline node */ typedef RxPipelineNode *RxNodeInput; /** * \ingroup rwcoregeneric - * \typedef RxLockedPipe + * \ref RxLockedPipe * typedef for a reference to a locked pipeline */ typedef RxPipeline RxLockedPipe; @@ -1119,275 +1126,6 @@ RxPipelineInsertDebugNode(RxPipeline *pipeline, /*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/p2altmdl.h ---*/ -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeTransform.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetTransform(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeSubmitTriangle.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetSubmitTriangle(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeSubmitLine.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetSubmitLine(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeScatter.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetScatter(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeClone.h ---*/ - -typedef struct RxPacketCacheCluster RxPacketCacheCluster; - -/** - * \ingroup rwcoregeneric - * \struct RxPacketCacheCluster - * structure containing a cache of an \ref RxCluster's - * within an \ref RxPacketCache - */ -struct RxPacketCacheCluster -{ - RwUInt32 slot; /**< A \ref RwUInt32 index into the \ref RxPacketCache's - * array of RxPacketCacheCluster's */ - RwUInt16 flags; /**< A cache of the original cluster's flags */ - RwUInt16 stride; /**< A cache of the original cluster's stride */ - void *data; /**< A cache of the original cluster's data */ - RwUInt32 numAlloced; /**< A cache of the original cluster's numAlloced */ - RwUInt32 numUsed; /**< A cache of the original cluster's numUsed */ - RxPipelineCluster *clusterRef; /**< A cache of the original cluster's \ref RxPipelineCluster */ -}; -typedef struct RxPacketCache RxPacketCache; - -/** - * \ingroup rwcoregeneric - * \struct RxPacketCache - * structure containing a cache of a \ref RxPacket */ -struct RxPacketCache -{ - RwUInt16 packetFlags; /**< A cache of the original packet's flags */ - RwUInt16 pad[1]; /**< Alignment padding */ - RwUInt32 numClusters; /**< The number of present clusters in the - * original packet when it was cloned */ - RwBool lastCloneDone;/**< Once the cache has been cloned by \ref RxPacketCacheClone - * with (lastClone == TRUE), it should not be used again! */ - RwUInt32 pad2[1]; /**< Alignment padding */ - RxPacketCacheCluster clusters[1]; /**< An array of \ref RxPacketCacheCluster's, - * extending beyond 1 element */ -}; - - -typedef struct RxNodeCloneInitData RxNodeCloneInitData; -/** - * \ingroup rwcoregeneric - * \struct RxNodeCloneInitData - * structure with which to initialize - * clone a \ref RxNodeDefinition, - * through \ref RxNodeDefinitionCloneCreate and - * set up cloned \ref RxPipelineNode modes, through - * \ref RxPipelineNodeCloneDefineModes */ -struct RxNodeCloneInitData -{ - RwUInt32 numModes; /**< Specifies the number of modes in - which the node should operate */ - RwUInt32 numOutputs; /**< Specifies the number of outputs of this - Clone node, which is also the maximum - number of outputs to which any one mode - may dispatch packets */ - RwUInt32 *modeSizes; /**< Specifies the number of outputs to which - each mode dispatches packets */ - RwUInt32 **modes; /**< An array of numModes pointers to arrays - (of length numOutputs) specifying the - outputs, in order, to which each mode - should dispatch packets (output zero is - the first output) */ -}; - -/** - * \ingroup rwcoregeneric - * \struct RxNodeCloneData - * structure which is the private - * data of Clone nodes \ref RxPipelineNode */ -typedef struct RxNodeCloneData RxNodeCloneData; -struct RxNodeCloneData -{ - RwBool optimized; /**< \ref RwBool specifying whether \ref RxPipelineNodeCloneOptimize - * has been run on this \ref RxPipelineNode yet */ - RwUInt32 currentMode; /**< \ref RwUInt32 The current mode of operation */ - RxNodeCloneInitData *data;/**< A pointer to \ref RxNodeCloneInitData data - * specifying the modes of operation */ -}; - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionCloneCreate(RxNodeCloneInitData *data); -extern RwBool RxPipelineNodeCloneDefineModes( - RxPipeline *pipeline, - RxPipelineNode *node, - RxNodeCloneInitData *data); -extern RwBool RxNodeDefinitionCloneDestroy(RxNodeDefinition *def); -extern RwBool RxPipelineNodeCloneOptimize(RxPipeline *pipeline, - RxPipelineNode *node); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeImmStash.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetImmStash(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeImmRenderSetup.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetImmRenderSetup(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeImmMangleTriangleIndices.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetImmMangleTriangleIndices(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeImmMangleLineIndices.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetImmMangleLineIndices(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeImmInstance.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetImmInstance(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeCullTriangle.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition * RxNodeDefinitionGetCullTriangle(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeClipTriangle.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetClipTriangle(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -/*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/nodeClipLine.h ---*/ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -extern RxNodeDefinition *RxNodeDefinitionGetClipLine(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - /*--- Automatically derived from: C:/daily/rwsdk/driver/d3d8/d3d8texdic.h ---*/ /*--- Automatically derived from: C:/daily/rwsdk/driver/d3d8/d3d8rendst.h ---*/ @@ -1415,7 +1153,7 @@ extern RxNodeDefinition *RxNodeDefinitionGetClipLine(void); */ /** - * \ingroup datatypes + * \ingroup rwraster * \ref RwRasterLockMode represents the options available for locking * a raster so that it may be modified (see API function \ref RwRasterLock). An * application may wish to write to the raster, read from the raster or @@ -1445,7 +1183,7 @@ enum RwRasterLockMode typedef enum RwRasterLockMode RwRasterLockMode; /** - * \ingroup datatypes + * \ingroup rwraster * \ref RwRasterFlipMode represents * raster flip modes */ enum RwRasterFlipMode @@ -1457,7 +1195,7 @@ enum RwRasterFlipMode typedef enum RwRasterFlipMode RwRasterFlipMode; /** - * \ingroup datatypes + * \ingroup rwraster * RwRasterType * This type represents the options available for creating a new * raster (se API function \ref RwRasterCreate)*/ @@ -1476,7 +1214,7 @@ enum RwRasterType typedef enum RwRasterType RwRasterType; /** - * \ingroup datatypes + * \ingroup rwraster * \ref RwRasterFormat is a set of values and flags which may be combined to * specify a raster format. The format chosen for a particular raster depends * on the hardware device and the raster type specified at creation time @@ -1569,8 +1307,8 @@ typedef enum RwRasterPrivateFlag RwRasterPrivateFlag; */ /** - * \ingroup datatypes - * \typedef RwRaster + * \ingroup rwraster + * \struct RwRaster * Raster containing device-dependent pixels. * This should be considered an opaque type. * Use the RwRaster API functions to access. @@ -1661,6 +1399,8 @@ extern "C" #endif /* __cplusplus */ /* Creating destroying rasters */ +extern void RwRasterSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwRaster *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags); extern RwBool RwRasterDestroy(RwRaster * raster); @@ -1743,8 +1483,6 @@ extern RwBool RwRasterValidatePlugins(const RwRaster * raster); #endif /* (defined(__ICL)) */ -#include - #if (defined(RWDEBUG)) #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) #define _CRTDBG_MAP_ALLOC @@ -1837,48 +1575,16 @@ MACRO_START \ } \ MACRO_STOP -/* LEGACY-SUPPORT macros */ -#define RWIM2DVERTEXSetCameraX(vert, camx) RwIm2DVertexSetCameraX(vert, camx) -#define RWIM2DVERTEXSetCameraY(vert, camy) RwIm2DVertexSetCameraY(vert, camy) -#define RWIM2DVERTEXSetCameraZ(vert, camz) RwIm2DVertexSetCameraZ(vert, camz) -#define RWIM2DVERTEXSetRecipCameraZ(vert, recipz) \ - RwIm2DVertexSetRecipCameraZ(vert, recipz) -#define RWIM2DVERTEXGetCameraX(vert) RwIm2DVertexGetCameraX(vert) -#define RWIM2DVERTEXGetCameraY(vert) RwIm2DVertexGetCameraY(vert) -#define RWIM2DVERTEXGetCameraZ(vert) RwIm2DVertexGetCameraZ(vert) -#define RWIM2DVERTEXGetRecipCameraZ(vert) RwIm2DVertexGetRecipCameraZ(vert) -#define RWIM2DVERTEXSetScreenX(vert, scrnx) RwIm2DVertexSetScreenX(vert, scrnx) -#define RWIM2DVERTEXSetScreenY(vert, scrny) RwIm2DVertexSetScreenY(vert, scrny) -#define RWIM2DVERTEXSetScreenZ(vert, scrnz) RwIm2DVertexSetScreenZ(vert, scrnz) -#define RWIM2DVERTEXGetScreenX(vert) RwIm2DVertexGetScreenX(vert) -#define RWIM2DVERTEXGetScreenY(vert) RwIm2DVertexGetScreenY(vert) -#define RWIM2DVERTEXGetScreenZ(vert) RwIm2DVertexGetScreenZ(vert) -#define RWIM2DVERTEXSetU(vert, u, recipz) RwIm2DVertexSetU(vert, u, recipz) -#define RWIM2DVERTEXSetV(vert, v, recipz) RwIm2DVertexSetV(vert, v, recipz) -#define RWIM2DVERTEXGetU(vert) RwIm2DVertexGetU(vert) -#define RWIM2DVERTEXGetV(vert) RwIm2DVertexGetV(vert) -#define RWIM2DVERTEXSetRealRGBA(vert, red, green, blue, alpha) \ - RwIm2DVertexSetRealRGBA(vert, red, green, blue, alpha) -#define RWIM2DVERTEXSetIntRGBA(vert, red, green, blue, alpha) \ - RwIm2DVertexSetIntRGBA(vert, red, green, blue, alpha) -#define RWIM2DVERTEXGetRed(vert) RwIm2DVertexGetRed(vert) -#define RWIM2DVERTEXGetGreen(vert) RwIm2DVertexGetGreen(vert) -#define RWIM2DVERTEXGetBlue(vert) RwIm2DVertexGetBlue(vert) -#define RWIM2DVERTEXGetAlpha(vert) RwIm2DVertexGetAlpha(vert) -#define RWIM2DVERTEXCopyRGBA(dst, src) RwIm2DVertexCopyRGBA(dst, src) -#define RWIM2DVERTEXClipRGBA(o, i, n, f) RwIm2DVertexClipRGBA(o, i, n, f) - /**************************************************************************** Global Types */ /* We use RwD3D8Vertex to drive the hardware in 2D mode */ -/** - * \ingroup rwcoredriverd3d8 - * \typedef RwD3D8Vertex +/* * D3D8 vertex structure definition for 2D geometry */ +#if !defined(RWADOXYGENEXTERNAL) typedef struct RwD3D8Vertex RwD3D8Vertex; /** * \ingroup rwcoredriverd3d8 @@ -1897,47 +1603,41 @@ struct RwD3D8Vertex RwReal u; /**< Texture coordinate U */ RwReal v; /**< Texture coordinate V */ }; +#endif /* !defined(RWADOXYGENEXTERNAL) */ /* Define types used */ +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \typedef RwIm2DVertex + * \ref RwIm2DVertex * Typedef for a RenderWare Graphics Immediate Mode 2D Vertex */ typedef RwD3D8Vertex RwIm2DVertex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ -/* LEGACY-SUPPORT macro */ +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \def RWIM2DVERTEX - * RWIM2DVERTEX is a legacy macro for RwIm2DVertex - */ -#define RWIM2DVERTEX RwIm2DVertex - -/** - * \ingroup rwcoredriverd3d8 - * \typedef RxVertexIndex + * \ref RxVertexIndex * * Typedef for a RenderWare Graphics PowerPipe Immediate * Mode Vertex */ typedef RwUInt16 RxVertexIndex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ + +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \typedef RwImVertexIndex + * \ref RwImVertexIndex * Typedef for a RenderWare Graphics Immediate Mode Vertex. */ typedef RxVertexIndex RwImVertexIndex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ -/* LEGACY-SUPPORT macro */ -/** - * \ingroup rwcoredriverd3d8 - * \def RWIMVERTEXINDEX - * RWIMVERTEXINDEX is a legacy macro for RwImVertexIndex - */ -#define RWIMVERTEXINDEX RwImVertexIndex +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 @@ -1950,8 +1650,10 @@ typedef struct RwUInt32 numTextureStageStateChanges; /**< Number of Texture Stage States changed */ RwUInt32 numMaterialChanges; /**< Number of Material changes */ RwUInt32 numLightsChanged; /**< Number of Lights changed */ + RwUInt32 numVBSwitches; /**< Number of Vertex Buffer switches */ } RwD3D8Metrics; +#endif /* !defined(RWADOXYGENEXTERNAL) */ #endif /* D3D8_DRVMODEL_H */ @@ -1973,15 +1675,13 @@ RwD3D8Metrics; /* We use D3D8 formats for the instanced versions, to allow hardware T&L */ -/** - * \ingroup corep2d3d8 - * \typedef RxObjSpace3DVertex +/* * Typedef for an RxObjSpace3DVertex. */ typedef struct RxObjSpace3DVertex RxObjSpace3DVertex; /** - * \ingroup corep2d3d8 + * \ingroup cored3d8 * \struct RxObjSpace3DVertex * Structure representing object space vertex. */ @@ -2000,21 +1700,25 @@ struct RxObjSpace3DVertex #define RxObjSpace3DVertexFullSize (sizeof(RxObjSpace3DVertex)) /** - * \ingroup corep2d3d8 - * \typedef RxObjSpace3DLitVertex + * \ingroup cored3d8 + * \ref RxObjSpace3DLitVertex * Typedef for an RxObjSpace3DLitVertex. */ typedef RxObjSpace3DVertex RxObjSpace3DLitVertex; /** - * \ingroup corep2d3d8 - * \typedef RwIm3DVertex + * \ingroup cored3d8 + * \ref RwIm3DVertex * Typedef for an RwIm3DVertex. */ typedef RxObjSpace3DLitVertex RwIm3DVertex; /* LEGACY-SUPPORT macro */ -#define RWIM3DVERTEX RwIm3DVertex +/** + * \ingroup cored3d8 + * \ref RxScrSpace2DVertex + * Typedef for an RxScrSpace2DVertex structure + */ typedef RwIm2DVertex RxScrSpace2DVertex; /**************************************************************************** @@ -2161,55 +1865,6 @@ MACRO_STOP #define RwIm3DVertexCopyRGBA(_dst, _src) (((_dst)->color) = ((_src)->color)) -/* LEGACY-SUPPORT macros */ -#define RWIM2DCAMERAVERTEXSetU(_devvert, _camvert, _u, _recipz) \ - RwIm2DCameraVertexSetU(_devvert, _camvert, _u, _recipz) -#define RWIM2DCAMERAVERTEXSetV(_devvert, _camvert, _v, _recipz) \ - RwIm2DCameraVertexSetV(_devvert, _camvert, _v, _recipz) -#define RWIM3DVERTEXGetNext(vert) RwIm3DVertexGetNext(vert) -#define RWIM3DVERTEXSetPos(vert, imx, imy, imz) RwIm3DVertexSetPos(vert, imx, imy, imz) -#define RWIM3DVERTEXGetPos(vert) RwIm3DVertexGetPos(vert) -#define RWIM3DVERTEXSetU(vert, imu) RwIm3DVertexSetU(vert, imu) -#define RWIM3DVERTEXSetV(vert, imv) RwIm3DVertexSetV(vert, imv) -#define RWIM3DVERTEXSetRGBA(vert, r, g, b, a) RwIm3DVertexSetRGBA(vert, r, g, b, a) -#define RWIM3DVERTEXSetNormal(vert, imx, imy, imz) RwIm3DVertexSetNormal(vert, imx, imy, imz) -#define RWIM3DVERTEXCopyRGBA(dst,src) RwIm3DVertexCopyRGBA(dst,src) -#define RXOBJSPACE3DVERTEXGetPos(_vert, _pos) \ - RxObjSpace3DVertexGetPos(_vert, _pos) -#define RXOBJSPACE3DVERTEXSetPos(_vert, _pos) \ - RxObjSpace3DVertexSetPos(_vert, _pos) -#define RXOBJSPACE3DVERTEXGetPreLitColor(_vert, _col) \ - RxObjSpace3DVertexGetPreLitColor(_vert, _col) -#define RXOBJSPACE3DVERTEXSetPreLitColor(_vert, _col) \ - RxObjSpace3DVertexSetPreLitColor(_vert, _col) -#define RXOBJSPACE3DVERTEXGetColor RxObjSpace3DVertexGetColor -#define RXOBJSPACE3DVERTEXGetNormal(_vert, _normal) \ - RxObjSpace3DVertexGetNormal(_vert, _normal) -#define RXOBJSPACE3DVERTEXSetNormal(_vert, _normal) \ - RxObjSpace3DVertexSetNormal(_vert, _normal) -#define RXOBJSPACE3DVERTEXGetU(_vert) RxObjSpace3DVertexGetU(_vert) -#define RXOBJSPACE3DVERTEXGetV(_vert) RxObjSpace3DVertexGetV(_vert) -#define RXOBJSPACE3DVERTEXSetU(_vert, _imu) \ - RxObjSpace3DVertexSetU(_vert, _imu) -#define RXOBJSPACE3DVERTEXSetV(_vert, _imv) \ - RxObjSpace3DVertexSetV(_vert, _imv) -#define RXOBJSPACE3DLITVERTEXGetPos(vert, pos) \ - RxObjSpace3DLitVertexGetPos(vert, pos) -#define RXOBJSPACE3DLITVERTEXSetPos(vert, pos) \ - RxObjSpace3DLitVertexSetPos(vert, pos) -#define RXOBJSPACE3DLITVERTEXGetColor(vert, col) \ - RxObjSpace3DLitVertexGetColor(vert, col) -#define RXOBJSPACE3DLITVERTEXSetColor(vert, col) \ - RxObjSpace3DLitVertexSetColor(vert, col) -#define RXOBJSPACE3DLITVERTEXGetU(vert) \ - RxObjSpace3DLitVertexGetU(vert) -#define RXOBJSPACE3DLITVERTEXGetV(vert) \ - RxObjSpace3DLitVertexGetV(vert) -#define RXOBJSPACE3DLITVERTEXSetU(vert, imu) \ - RxObjSpace3DLitVertexSetU(vert, imu) -#define RXOBJSPACE3DLITVERTEXSetV(vert, imv) \ - RxObjSpace3DLitVertexSetV(vert, imv) - /*--- Automatically derived from: C:/daily/rwsdk/src/pipe/p2/p2renderstate.h ---*/ @@ -2224,7 +1879,6 @@ enum RxRenderStateFlag rxRENDERSTATEFLAG_ZWRITEENABLE = 0x00000004, /** - * Automatically Generated on: Wed Jul 10 10:45:00 2002 + * Automatically Generated on: Thu Jan 23 11:06:23 2003 * ************************************************************************/ @@ -68,6 +68,7 @@ typedef struct _RwUInt64 RwUInt64; typedef struct _RwInt64 RwInt64; /* We'll do it with structures (can't do maths on these, but OK for allocation): */ +#if (!defined(DOXYGEN)) #ifdef rwBIGENDIAN struct _RwUInt64 { @@ -99,6 +100,7 @@ struct _RwInt64 #error "ENDIAN-ness undefined!" #endif /* rwLITTLEENDIAN */ #endif /* rwBIGENDIAN */ +#endif /* (!defined(DOXYGEN)) */ #define RWZERO64 { (RwUInt32)0, (RwUInt32)0 } #endif /* _MSC_VER */ @@ -108,7 +110,8 @@ typedef struct _RwInt128 RwInt128; /* We'll do it with structures * (can't do maths on these, but OK for allocation): */ -#ifdef rwBIGENDIAN +#if (!defined(DOXYGEN)) +#ifdef rwBIGENDIAN struct _RwUInt128 { RwUInt64 top; @@ -139,6 +142,7 @@ struct _RwInt128 #error "ENDIAN-ness undefined!" #endif /* rwLITTLEENDIAN */ #endif /* rwBIGENDIAN */ +#endif /* (!defined(DOXYGEN)) */ #define RWZERO128 { RWZERO64, RWZERO64 } @@ -160,6 +164,10 @@ struct _RwInt128 #define rwFRAMEALIGNMENT sizeof(RwUInt32) #define rwV4DALIGNMENT sizeof(RwUInt32) +#if (!defined(rwMALLOCALIGNMENT)) +#define rwMALLOCALIGNMENT sizeof(RwUInt32) +#endif /* (!defined(rwMALLOCALIGNMENT) */ + #if (defined(_MSC_VER)) #if (defined(RWVERBOSE)) @@ -501,7 +509,7 @@ int32fromreal(RwReal x) #if (!defined(NOASM)) static __inline RwUInt32 -RwFastRealToUInt32(RwReal x) +RwFastRealToUInt32Inline(RwReal x) { RwUInt32 res; @@ -510,6 +518,9 @@ RwFastRealToUInt32(RwReal x) return(res); } + +#define RwFastRealToUInt32 RwFastRealToUInt32Inline + #endif /* (defined(NOASM)) */ #endif /* (defined(_MSC_VER)) */ @@ -627,11 +638,14 @@ do \ while(0) typedef union _rwIEEEFloatShapeType _rwIEEEFloatShapeType; + +#if (!defined(DOXYGEN)) union _rwIEEEFloatShapeType { float value; unsigned int word; }; +#endif /* (!defined(DOXYGEN)) */ #define _RW_GET_FLOAT_WORD(i,d) \ do { \ @@ -949,13 +963,13 @@ while(0) #if (!defined(rwSqrt)) /* NOTE: this is overloaded in drvmodel.h for some targets (SKY2 and XBOX atm) * [we do in fact do overload w/ sqrtf there, if RW_USE_SPF, - * for D3D7, D3D8, OpenGL and SoftRas] */ + * for D3D8, OpenGL and SoftRas] */ #define rwSqrt(_result, _x) rwSqrtMacro(_result, _x) #endif /* (!defined(rwSqrt)) */ #if (!defined(rwInvSqrt)) /* NOTE: this is overloaded in drvmodel.h for some targets (SKY2 and XBOX atm) * [we do in fact do overload w/ (1 / sqrtf) there, if RW_USE_SPF, - * for D3D7, D3D8, OpenGL and SoftRas] */ + * for D3D8, OpenGL and SoftRas] */ #define rwInvSqrt(_recip, _x) rwInvSqrtMacro(_recip, _x) #endif /* (!defined(rwInvSqrt)) */ #if (!defined(RwTan)) @@ -977,7 +991,22 @@ while(0) /*--- Automatically derived from: C:/daily/rwsdk/src/plcore/batypes.h ---*/ #define rwLIBRARYBASEVERSION 0x31000 -#define rwLIBRARYCURRENTVERSION 0x33002 +#define rwLIBRARYCURRENTVERSION 0x34005 + +#define rwLIBRARYVERSION31000 0x31000 +#if (rwLIBRARYVERSION31000 < rwLIBRARYBASEVERSION) +#error "Time to remove all rwLIBRARYVERSION31000 code" +#endif + +#define rwLIBRARYVERSION34001 0x34001 +#if (rwLIBRARYVERSION34001 < rwLIBRARYBASEVERSION) +#error "Time to remove all rwLIBRARYVERSION34001 code" +#endif + +#define rwLIBRARYVERSION34002 0x34002 +#if (rwLIBRARYVERSION34002 < rwLIBRARYBASEVERSION) +#error "Time to remove all rwLIBRARYVERSION34002 code" +#endif /* * RWBUILDNUMBER @@ -993,14 +1022,16 @@ while(0) * The following Doxygen comment MUST be copied into RwCore.h, * so don't move it from here. */ +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup rwcore - * \page rwcoreoverview Core Library Overview + * \ingroup fundamentaltypes + * \page fundtypesoverview Fundamental Types Overview * - * LIBRARY: rwcore.lib - * HEADER: rwcore.h + * \par Requirements + * \li \b Headers: rwcore.h + * \li \b Libraries: rwcore.lib * - * This library provides the fundamental RenderWare features. + * The rwcore.lib library provides the fundamental RenderWare features. * * When creating a RenderWare application, this library must always be * linked. @@ -1024,7 +1055,7 @@ while(0) * supplied User Guide. The RenderWare Engine \ref rwengine API is * usually the starting point for new developers. */ - +#endif /* RWADOXYGENEXTERNAL */ #if (!defined(RWFORCEENUMSIZEINT)) #define RWFORCEENUMSIZEINT ((RwInt32)((~((RwUInt32)0))>>1)) @@ -1157,7 +1188,6 @@ while(0) #if (defined(RWDEBUG) && defined(RWVERBOSE)) -/* #include */ #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) #define _CRTDBG_MAP_ALLOC #endif /* defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) */ @@ -1189,6 +1219,8 @@ while(0) /* NB volatile keyword required for VC5.0 to ensure a reload - AMB */ typedef union RwSplitBits RwSplitBits; + +#if (!defined(DOXYGEN)) union RwSplitBits { RwReal nReal; @@ -1219,6 +1251,7 @@ struct RwSplitFixed #endif /* rwBIGENDIAN */ typedef union RwUnionReal RwUnionReal; + union RwUnionReal /* MSB is sign bit in any circumstance */ { RwReal real; /* 4 bytes interpreted as RwReal */ @@ -1226,6 +1259,7 @@ union RwUnionReal /* MSB is sign bit in any circumstance */ RwFixed fixed; /* 4 bytes interpreted as 16:16 fixed */ RwSplitFixed splitfixed; /* 4 bytes interpreted as 16:16 fixed */ }; +#endif /* (!defined(DOXYGEN)) */ /*****************/ @@ -1233,14 +1267,9 @@ union RwUnionReal /* MSB is sign bit in any circumstance */ /*****************/ -/** - * \ingroup datatypes - * \typedef RwV2d - * typedef for struct RwV2d - */ typedef struct RwV2d RwV2d; /** - * \ingroup datatypes + * \ingroup rwv2d * \struct RwV2d * This type represents points in a 2D space, such as device * space, specified by the (x, y) coordinates of the point. @@ -1251,14 +1280,9 @@ struct RwV2d RwReal y; /**< Y vlaue */ }; -/** - * \ingroup datatypes - * \typedef RwV3d - * typedef for struct RwV3d - */ typedef struct RwV3d RwV3d; /** - * \ingroup datatypes + * \ingroup rwv3d * \struct RwV3d * This type represents 3D points and vectors specified by * the (x, y, z) coordinates of a 3D point or the (x, y, z) components of a @@ -1274,13 +1298,16 @@ struct RwV3d #define RWV4DALIGNMENT(_v4d) \ (! (((rwV4DALIGNMENT)-1) & ((RwUInt32)(_v4d)))) +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwv4d * \struct RwV4d * This type represents 4D points and vectors specified by * the (x, y, z, w) coordinates of a 4D point or the (x, y, z, w) components of a * 4D vector. */ +#endif /* RWADOXYGENEXTERNAL */ + struct RwV4d { RwReal x; /**< X value */ @@ -1289,27 +1316,21 @@ struct RwV4d RwReal w; /**< W value */ }; -/** - * \ingroup datatypes - * \typedef RwV4d - * typedef for struct RwV4d - */ typedef struct RwV4d RWALIGN(RwV4d, rwV4DALIGNMENT); -/** - * \ingroup datatypes - * \typedef RwRect - * typedef for struct RwRect - */ typedef struct RwRect RwRect; + +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup geometricaltypes * \struct RwRect * This type represents a 2D device space rectangle specified * by the position of the top-left corner (the offset x, y) and its width (w) * and height (h). */ +#endif /* RWADOXYGENEXTERNAL */ + struct RwRect { RwInt32 x; /**< X value of the top-left corner */ @@ -1318,18 +1339,15 @@ struct RwRect RwInt32 h; /**< Height of the rectangle */ }; -/** - * \ingroup datatypes - * \typedef RwSphere - * typedef for struct RwSphere - */ typedef struct RwSphere RwSphere; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup geometricaltypes * \struct RwSphere * This type represents a sphere specified by the position * of its center and its radius */ +#endif /* RWADOXYGENEXTERNAL */ struct RwSphere { RwV3d center; /**< Sphere center */ @@ -1341,18 +1359,16 @@ struct RwSphere ( *(_target) = *(_source) ) #endif /* (!defined(RwSphereAssign)) */ -/** - * \ingroup datatypes - * \typedef RwLine - * typedef for struct RwLine - */ typedef struct RwLine RwLine; + +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup geometricaltypes * \struct RwLine * This type represents a 3D line specified by the position * of its start and end points. */ +#endif /* RWADOXYGENEXTERNAL */ struct RwLine { RwV3d start; /**< Line start */ @@ -1367,11 +1383,13 @@ struct RwLine /* The maximum number of texture coordinates */ #define rwMAXTEXTURECOORDS 8 +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup fundtypesdatatypes * RwTextureCoordinateIndex * This type represents the index for texture coordinates. */ +#endif /* RWADOXYGENEXTERNAL */ enum RwTextureCoordinateIndex { rwNARWTEXTURECOORDINATEINDEX = 0, @@ -1387,18 +1405,16 @@ enum RwTextureCoordinateIndex }; typedef enum RwTextureCoordinateIndex RwTextureCoordinateIndex; -/** - * \ingroup datatypes - * \typedef RwTexCoords - * typedef for struct RwTexCoords - */ typedef struct RwTexCoords RwTexCoords; + +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup fundtypesdatatypes * \struct RwTexCoords * This type represents the the u and v texture * coordinates of a particular vertex. */ +#endif /* RWADOXYGENEXTERNAL */ struct RwTexCoords { RwReal u; /**< U value */ @@ -1409,10 +1425,13 @@ struct RwTexCoords /* Singley linked list macros. End marked as NULL */ typedef struct RwSLLink RwSLLink; /*** RwSLLink ***/ + +#if (!defined(DOXYGEN)) struct RwSLLink { RwSLLink *next; }; +#endif /* (!defined(DOXYGEN)) */ #define rwSLLinkGetData(link,type,entry) \ ((type *)(((RwUInt8 *)(link))-offsetof(type,entry))) @@ -1427,10 +1446,13 @@ struct RwSLLink ((linkvar)->next) typedef struct RwSingleList RwSingleList; + +#if (!defined(DOXYGEN)) struct RwSingleList { RwSLLink link; }; +#endif /* (!defined(DOXYGEN)) */ #define rwSingleListInitialize(list) \ (list)->link.next= NULL; @@ -1446,11 +1468,14 @@ struct RwSingleList /* Doubly linked list. End marked as start (its a ring) */ typedef struct RwLLLink RwLLLink; /*** RwLLLink ***/ + +#if (!defined(DOXYGEN)) struct RwLLLink { RwLLLink *next; RwLLLink *prev; }; +#endif /* (!defined(DOXYGEN)) */ #define rwLLLinkGetData(linkvar,type,entry) \ ((type *)(((RwUInt8 *)(linkvar))-offsetof(type,entry))) @@ -1472,10 +1497,13 @@ struct RwLLLink ((linkvar)->next) typedef struct RwLinkList RwLinkList; + +#if (!defined(DOXYGEN)) struct RwLinkList { RwLLLink link; }; +#endif /* (!defined(DOXYGEN)) */ #define rwLinkListInitialize(list) \ ( (list)->link.next = ((RwLLLink *)(list)), \ @@ -1497,19 +1525,17 @@ struct RwLinkList #define rwLinkListGetTerminator(list) \ (&((list)->link)) -/** - * \ingroup datatypes - * \typedef RwSurfaceProperties - * typedef for struct RwSurfaceProperties - */ typedef struct RwSurfaceProperties RwSurfaceProperties; + +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup fundtypesdatatypes * \struct RwSurfaceProperties * This type represents the ambient, diffuse and * specular reflection coefficients of a particular geometry. Each coefficient * is specified in the range 0.0 (no reflection) to 1.0 (maximum reflection). */ +#endif /* RWADOXYGENEXTERNAL */ struct RwSurfaceProperties { RwReal ambient; /**< ambient reflection coefficient */ @@ -1541,10 +1567,10 @@ struct RwSurfaceProperties */ #define RWFIX_MIN (1) #define RWFIX_MAX (0x7fffffff) -#define RwFixedCast(A) (RwInt32FromRealMacro((A) * 65536.0f)) -#define RwFixedToInt(A) ((A) >> 16) -#define RwFixedToFloat(A) ((float)(((float)(A)) * (1.0f / 65536.0f))) +#define RwFixedToInt(a) ((a) >> 16) +#define RwFixedToFloat(a) ((float)(((float)(a)) * (1.0f / 65536.0f))) #define RwFixedToReal(a) ((RwReal)(((RwReal)(a)) * (1.0f / 65536.0f))) +#define RwIntToFixed(a) ((a) << 16) #define RwRealToFixed(a) (RwInt32FromRealMacro((a) * 65536.0f)) #define RwRealAbs(a) ((RwReal)((a) >= (RwReal)(0.0) ? (a) : (-(a)))) #define RwRealMin2(a,b) ((RwReal)( ((a) <= (b)) ? (a) : (b))) @@ -1555,7 +1581,6 @@ struct RwSurfaceProperties #ifndef NORWREALSHORTCUT #define RToFixed RwRealToFixed #define RAbs RwRealAbs -#define FxCast RwFixedCast #define FxToInt RwFixedToInt #define FxToFloat RwFixedToFloat #define FxToReal RwFixedToFloat @@ -1580,6 +1605,8 @@ struct RwSurfaceProperties * typedef for struct RwPlane */ typedef struct RwPlane RwPlane; + +#if (!defined(DOXYGEN)) /* * This type represents a plane */ @@ -1588,7 +1615,7 @@ struct RwPlane RwV3d normal; /**< Normal to the plane */ RwReal distance; /**< Distance to plane from origin in normal direction*/ }; - +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** Defines @@ -1613,7 +1640,7 @@ typedef enum RwPlaneType RwPlaneType; (*(const RwReal *)(((const RwUInt8 *)(&((vect).x)))+(RwInt32)(y))) #define SETCOORD(vect,y,value) \ (((*(RwReal *)(((RwUInt8 *)(&((vect).x)))+(RwInt32)(y))))=(value)) -#define SETCONTCOORD(vect,y,value) \ +#define SETCONSTCOORD(vect,y,value) \ (((*(const RwReal *) \ (((const RwUInt8 *) \ (&((vect).x)))+(RwInt32)(y))))=(value)) @@ -1624,7 +1651,7 @@ typedef enum RwPlaneType RwPlaneType; /** - * \ingroup rwcore + * \ingroup integertypes * \page inttypes Integer Types * * RenderWare supports a number of integer types: @@ -1661,7 +1688,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup realtypes * \typedef RwReal * * RenderWare supports a single RwReal floating-point type to aid portability @@ -1683,7 +1710,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup realtypes * \typedef RwFixed * * RenderWare supports a single RwFixed fixed-point type. @@ -1696,15 +1723,15 @@ typedef enum RwPlaneType RwPlaneType; * RWFIX_MAX and RWFIX_MIN respectively. * * The following macros are provided to help you work with RwFixed datatypes: - * \li RwFixedCast(x) Cast the integer portion of an RwFixed to another type. * \li RwFixedToInt(x) Convert an RwFixed to an integer. (The fractional portion is lost.) * \li RwFixedToFloat(x) Convert an RwFixed to a float. * \li RwFixedToReal(x) Convert an RwFixed to an RwReal. * \li RwRealToFixed(x) Convert an RwReal to an RwFixed. (Some precision may be lost.) + * \li RwIntToFixed(x) Convert an RwInt32 to an RwFixed. (Some precision may be lost.) */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwInt8 * * Signed 8 bit integer type. @@ -1712,7 +1739,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwUInt8 * * Unsigned 8bit integer type. @@ -1720,7 +1747,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwChar * * Character type. @@ -1728,7 +1755,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwInt16 * * Signed 16 bit integer type. @@ -1736,7 +1763,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwUInt16 * * Unsigned 16 bit integer type. @@ -1744,7 +1771,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwInt32 * * Signed 32 bit integer type. @@ -1752,7 +1779,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwUInt32 * * Unsigned 32 bit integer type. @@ -1760,7 +1787,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwInt64 * * Signed 64 bit integer type. @@ -1768,7 +1795,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwUInt64 * * Unsigned 64 bit integer type. @@ -1776,7 +1803,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwInt128 * * Signed 128 bit integer type. @@ -1784,7 +1811,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwUInt128 * * Unsigned 128 bit integer type. @@ -1792,7 +1819,7 @@ typedef enum RwPlaneType RwPlaneType; */ /** - * \ingroup datatypes + * \ingroup integertypes * \typedef RwBool * * Boolean type. @@ -1894,8 +1921,10 @@ enum RwCorePluginID rwID_PITEXDICTIONARY = 0x23, rwID_TOC = 0x24, rwID_PRTSTDGLOBALDATA = 0x25, + rwID_ALTPIPE = 0x26, + rwID_PIPEDS = 0x27, /* Insert before MAX and increment MAX */ - rwID_COREPLUGINIDMAX = 0x26, + rwID_COREPLUGINIDMAX = 0x28, rwCOREPLUGINIDFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; typedef enum RwCorePluginID RwCorePluginID ; @@ -1944,12 +1973,15 @@ typedef enum RwPlatformID RwPlatformID; */ typedef struct RwObject RwObject; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwobject * \struct RwObject * This should be considered an opaque type. Use * the RwObject API functions to access. */ +#endif /* RWADOXYGENEXTERNAL */ + struct RwObject { RwUInt8 type; /**< Internal Use */ @@ -1960,20 +1992,23 @@ struct RwObject /* Often a Frame */ }; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes - * \typedef RwObjectCallBack + * \ingroup rwobject + * \ref RwObjectCallBack * callback function supplied for object callback functions. * - * \return Pointer to the current object - * * \param object Pointer to the current object, supplied by - * iterator. - * \param data Pointer to developer-defined data structure. + * iterator. + * \param data Pointer to developer-defined data structure. + * + * \return Pointer to the current object * * \see RwFrameForAllObjects * */ +#endif /* RWADOXYGENEXTERNAL */ + typedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data); /**************************************************************************** @@ -2128,6 +2163,8 @@ typedef int (*vecSscanfFunc)(const RwChar *buffer, ...) /* __RWFORMAT__(scanf, 2, 3) */; typedef struct RwStringFunctions RwStringFunctions; + +#if (!defined(DOXYGEN)) struct RwStringFunctions { vecSprintfFunc vecSprintf ; @@ -2147,6 +2184,7 @@ struct RwStringFunctions vecStrtokFunc vecStrtok; vecSscanfFunc vecSscanf; }; +#endif /* (!defined(DOXYGEN)) */ /*--- Automatically derived from: C:/daily/rwsdk/src/plcore/rwdbgerr.h ---*/ @@ -2203,32 +2241,32 @@ typedef enum RwErrorCodePlugin_errcore RwErrorCodePlugin_errcore; #endif /* (!defined(rwFREELISTCLEANLANDFILL)) */ #define RWFREELISTALIGNED(_pData, _freelist) \ - (! (((RwUInt32)(_pData)) & ((_freelist)->alignmentMinusOne)) ) + (! (((RwUInt32)(_pData)) & ((_freelist)->alignment - 1)) ) /***************************** * REGULAR MEMORY ALLOCATION * *****************************/ /** - * \ingroup rwmem + * \ingroup memoryfileinterface * \def RwMalloc * RwMalloc(_s) is a macro for malloc(_s). */ /** - * \ingroup rwmem + * \ingroup memoryfileinterface * \def RwFree * RwFree(_p) is a macro for free(_p). */ /** - * \ingroup rwmem + * \ingroup memoryfileinterface * \def RwCalloc * RwCalloc(_n, _s) is a macro for calloc(_n, _s). */ /** - * \ingroup rwmem + * \ingroup memoryfileinterface * \def RwRealloc * RwRealloc(_p, _s) is a macro for realloc(_p, _s). */ @@ -2252,8 +2290,6 @@ typedef enum RwErrorCodePlugin_errcore RwErrorCodePlugin_errcore; # if (defined(_MSC_VER)) # if ((_MSC_VER>=1000) && defined(_DEBUG)) -/* Pick up _ASSERTE() macro */ -/* #include */ #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) #define _CRTDBG_MAP_ALLOC #endif /* defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) */ @@ -2556,12 +2592,12 @@ typedef enum RwErrorCodePlugin_errcore RwErrorCodePlugin_errcore; typedef struct RwMemoryFunctions RwMemoryFunctions; /** - * \ingroup datatypes + * \ingroup memoryfileinterface * \struct RwMemoryFunctions * This type represents the memory functions used * by RenderWare. By default, the standard ANSI functions are used. The * application may install an alternative interface providing that it is ANSI - * compliant (see API function \ref RwEngineInit): + * compliant (in RenderWare Graphics see API function RwEngineInit): */ struct RwMemoryFunctions { @@ -2574,60 +2610,44 @@ struct RwMemoryFunctions void *(*rwcalloc)(size_t numObj, size_t sizeObj); /**< calloc calloc */ }; -typedef struct RwFreeBlock RwFreeBlock; -/* - * Freelists -- from Page 131 - * Advanced Animation and Rendering Techniques - * Alan Watt and Mark Watt - * Addison-Wesley 1993, - * ISBN 0-201-54412-1: + /** + * \ingroup rwfreelist + * The free list was statically allocated * - * "Lastly, on a more general note concerning speedups for renderers, the - * implementor should be aware that a lot of suggestions for improving - * efficiency fall into the category of ingenious, but complex, - * algorithms for very specific contexts that may save a few microseconds - * but which make your code unreadable. A more general computer science - * perspective that takes a `global view' of the renderer can be more - * fruitful. For example, the renderer devotes a lot of time to - * allocating and deallocating chunks of memory for storing data. A lot - * of these chunks are always the same size - such as those that are - * continually required to store the data structure for fragment lists. - * Using memory management techniques that recognize this fact can yield - * considerable dividends. One such scheme would be to hold a series of - * empty lists in memory for all the commonly used data structures. An - * empty list for fragments, say, would contain a list of previously - * allocated, but no longer needed, fragment structures. When the - * renderer needs memory for a new fragment, it looks first at this empty - * list. If there is nothing there it allocates space directly, - * otherwise it takes a fragments off the end of the list and uses that. - * Conversely, when the renderer no longer needs a fragment, instead of - * freeing it, it goes onto the end of the empty list. In the authors' - * experience, replacing the naive allocate/deallocate scheme with this - * way of managing memory can result in 100% speedup. " + * \see RwFreeListSetFlags */ -struct RwFreeBlock -{ - RwFreeBlock *nextBlock; -}; +#define rwFREELISTFLAG_STATIC 0x00000001 + +/** + * \ingroup rwfreelist + * \hideinitializer + * Free blocks as soon as they are empty + * + * \see RwFreeListSetFlags + */ +#define rwFREELISTFLAG_FREEBLOCKS 0x00000002 + typedef struct RwFreeList RwFreeList; + +/** + * \ingroup rwfreelist + * Holds free list info, should be considered opaque. Use API functions to access. + */ struct RwFreeList { - void **freeListStack; /* Stack of unused entries */ - void **freeListStackTop; /* Pointer to the top of the stack */ - - RwFreeBlock *firstBlock; /* Data start */ - - RwInt32 blockSize; /* Size of block in bytes */ - RwInt32 entrySize; /* Entry size */ - RwInt32 alignmentMinusOne; /* Entry alignment minus 1 */ - RwInt32 entriesPerBlock; /* Amount of space in a block */ - - RwInt32 entriesAllocated; /* Total slots allocated - * (but not necessarily being used */ - - /* All freelists */ - RwLLLink lFreeList; + RwUInt32 entrySize; /** + rwFREELISTFLAG_FREEBLOCKS */ + RwLLLink link; /** #define RwFreeListAlloc(_f) \ - memalign((1 + (_f)->alignmentMinusOne), (_f)->entrySize) + memalign(((_f)->alignment), (_f)->entrySize) #else /* ((defined(__MWERKS__) || defined(__GNUC__)) && defined(__R5900__)) */ @@ -2750,7 +2786,7 @@ extern RwInt32 RwFreeListPurgeAllFreeLists(void); */ /** - * \ingroup datatypes + * \ingroup rwstream * \ref RwStreamType * This type represents the different types of stream that * can be used. @@ -2768,7 +2804,7 @@ enum RwStreamType typedef enum RwStreamType RwStreamType; /** - * \ingroup datatypes + * \ingroup rwstream * \ref RwStreamAccessType * This type represents the options available for * accessing a stream when it is opened. @@ -2785,8 +2821,8 @@ typedef enum RwStreamAccessType RwStreamAccessType; /* Memory stream */ /** - * \ingroup datatypes - * \typedef RwStreamMemory + * \ingroup rwstream + * \struct RwStreamMemory * This should be considered an opaque type. * Use the RwStream API functions to access. */ @@ -2803,7 +2839,7 @@ struct RwStreamMemory typedef union RwStreamFile RwStreamFile; /** - * \ingroup datatypes + * \ingroup rwstream * \union RwStreamFile * This type is used to represent a file pointer for * accessing data on disk through the stream mechanism. @@ -2829,8 +2865,8 @@ typedef RwBool(*rwCustomStreamFnSkip) (void *data, /* Custom stream */ /** - * \ingroup datatypes - * \typedef RwStreamCustom + * \ingroup rwstream + * \struct RwStreamCustom * This should be considered an opaque type. * Use the RwStream API functions to access. */ @@ -2850,7 +2886,7 @@ struct RwStreamCustom typedef union RwStreamUnion RwStreamUnion; /** - * \ingroup datatypes + * \ingroup rwstream * \union RwStreamUnion * The union of all supported stream types */ @@ -2862,8 +2898,8 @@ union RwStreamUnion }; /** - * \ingroup datatypes - * \typedef RwStream + * \ingroup rwstream + * \struct RwStream * Binary stream for reading or writing object data. * This should be considered an opaque type. * Use the RwStream API functions to access. @@ -2883,7 +2919,7 @@ struct RwStream typedef struct RwMemory RwMemory; /** - * \ingroup datatypes + * \ingroup rwstream * \struct RwMemory * This type represents a block of allocated memory. * It is used to specify an area of memory connected to a stream of type @@ -2905,6 +2941,9 @@ extern "C" { #endif /* __cplusplus */ +extern void +RwStreamSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + /* Open/Close streams */ extern RwStream * @@ -2953,8 +2992,9 @@ RwStreamSkip(RwStream * stream, Global Types */ +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginDataChunkWriteCallBack represents the function * registered by \ref RwCameraRegisterPluginStream, etc. as the function that * writes extension data to a binary stream. @@ -2979,7 +3019,7 @@ RwStreamSkip(RwStream * stream, typedef RwStream *(*RwPluginDataChunkWriteCallBack)(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginDataChunkReadCallBack represents the function * registered by \ref RwCameraRegisterPluginStream, etc. as the function that * reads extension data from a binary stream. @@ -3004,7 +3044,7 @@ typedef RwStream *(*RwPluginDataChunkWriteCallBack)(RwStream *stream, RwInt32 bi typedef RwStream *(*RwPluginDataChunkReadCallBack)(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginDataChunkGetSizeCallBack represents the callback * registered by \ref RwCameraRegisterPluginStream, etc. as the function that * determines the binary size of the extension data. @@ -3022,7 +3062,7 @@ typedef RwStream *(*RwPluginDataChunkReadCallBack)(RwStream *stream, RwInt32 bin typedef RwInt32(*RwPluginDataChunkGetSizeCallBack)(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginDataChunkAlwaysCallBack represents the callback * registered by \ref RwCameraSetStreamAlwaysCallBack, etc. as the * function that is called after the reading of plugin stream data is @@ -3037,11 +3077,13 @@ typedef RwInt32(*RwPluginDataChunkGetSizeCallBack)(const void *object, RwInt32 o * * \param sizeInObject A RwInt32 value equal to the size * (in bytes) of the extension data. + * + * \return Returns TRUE if successful, FALSE otherwise. */ typedef RwBool(*RwPluginDataChunkAlwaysCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginDataChunkRightsCallBack represents the callback * registered by RwCameraSetStreamRightsCallBack, etc. as the * function that is called after the reading of plugin stream data is @@ -3058,11 +3100,13 @@ typedef RwBool(*RwPluginDataChunkAlwaysCallBack)(void *object, RwInt32 offsetInO * (in bytes) of the extension data. * * \param extraData An RwUInt32 writen with the plugin id. + * + * \return Returns TRUE if successful, FALSE otherwise. */ typedef RwBool(*RwPluginDataChunkRightsCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject, RwUInt32 extraData); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginObjectConstructor represents the callback * registered by \ref RwEngineRegisterPlugin, \ref RwCameraRegisterPlugin, etc. * as the function that initializes either the global extension data (in the @@ -3083,7 +3127,7 @@ typedef RwBool(*RwPluginDataChunkRightsCallBack)(void *object, RwInt32 offsetInO typedef void *(*RwPluginObjectConstructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginObjectCopy represents the callback registered by * \ref RwCameraRegisterPlugin, etc. as the function that copies the object * extension data when an object is duplicated. @@ -3105,7 +3149,7 @@ typedef void *(*RwPluginObjectConstructor)(void *object, RwInt32 offsetInObject, typedef void *(*RwPluginObjectCopy)(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject); /** - * \ingroup datatypes + * \ingroup rwplugin * \ref RwPluginObjectDestructor represents the callback registered * by \ref RwEngineRegisterPlugin, \ref RwCameraRegisterPlugin, etc. as the * function that destroys either the global extension data (in the case of @@ -3123,6 +3167,8 @@ typedef void *(*RwPluginObjectCopy)(void *dstObject, const void *srcObject, RwIn * * \return Pointer to the object. */ +#endif /* RWADOXYGENEXTERNAL */ + typedef void *(*RwPluginObjectDestructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); typedef void *(*RwPluginErrorStrCallBack)(void *); @@ -3130,6 +3176,7 @@ typedef void *(*RwPluginErrorStrCallBack)(void *); typedef struct RwPluginRegistry RwPluginRegistry; typedef struct RwPluginRegEntry RwPluginRegEntry; +#if (!defined(DOXYGEN)) struct RwPluginRegistry { RwInt32 sizeOfStruct; @@ -3158,6 +3205,7 @@ struct RwPluginRegEntry RwPluginRegEntry *prevRegEntry; RwPluginRegistry *parentRegistry; }; +#endif /* (!defined(DOXYGEN)) */ @@ -3172,6 +3220,9 @@ extern "C" /* Registering toolkits and allocating memory */ +extern void +RwPluginRegistrySetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwBool _rwPluginRegistrySetStaticPluginsSize(RwPluginRegistry * reg, RwInt32 size); @@ -3355,14 +3406,17 @@ MACRO_STOP #define RWMATRIXPRINT(_matrix) /* No op */ #endif /* (!(defined(RWMATRIXPRINT))) */ +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwmatrix * enum RwOpCombineType * This type represents a combination operator which * can be applied to frames and matrices. * The operator determines the order * in which one object is combined with another */ +#endif /* RWADOXYGENEXTERNAL */ + enum RwOpCombineType { rwCOMBINEREPLACE = 0, /**flags & (RwInt32)(flagsbit)) /* Creation/destruction */ +extern void +RwMatrixSetFreeListCreateParams( RwInt32 blockSize, RwInt32 numBlocksToPrealloc ); + extern RwBool RwMatrixDestroy(RwMatrix * mpMat); @@ -3693,7 +3746,7 @@ MACRO_STOP rwMATRIXTYPENORMAL) ) || /* ... or actually is */ \ rwMatrixIsNormal(_matrix, _epsilon)) && \ ( ( !( rwMatrixGetFlags(_matrix) & /* not flagged as orthogonal */ \ - rwMATRIXTYPEORTHOGANAL) ) || /* ... or actually is */ \ + rwMATRIXTYPEORTHOGONAL) ) || /* ... or actually is */ \ rwMatrixIsOrthogonal(_matrix, _epsilon)) ) #define rwMat01Det(_mAA) \ @@ -3906,8 +3959,6 @@ MACRO_STOP #pragma warning( disable : 344 ) #endif /* (defined(__ICL)) */ -//nobody needed that - AAP -//#include #if (defined(RWDEBUG)) #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) @@ -4001,48 +4052,16 @@ MACRO_START \ } \ MACRO_STOP -/* LEGACY-SUPPORT macros */ -#define RWIM2DVERTEXSetCameraX(vert, camx) RwIm2DVertexSetCameraX(vert, camx) -#define RWIM2DVERTEXSetCameraY(vert, camy) RwIm2DVertexSetCameraY(vert, camy) -#define RWIM2DVERTEXSetCameraZ(vert, camz) RwIm2DVertexSetCameraZ(vert, camz) -#define RWIM2DVERTEXSetRecipCameraZ(vert, recipz) \ - RwIm2DVertexSetRecipCameraZ(vert, recipz) -#define RWIM2DVERTEXGetCameraX(vert) RwIm2DVertexGetCameraX(vert) -#define RWIM2DVERTEXGetCameraY(vert) RwIm2DVertexGetCameraY(vert) -#define RWIM2DVERTEXGetCameraZ(vert) RwIm2DVertexGetCameraZ(vert) -#define RWIM2DVERTEXGetRecipCameraZ(vert) RwIm2DVertexGetRecipCameraZ(vert) -#define RWIM2DVERTEXSetScreenX(vert, scrnx) RwIm2DVertexSetScreenX(vert, scrnx) -#define RWIM2DVERTEXSetScreenY(vert, scrny) RwIm2DVertexSetScreenY(vert, scrny) -#define RWIM2DVERTEXSetScreenZ(vert, scrnz) RwIm2DVertexSetScreenZ(vert, scrnz) -#define RWIM2DVERTEXGetScreenX(vert) RwIm2DVertexGetScreenX(vert) -#define RWIM2DVERTEXGetScreenY(vert) RwIm2DVertexGetScreenY(vert) -#define RWIM2DVERTEXGetScreenZ(vert) RwIm2DVertexGetScreenZ(vert) -#define RWIM2DVERTEXSetU(vert, u, recipz) RwIm2DVertexSetU(vert, u, recipz) -#define RWIM2DVERTEXSetV(vert, v, recipz) RwIm2DVertexSetV(vert, v, recipz) -#define RWIM2DVERTEXGetU(vert) RwIm2DVertexGetU(vert) -#define RWIM2DVERTEXGetV(vert) RwIm2DVertexGetV(vert) -#define RWIM2DVERTEXSetRealRGBA(vert, red, green, blue, alpha) \ - RwIm2DVertexSetRealRGBA(vert, red, green, blue, alpha) -#define RWIM2DVERTEXSetIntRGBA(vert, red, green, blue, alpha) \ - RwIm2DVertexSetIntRGBA(vert, red, green, blue, alpha) -#define RWIM2DVERTEXGetRed(vert) RwIm2DVertexGetRed(vert) -#define RWIM2DVERTEXGetGreen(vert) RwIm2DVertexGetGreen(vert) -#define RWIM2DVERTEXGetBlue(vert) RwIm2DVertexGetBlue(vert) -#define RWIM2DVERTEXGetAlpha(vert) RwIm2DVertexGetAlpha(vert) -#define RWIM2DVERTEXCopyRGBA(dst, src) RwIm2DVertexCopyRGBA(dst, src) -#define RWIM2DVERTEXClipRGBA(o, i, n, f) RwIm2DVertexClipRGBA(o, i, n, f) - /**************************************************************************** Global Types */ /* We use RwD3D8Vertex to drive the hardware in 2D mode */ -/** - * \ingroup rwcoredriverd3d8 - * \typedef RwD3D8Vertex +/* * D3D8 vertex structure definition for 2D geometry */ +#if !defined(RWADOXYGENEXTERNAL) typedef struct RwD3D8Vertex RwD3D8Vertex; /** * \ingroup rwcoredriverd3d8 @@ -4061,47 +4080,41 @@ struct RwD3D8Vertex RwReal u; /**< Texture coordinate U */ RwReal v; /**< Texture coordinate V */ }; +#endif /* !defined(RWADOXYGENEXTERNAL) */ /* Define types used */ +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \typedef RwIm2DVertex + * \ref RwIm2DVertex * Typedef for a RenderWare Graphics Immediate Mode 2D Vertex */ typedef RwD3D8Vertex RwIm2DVertex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ -/* LEGACY-SUPPORT macro */ +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \def RWIM2DVERTEX - * RWIM2DVERTEX is a legacy macro for RwIm2DVertex - */ -#define RWIM2DVERTEX RwIm2DVertex - -/** - * \ingroup rwcoredriverd3d8 - * \typedef RxVertexIndex + * \ref RxVertexIndex * * Typedef for a RenderWare Graphics PowerPipe Immediate * Mode Vertex */ typedef RwUInt16 RxVertexIndex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ + +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 - * \typedef RwImVertexIndex + * \ref RwImVertexIndex * Typedef for a RenderWare Graphics Immediate Mode Vertex. */ typedef RxVertexIndex RwImVertexIndex; +#endif /* !defined(RWADOXYGENEXTERNAL) */ -/* LEGACY-SUPPORT macro */ -/** - * \ingroup rwcoredriverd3d8 - * \def RWIMVERTEXINDEX - * RWIMVERTEXINDEX is a legacy macro for RwImVertexIndex - */ -#define RWIMVERTEXINDEX RwImVertexIndex +#if !defined(RWADOXYGENEXTERNAL) /** * \ingroup rwcoredriverd3d8 @@ -4114,8 +4127,10 @@ typedef struct RwUInt32 numTextureStageStateChanges; /**< Number of Texture Stage States changed */ RwUInt32 numMaterialChanges; /**< Number of Material changes */ RwUInt32 numLightsChanged; /**< Number of Lights changed */ + RwUInt32 numVBSwitches; /**< Number of Vertex Buffer switches */ } RwD3D8Metrics; +#endif /* !defined(RWADOXYGENEXTERNAL) */ #endif /* D3D8_DRVMODEL_H */ @@ -4125,7 +4140,7 @@ RwD3D8Metrics; * Typedef for pointer to Vector multiplication by Matrix function */ -typedef RwV3d *(*rwVectorMultFn) (RwV3d * pointsOut, +typedef RwV3d *(*rwVectorMultFn) (RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix); @@ -4136,7 +4151,7 @@ typedef RwV3d *(*rwVectorMultFn) (RwV3d * pointsOut, * currently applies to SKY2 and XBOX - IDBS [2/11/2001] * [and, if using the intel compiler version 400 or above, * we will use the single-precision float "sqrtf" under - * D3D7, D3D8, OpenGL or SoftRas] */ + * D3D8, OpenGL or SoftRas] */ #if (defined(rwSqrtMacro)) #define RWNOSQRTTABLE #endif /* (defined(rwSqrtMacro)) */ @@ -4198,7 +4213,7 @@ MACRO_STOP #define RwV2dDotProductMacro(a,b) \ (( ((((a)->x) * ( (b)->x))) + \ - ( (((a)->y) * ( (b)->y))))) \ + ( (((a)->y) * ( (b)->y))))) #define _rwV2dNormalizeMacro(_result, _out, _in) \ MACRO_START \ @@ -4303,7 +4318,7 @@ MACRO_STOP #define RwV3dDotProductMacro(a, b) \ ((((( (((a)->x) * ((b)->x))) + \ ( (((a)->y) * ((b)->y))))) + \ - ( (((a)->z) * ((b)->z))))) \ + ( (((a)->z) * ((b)->z))))) #define RwV3dCrossProductMacro(o, a, b) \ MACRO_START \ @@ -4375,7 +4390,7 @@ MACRO_STOP #endif /* (!defined(rw4OVERPISQ)) */ #if (!defined(rwPI3)) -#define rwPI3 (rwPI * (RwReal)3) +#define rwPI3 (rwPI * (RwReal)3) #endif /* (!defined(rwPI3)) */ #if (!defined(rwPI3OVER2)) @@ -4463,7 +4478,7 @@ extern void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb); extern void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar); -extern void RwV3dIncrementScaled(RwV3d * out, +extern void RwV3dIncrementScaled(RwV3d * out, const RwV3d * in, RwReal scalar); extern void RwV3dNegate(RwV3d * out, const RwV3d * in); extern RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb); @@ -4513,6 +4528,8 @@ extern RwReal _rwV3dNormalize(RwV3d * out, const RwV3d * in); */ typedef struct RwSList RwSList; + +#if (!defined(DOXYGEN)) struct RwSList { RwUInt8 *listElements; @@ -4520,7 +4537,7 @@ struct RwSList RwInt32 numElementsAlloced; RwInt32 entrySize; }; - +#endif /* (!defined(DOXYGEN) */ /**************************************************************************** @@ -4595,99 +4612,169 @@ extern void *_rwSListToArray(RwSList *sList); !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes - * RwRenderState - * This type represents the various render states that - * can be set using the API function \ref RwRenderStateSet. This function also - * takes a render state value or pointer to an object depending on the type. - * For render states that are toggles, the value should be TRUE to switch the - * state on and FALSE to turn it off. + * \ingroup rwrenderstate + * RwRenderState represents the global state variables that control + * rendering. These may be set and queried using the + * \ref RwRenderStateSet and \ref RwRenderStateGet functions respectively. * - * Note that many of these render states may not be supported on certain - * platforms. The \ref RwRenderStateSet functions will return FALSE in such cases. + * Refer to the \ref rwrenderstateoverview for an overview of this system. + * + * \note The texture render states (raster, address & filter modes) would + * normally just be used when rendering in immediate mode and should be + * specificied completely every time a texture is used. Retained mode + * pipelines will frequently set theses states internally, usually based on + * \ref RwTexture objects. */ +#endif /* RWADOXYGENEXTERNAL */ enum RwRenderState { rwRENDERSTATENARENDERSTATE = 0, - rwRENDERSTATETEXTURERASTER, /** Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILFAIL, + /**<\ref RwStencilOperation used when the stencil test passes. + * Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILZFAIL, + /**<\ref RwStencilOperation used when the stencil test passes and + * the depth test (z-test) fails. + * Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILPASS, + /** Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILFUNCTION, + /**<\ref RwStencilFunction for the stencil test. + * Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILFUNCTIONREF, + /** Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILFUNCTIONMASK, + /** Supported on Xbox, D3D8, and OpenGL only. + */ + rwRENDERSTATESTENCILFUNCTIONWRITEMASK, + /** Supported on Xbox, D3D8, and OpenGL only. + */ rwRENDERSTATEFORCEENUMSIZEINT = RWFORCEENUMSIZEINT }; typedef enum RwRenderState RwRenderState; - +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes - * RwShadeMode - * This type represents the options available for setting the - * rwRENDERSTATESHADEMODE render state */ + * \ingroup rwrenderstate + * RwShadeMode represents the available shading modes that may be + * set using the \ref RwRenderState \ref rwRENDERSTATESHADEMODE. + */ +#endif /* RWADOXYGENEXTERNAL */ enum RwShadeMode { - rwSHADEMODENASHADEMODE = 0, /**var) +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes - * \typedef RwResEntry + * \ingroup rwresources + * \struct RwResEntry * RwResEntry object. Instanced data block in resources arena. * This should be considered an opaque * type. Use the RwResEntry API functions to access. */ +#endif /* RWADOXYGENEXTERNAL */ + typedef struct RwResEntry RwResEntry; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes - * \typedef RwResEntryDestroyNotify - * This type represents the function + * \ingroup rwresources + * \ref RwResEntryDestroyNotify type represents the function * called from \ref RwResourcesFreeResEntry (and indirectly from * \ref RwResourcesEmptyArena) immediately before the memory used by the * specified resources entry is released. * * \param resEntry Pointer to the instanced data. */ +#endif /* RWADOXYGENEXTERNAL */ typedef void (*RwResEntryDestroyNotify) (RwResEntry * resEntry); #if (!defined(DOXYGEN)) struct RwResEntry { - RwLLLink link; /**< Node in the list of resource elements */ - RwInt32 size; /**< Size of this node */ - void *owner; /**< Owner of this node */ - RwResEntry **ownerRef; /**< Pointer to pointer to this (enables de-alloc) */ - RwResEntryDestroyNotify destroyNotify; /**< This is called right before destruction */ + RwLLLink link; /* Node in the list of resource elements */ + RwInt32 size; /* Size of this node */ + void *owner; /* Owner of this node */ + RwResEntry **ownerRef; /* Pointer to pointer to this (enables de-alloc) */ + RwResEntryDestroyNotify destroyNotify; /* This is called right before destruction */ }; #endif /* (!defined(DOXYGEN)) */ typedef struct rwResources rwResources; + +#if (!defined(DOXYGEN)) struct rwResources { RwInt32 maxSize; @@ -5711,11 +5890,13 @@ struct rwResources RwLinkList *usedEntries; }; + typedef struct rwResourcesGlobals rwResourcesGlobals; struct rwResourcesGlobals { rwResources res; }; +#endif /* (!defined(DOXYGEN)) */ #ifdef __cplusplus @@ -5768,8 +5949,9 @@ extern RwModuleInfo resourcesModule; */ typedef struct RwRGBAReal RwRGBAReal; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwrgba * \struct RwRGBAReal * This structure represents a RGBA color which has * components specified as real values. @@ -5785,6 +5967,7 @@ typedef struct RwRGBAReal RwRGBAReal; * value 0 generally corresponds to the associcated component in an * RwRGBAReal with the value 0.0. */ +#endif /* RWADOXYGENEXTERNAL */ struct RwRGBAReal { RwReal red; /**< red component */ @@ -5799,11 +5982,14 @@ struct RwRGBAReal #endif /* (!defined(RwRGBARealAssign)) */ typedef struct RwRGBA RwRGBA; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwrgba * \struct RwRGBA * This structure represents a RGBA color - * which has integer components specified in the range 0 to 255. */ + * which has integer components specified in the range 0 to 255. + */ +#endif /* RWADOXYGENEXTERNAL */ struct RwRGBA { RwUInt8 red; /**< red component */ @@ -5947,6 +6133,7 @@ extern void RwRGBARealFromRwRGBA(RwRGBAReal *result, /* Matrix stream format */ typedef struct rwStreamMatrix RwMatrixChunkInfo; typedef struct rwStreamMatrix rwStreamMatrix; +#if (!defined(DOXYGEN)) struct rwStreamMatrix { RwV3d right; @@ -5955,6 +6142,7 @@ struct rwStreamMatrix RwV3d pos; RwInt32 type; }; +#endif /* (!defined(DOXYGEN)) */ /**************************************************************************** @@ -6009,11 +6197,14 @@ extern RwMatrixChunkInfo *RwMatrixChunkInfoRead(RwStream * stream, */ typedef struct RwChunkHeaderInfo RwChunkHeaderInfo; +#ifndef RWADOXYGENEXTERNAL /** - * \ingroup datatypes + * \ingroup rwstream * \struct RwChunkHeaderInfo * Holds data for a chunk header read from a - * stream with \ref RwStreamReadChunkHeaderInfo. */ + * stream with \ref RwStreamReadChunkHeaderInfo. + */ +#endif /* RWADOXYGENEXTERNAL */ struct RwChunkHeaderInfo { RwUInt32 type; /**< chunk ID - see \ref RwStreamFindChunk */ diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index 8671e95d..6739f56a 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -169,7 +169,11 @@ RpAnimBlendClumpInitSkinned(RpClump *clump) for(i = 0; i < numBones; i++){ frames[i].nodeID = HIERNODEID(hier, i); frames[i].resetPos = boneTab[i]; +#ifdef LIBRW frames[i].hanimFrame = (RpHAnimStdKeyFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); +#else + frames[i].hanimFrame = (RpHAnimStdKeyFrame*)rtANIMGETINTERPFRAME(hier->currentAnim, i); +#endif } clumpData->ForAllFrames(FrameInitCBskin, nil); clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION; diff --git a/src/core/main.cpp b/src/core/main.cpp index 7d8bdb5e..9083646d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -303,7 +303,12 @@ PluginAttach(void) return FALSE; } - +#ifndef LIBRW + if (!RtAnimInitialize()) + { + return FALSE; + } +#endif if( !RpHAnimPluginAttach() ) { printf("Couldn't attach RpHAnim plugin\n"); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index e8a85be6..ab368e85 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -108,7 +108,7 @@ DefinedState(void) RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE); + //RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEBORDERCOLOR, (void*)RWRGBALONG(0, 0, 0, 255)); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEFOGCOLOR, @@ -358,9 +358,9 @@ AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data) hier->interpolator->currentAnim = nil; } #else - if(hier && hier->pCurrentAnim){ - RpHAnimAnimationDestroy(hier->pCurrentAnim); - hier->pCurrentAnim = nil; + if(hier && hier->currentAnim){ + RpHAnimAnimationDestroy(hier->currentAnim->pCurrentAnim); + hier->currentAnim = nil; } #endif } From a1412d1cdbc91535011a6048c79699eccfaa6e0c Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 14:15:06 +0300 Subject: [PATCH 51/85] Fix OneShotPriority overflow --- src/audio/AudioManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 88cfc16a..5b0b4907 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -169,11 +169,11 @@ cAudioManager::SetEntityStatus(int32 id, uint8 status) void cAudioManager::PlayOneShot(int32 index, int16 sound, float vol) { - static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 1, 1, 1, 9, - 2, 2, 0, 0, 0, 0, 3, 3, 5, 1, 1, 1, 1, 3, 4, 7, 6, 6, 6, 6, 1, 3, 4, 3, 4, 2, 1, 3, 5, 4, 6, 6, 1, 3, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static const uint8 OneShotPriority[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 2, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 4, 4, 4, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 3, 4, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 1, 1, 1, 9, 0, 0, 0, 1, 2, 2, 0, 0, 2, 3, 3, 3, 5, 1, 1, + 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 7, 1, 4, 3, 4, 2, 2, 2, 3, 1, 2, 1, 3, 5, 3, 4, 6, 4, 6, 3, 0, 0, 0, 0, 0, + 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 0, 0, 0, 0, 0, 3, 3, 1, 0 }; if (m_bIsInitialised) { if (index >= 0 && index < NUM_AUDIOENTITIES) { From 28d7d6b2f11237bb87f870cd3b4066e4b8e9dfc4 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 19:18:08 +0300 Subject: [PATCH 52/85] Fix some audio floats --- src/audio/AudioLogic.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index ef3814a2..6c025175 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -1507,7 +1507,7 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil { case WHEEL_STATE_SPINNING: if (gasPedalAudio > 0.4f) - relativeVelChange = (gasPedalAudio - 0.4f) * 1.6666666f * 0.75f; + relativeVelChange = (gasPedalAudio - 0.4f) * (5.0f / 3.0f) / (4.0f / 3.0f); break; case WHEEL_STATE_SKIDDING: relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); @@ -1515,7 +1515,7 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil case WHEEL_STATE_FIXED: relativeVel = gasPedalAudio; if (relativeVel > 0.4f) - relativeVel = (gasPedalAudio - 0.4f) * 1.6666666f; + relativeVel = (gasPedalAudio - 0.4f) * (5.0f / 3.0f); velChange = Abs(velocityChange); if (velChange > 0.04f) @@ -2659,7 +2659,7 @@ cAudioManager::ProcessJumbo(cVehicleParams *params) DoJumboVolOffset(); position = PlanePathPosition[plane->m_nPlaneId]; if (position <= TakeOffPoint) { - if (plane->m_fSpeed <= 0.10334f) { + if (plane->m_fSpeed <= 0.103344f) { ProcessJumboTaxi(); return; } @@ -2671,7 +2671,7 @@ cAudioManager::ProcessJumbo(cVehicleParams *params) ProcessJumboFlying(); } else { if (position > LandingPoint) { - if (plane->m_fSpeed > 0.10334f) { + if (plane->m_fSpeed > 0.103344f) { ProcessJumboDecel(plane); return; } @@ -2701,7 +2701,7 @@ cAudioManager::ProcessJumboAccel(CPlane *plane) float modificator; if (SetupJumboFlySound(20)) { - modificator = (plane->m_fSpeed - 0.10334f) * 1.676f; + modificator = (plane->m_fSpeed - 0.103344f) * 1.6760077f; if (modificator > 1.0f) modificator = 1.0f; if (SetupJumboRumbleSound(MAX_VOLUME * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) { @@ -2754,7 +2754,7 @@ void cAudioManager::ProcessJumboDecel(CPlane *plane) { if (SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) { - const float modificator = Min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); + const float modificator = Min(1.f, (plane->m_fSpeed - 0.103344f) * 1.6760077f); SetupJumboEngineSound(MAX_VOLUME * modificator, 6050.f * modificator + 16000); SetupJumboWhineSound(18, 29500); } From f760696a9f6052381536de466d2c4f783b4262c6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Jul 2020 19:37:28 +0300 Subject: [PATCH 53/85] Fix another float --- src/audio/AudioLogic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 6c025175..8fd2c2c9 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -2538,7 +2538,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) return true; velocityChange = Min(0.75f, velocityChange); - multiplier = (velocityChange - 0.0005f) * 1.3342f; + multiplier = (velocityChange - 0.0005f) * 1.3342229f; CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); vol = (30.f * multiplier); m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); From 2cfd3a9e923239e9a3973cab79f2b8b841611ec8 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 19 Jul 2020 00:37:12 +0200 Subject: [PATCH 54/85] CPlane fixes --- src/vehicles/Plane.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 1f5fcb5a..8a183a23 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -86,7 +86,7 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) m_level = LEVEL_GENERIC; #ifdef FIX_BUGS - m_isFarAway = true; + m_isFarAway = false; #endif } @@ -154,7 +154,7 @@ CPlane::ProcessControl(void) int f = ++nFrameGen & 3; CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); + colors[nFrameGen&7], rotSpeed, 0, f, 0); } } if(frm >= 40 && frm <= 80 && frm & 1){ @@ -197,17 +197,18 @@ CPlane::ProcessControl(void) colors[6] = CRGBA(0, 0, 0, 255); colors[7] = CRGBA(252, 66, 66, 255); + CVector dir; for(i = 0; i < 40; i++){ + dir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); + dir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); + dir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f); int rotSpeed = CGeneral::GetRandomNumberInRange(30.0f, 20.0f); if(CGeneral::GetRandomNumber() & 1) rotSpeed = -rotSpeed; int f = ++nFrameGen & 3; - CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), - CVector(CGeneral::GetRandomNumberInRange(-2.0f, 2.0f), - CGeneral::GetRandomNumberInRange(-2.0f, 2.0f), - CGeneral::GetRandomNumberInRange(0.0f, 2.0f)), + CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); + colors[nFrameGen&7], rotSpeed, 0, f, 0); } } if(frm >= 40 && frm <= 60 && frm & 1){ @@ -226,7 +227,7 @@ CPlane::ProcessControl(void) } if(frm == 30) bRenderScorched = true; - if(frm == 61){ + if(frm == 62){ TheCamera.SetFadeColour(200, 200, 200); TheCamera.Fade(0.0f, FADE_OUT); TheCamera.ProcessFade(); @@ -363,7 +364,7 @@ CPlane::ProcessControl(void) CVector posFront2 = (1.0f - f)*pPathNodes[curPathNodeFront2].p + f*pPathNodes[nextPathNodeFront2].p; // Now set matrix - GetMatrix().GetPosition() = (posRear + posFront) / 2.0f; + GetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f); GetMatrix().GetPosition().z += 4.3f; CVector fwd = posFront - posRear; fwd.Normalise(); @@ -388,7 +389,7 @@ CPlane::ProcessControl(void) m_fSpeed = PlanePathSpeed[m_nPlaneId]/60.0f; m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f)); + m_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f)); }else{ float planePathPosition; float totalLengthOfFlightPath; @@ -484,7 +485,7 @@ CPlane::ProcessControl(void) f = (pathPositionFront - pathNodes[curPathNodeFront].t)/dist; CVector posFront = (1.0f - f)*pathNodes[curPathNodeFront].p + f*pathNodes[nextPathNodeFront].p; - // And for another point 60 units in front of the plane, used to calculate roll + // And for another point 30 units in front of the plane, used to calculate roll float pathPositionFront2 = pathPositionFront + 30.0f; if(pathPositionFront2 > totalLengthOfFlightPath) pathPositionFront2 -= totalLengthOfFlightPath; @@ -515,7 +516,7 @@ CPlane::ProcessControl(void) CVector posFront2 = (1.0f - f)*pathNodes[curPathNodeFront2].p + f*pathNodes[nextPathNodeFront2].p; // Now set matrix - GetMatrix().GetPosition() = (posRear + posFront) / 2.0f; + GetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f); GetMatrix().GetPosition().z += 1.0f; CVector fwd = posFront - posRear; fwd.Normalise(); @@ -535,7 +536,7 @@ CPlane::ProcessControl(void) m_fSpeed = planePathSpeed/60.0f; m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f)); + m_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f)); } } From b8c2cf597db91188ceae24a702e2d276d4d89fd2 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 19 Jul 2020 00:56:13 +0200 Subject: [PATCH 55/85] figured out magic --- src/vehicles/Plane.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 8a183a23..b8a957cf 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -698,7 +698,7 @@ CPlane::InitPlanes(void) aPlaneLineBits[1].time = time; aPlaneLineBits[1].position = position; aPlaneLineBits[1].speed = TAXI_SPEED; - aPlaneLineBits[1].acceleration = 33.0f/32.0f; + aPlaneLineBits[1].acceleration = 618.75f/600.0f; time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); position += 600.0f; @@ -717,7 +717,7 @@ CPlane::InitPlanes(void) aPlaneLineBits[3].time = time; aPlaneLineBits[3].position = position; aPlaneLineBits[3].speed = CRUISE_SPEED; - aPlaneLineBits[3].acceleration = -33.0f/32.0f; + aPlaneLineBits[3].acceleration = -618.75f/600.0f; time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); position += 600.0f; From e74b569115a9f9596a0cf2def74dd37117fe2aae Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 19 Jul 2020 00:37:44 +0200 Subject: [PATCH 56/85] CPlane done --- src/render/Fluff.cpp | 12 ++ src/render/Fluff.h | 50 +++++++++ src/vehicles/Boat.cpp | 2 +- src/vehicles/Plane.cpp | 229 +++++++++++++++++++++++--------------- src/vehicles/Plane.h | 5 +- src/weapons/Explosion.cpp | 2 + src/weapons/Explosion.h | 2 + 7 files changed, 211 insertions(+), 91 deletions(-) diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 53b06a46..067d0742 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -19,6 +19,18 @@ #include "World.h" +void +CPlaneTrails::RegisterPoint(CVector pos, uint32 id) +{ + // TODO +} + +void +CPlaneBanners::RegisterPoint(CVector pos, uint32 id) +{ + // TODO +} + bool CSmokeTrails::CigOn = false; CSmokeTrail CSmokeTrails::aSmoke[3]; diff --git a/src/render/Fluff.h b/src/render/Fluff.h index 41db75ec..23b614b8 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -2,6 +2,56 @@ #include "common.h" #include "Vector.h" +// TODO +class CScriptPath +{ +public: +}; + +// TODO +class CScriptPaths +{ +public: +}; + +// TODO +class CPlaneTrail +{ +public: +}; + +// TODO +class CPlaneTrails +{ +public: + static void RegisterPoint(CVector pos, uint32 id); +}; + +// TODO +class CPlaneBanner +{ +public: +}; + +// TODO +class CPlaneBanners +{ +public: + static void RegisterPoint(CVector pos, uint32 id); +}; + +// TODO +class CEscalators +{ +public: +}; + +// TODO +class CEscalator +{ +public: +}; + class CMovingThing { public: diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 786b5f4d..ae437f56 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -851,7 +851,7 @@ CBoat::BlowUpCar(CEntity *culprit) bLightsOn = false; ChangeLawEnforcerState(false); - CExplosion::AddExplosion(this, culprit, EXPLOSION_HELI, GetPosition(), 0); + CExplosion::AddExplosion(this, culprit, EXPLOSION_BOAT, GetPosition(), 0); CDarkel::RegisterCarBlownUpByPlayer(this); if(m_aBoatNodes[BOAT_MOVING] == nil) return; diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index c275ff6e..9ea4a289 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -2,6 +2,7 @@ #include "main.h" #include "General.h" +#include "CutsceneMgr.h" #include "ModelIndices.h" #include "FileMgr.h" #include "Streaming.h" @@ -12,10 +13,13 @@ #include "Coronas.h" #include "Particle.h" #include "Explosion.h" +#include "Fluff.h" #include "World.h" #include "HandlingMgr.h" #include "Plane.h" +//--MIAMI: file done + CPlaneNode *pPathNodes; CPlaneNode *pPath2Nodes; CPlaneNode *pPath3Nodes; @@ -39,12 +43,10 @@ CPlaneInterpolationLine aPlaneLineBits[6]; float PlanePathPosition[3]; float OldPlanePathPosition[3]; float PlanePathSpeed[3]; -float PlanePath2Position[3]; -float PlanePath3Position; -float PlanePath4Position; -float PlanePath2Speed[3]; -float PlanePath3Speed; -float PlanePath4Speed; +float PlanePath2Position[5]; +float PlanePath3Position[4]; +float PlanePath2Speed[5]; +float PlanePath3Speed[4]; enum @@ -62,7 +64,6 @@ int32 DropOffCesnaMissionStatus; int32 DropOffCesnaMissionStartTime; CPlane *pDropOffCesna; - CPlane::CPlane(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) { @@ -80,14 +81,13 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) m_bHasBeenHit = false; m_bIsDrugRunCesna = false; m_bIsDropOffCesna = false; + m_bTempPlane = false; SetStatus(STATUS_PLANE); bIsBIGBuilding = true; m_level = LEVEL_GENERIC; -#ifdef FIX_BUGS - m_isFarAway = true; -#endif + m_isFarAway = false; } CPlane::~CPlane() @@ -123,6 +123,14 @@ CPlane::ProcessControl(void) int i; CVector pos; + if(CReplay::IsPlayingBack()) + return; + + if(GetModelIndex() == MI_AIRTRAIN) + CPlaneTrails::RegisterPoint(GetPosition(), m_nPlaneId); + else if(GetModelIndex() == MI_DEADDODO) + CPlaneBanners::RegisterPoint(GetPosition(), m_nPlaneId); + // Explosion if(m_bHasBeenHit){ // BUG: since this is all based on frames, you can skip the explosion processing when you go into the menu @@ -154,7 +162,7 @@ CPlane::ProcessControl(void) int f = ++nFrameGen & 3; CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); + colors[nFrameGen&7], rotSpeed, 0, f, 0); } } if(frm >= 40 && frm <= 80 && frm & 1){ @@ -197,17 +205,18 @@ CPlane::ProcessControl(void) colors[6] = CRGBA(0, 0, 0, 255); colors[7] = CRGBA(252, 66, 66, 255); + CVector dir; for(i = 0; i < 40; i++){ + dir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); + dir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); + dir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f); int rotSpeed = CGeneral::GetRandomNumberInRange(30.0f, 20.0f); if(CGeneral::GetRandomNumber() & 1) rotSpeed = -rotSpeed; int f = ++nFrameGen & 3; - CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), - CVector(CGeneral::GetRandomNumberInRange(-2.0f, 2.0f), - CGeneral::GetRandomNumberInRange(-2.0f, 2.0f), - CGeneral::GetRandomNumberInRange(0.0f, 2.0f)), + CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); + colors[nFrameGen&7], rotSpeed, 0, f, 0); } } if(frm >= 40 && frm <= 60 && frm & 1){ @@ -226,7 +235,7 @@ CPlane::ProcessControl(void) } if(frm == 30) bRenderScorched = true; - if(frm == 61){ + if(frm == 62){ TheCamera.SetFadeColour(200, 200, 200); TheCamera.Fade(0.0f, FADE_OUT); TheCamera.ProcessFade(); @@ -363,7 +372,7 @@ CPlane::ProcessControl(void) CVector posFront2 = (1.0f - f)*pPathNodes[curPathNodeFront2].p + f*pPathNodes[nextPathNodeFront2].p; // Now set matrix - GetMatrix().GetPosition() = (posRear + posFront) / 2.0f; + GetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f); GetMatrix().GetPosition().z += 4.3f; CVector fwd = posFront - posRear; fwd.Normalise(); @@ -382,13 +391,12 @@ CPlane::ProcessControl(void) GetMatrix().GetRight() = right; GetMatrix().GetUp() = up; GetMatrix().GetForward() = fwd; - // Set speed m_vecMoveSpeed = fwd*PlanePathSpeed[m_nPlaneId]/60.0f; m_fSpeed = PlanePathSpeed[m_nPlaneId]/60.0f; m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f)); + m_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f)); }else{ float planePathPosition; float totalLengthOfFlightPath; @@ -396,26 +404,12 @@ CPlane::ProcessControl(void) float planePathSpeed; int numPathNodes; - if(m_bIsDrugRunCesna){ - planePathPosition = PlanePath3Position; + if(GetModelIndex() == MI_CHOPPER){ + planePathPosition = PlanePath3Position[m_nPlaneId]; totalLengthOfFlightPath = TotalLengthOfFlightPath3; pathNodes = pPath3Nodes; - planePathSpeed = PlanePath3Speed; + planePathSpeed = PlanePath3Speed[m_nPlaneId]; numPathNodes = NumPath3Nodes; - if(CesnaMissionStatus == CESNA_STATUS_LANDED){ - pDrugRunCesna = nil; - FlagToDestroyWhenNextProcessed(); - } - }else if(m_bIsDropOffCesna){ - planePathPosition = PlanePath4Position; - totalLengthOfFlightPath = TotalLengthOfFlightPath4; - pathNodes = pPath4Nodes; - planePathSpeed = PlanePath4Speed; - numPathNodes = NumPath4Nodes; - if(DropOffCesnaMissionStatus == CESNA_STATUS_LANDED){ - pDropOffCesna = nil; - FlagToDestroyWhenNextProcessed(); - } }else{ planePathPosition = PlanePath2Position[m_nPlaneId]; totalLengthOfFlightPath = TotalLengthOfFlightPath2; @@ -484,7 +478,7 @@ CPlane::ProcessControl(void) f = (pathPositionFront - pathNodes[curPathNodeFront].t)/dist; CVector posFront = (1.0f - f)*pathNodes[curPathNodeFront].p + f*pathNodes[nextPathNodeFront].p; - // And for another point 60 units in front of the plane, used to calculate roll + // And for another point 30 units in front of the plane, used to calculate roll float pathPositionFront2 = pathPositionFront + 30.0f; if(pathPositionFront2 > totalLengthOfFlightPath) pathPositionFront2 -= totalLengthOfFlightPath; @@ -515,7 +509,7 @@ CPlane::ProcessControl(void) CVector posFront2 = (1.0f - f)*pathNodes[curPathNodeFront2].p + f*pathNodes[nextPathNodeFront2].p; // Now set matrix - GetMatrix().GetPosition() = (posRear + posFront) / 2.0f; + GetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f); GetMatrix().GetPosition().z += 1.0f; CVector fwd = posFront - posRear; fwd.Normalise(); @@ -535,7 +529,7 @@ CPlane::ProcessControl(void) m_fSpeed = planePathSpeed/60.0f; m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f)); + m_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f)); } } @@ -639,7 +633,8 @@ CPlane::PreRender(void) void CPlane::Render(void) { - CEntity::Render(); + if(!CCutsceneMgr::IsRunning()) + CEntity::Render(); } #define CRUISE_SPEED (50.0f) @@ -657,11 +652,9 @@ CPlane::InitPlanes(void) pPathNodes = LoadPath("data\\paths\\flight.dat", NumPathNodes, TotalLengthOfFlightPath, true); // Figure out which nodes are on ground - CColPoint colpoint; - CEntity *entity; for(i = 0; i < NumPathNodes; i++){ - if(CWorld::ProcessVerticalLine(pPathNodes[i].p, 1000.0f, colpoint, entity, true, false, false, false, true, false, nil)){ - pPathNodes[i].p.z = colpoint.point.z; + if(pPathNodes[i].p.z < 14.0f){ + pPathNodes[i].p.z = 14.0f; pPathNodes[i].bOnGround = true; }else pPathNodes[i].bOnGround = false; @@ -688,7 +681,7 @@ CPlane::InitPlanes(void) aPlaneLineBits[0].position = position; aPlaneLineBits[0].speed = TAXI_SPEED; aPlaneLineBits[0].acceleration = 0.0f; - float dist = (TakeOffPoint-600.0f) - position; + float dist = (TakeOffPoint-500.0f) - position; time += dist/TAXI_SPEED; position += dist; @@ -697,9 +690,9 @@ CPlane::InitPlanes(void) aPlaneLineBits[1].time = time; aPlaneLineBits[1].position = position; aPlaneLineBits[1].speed = TAXI_SPEED; - aPlaneLineBits[1].acceleration = 33.0f/32.0f; - time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); - position += 600.0f; + aPlaneLineBits[1].acceleration = 618.75f/500.0f; + time += 500.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); + position += 500.0f; // Fly at cruise speed aPlaneLineBits[2].type = 1; @@ -716,9 +709,9 @@ CPlane::InitPlanes(void) aPlaneLineBits[3].time = time; aPlaneLineBits[3].position = position; aPlaneLineBits[3].speed = CRUISE_SPEED; - aPlaneLineBits[3].acceleration = -33.0f/32.0f; - time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); - position += 600.0f; + aPlaneLineBits[3].acceleration = -618.75f/500.0f; + time += 500.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f); + position += 500.0f; // Taxi aPlaneLineBits[4].type = 1; @@ -739,20 +732,12 @@ CPlane::InitPlanes(void) TotalDurationOfFlightPath2 = TotalLengthOfFlightPath2/CRUISE_SPEED; } -/* - // Mission Cesna + // Heli if(pPath3Nodes == nil){ pPath3Nodes = LoadPath("data\\paths\\flight3.dat", NumPath3Nodes, TotalLengthOfFlightPath3, false); TotalDurationOfFlightPath3 = TotalLengthOfFlightPath3/CRUISE_SPEED; } - // Mission Cesna - if(pPath4Nodes == nil){ - pPath4Nodes = LoadPath("data\\paths\\flight4.dat", NumPath4Nodes, TotalLengthOfFlightPath4, false); - TotalDurationOfFlightPath4 = TotalLengthOfFlightPath4/CRUISE_SPEED; - } -*/ - CStreaming::LoadAllRequestedModels(false); CStreaming::RequestModel(MI_AIRTRAIN, 0); CStreaming::LoadAllRequestedModels(false); @@ -766,20 +751,6 @@ CPlane::InitPlanes(void) plane->m_nCurPathNode = 0; CWorld::Add(plane); } - - - CStreaming::RequestModel(MI_DEADDODO, 0); - CStreaming::LoadAllRequestedModels(false); - - for(i = 0; i < 3; i++){ - CPlane *plane = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE); - plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f); - plane->SetStatus(STATUS_ABANDONED); - plane->bIsLocked = true; - plane->m_nPlaneId = i; - plane->m_nCurPathNode = 0; - CWorld::Add(plane); - } } void @@ -811,7 +782,6 @@ CPlane::LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool CPlaneNode *nodes = new CPlaneNode[numNodes]; for(i = 0; i < numNodes; i++){ - *gString = '\0'; for(lp = 0; work_buff[bp] != '\n' && work_buff[bp] != '\0'; bp++, lp++) gString[lp] = work_buff[bp]; bp++; @@ -833,6 +803,10 @@ CPlane::LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool return nodes; } +int32 LastTimeInPlane, LastTimeNotInPlane; +bool bCesnasActivated; +bool bHelisActivated; + void CPlane::UpdatePlanes(void) { @@ -875,25 +849,87 @@ CPlane::UpdatePlanes(void) t = TotalDurationOfFlightPath2/0x80000; PlanePath2Position[0] = CRUISE_SPEED * (time & 0x7FFFF)*t; - PlanePath2Position[1] = CRUISE_SPEED * ((time + 0x80000/3) & 0x7FFFF)*t; - PlanePath2Position[2] = CRUISE_SPEED * ((time + 0x80000/3*2) & 0x7FFFF)*t; + PlanePath2Position[1] = CRUISE_SPEED * ((time + 0x80000/5) & 0x7FFFF)*t; + PlanePath2Position[2] = CRUISE_SPEED * ((time + 0x80000/5*2) & 0x7FFFF)*t; + PlanePath2Position[3] = CRUISE_SPEED * ((time + 0x80000/5*3) & 0x7FFFF)*t; + PlanePath2Position[4] = CRUISE_SPEED * ((time + 0x80000/5*4) & 0x7FFFF)*t; PlanePath2Speed[0] = CRUISE_SPEED*t; PlanePath2Speed[1] = CRUISE_SPEED*t; PlanePath2Speed[2] = CRUISE_SPEED*t; + PlanePath2Speed[3] = CRUISE_SPEED*t; + PlanePath2Speed[4] = CRUISE_SPEED*t; - if(CesnaMissionStatus == CESNA_STATUS_FLYING){ - PlanePath3Speed = CRUISE_SPEED*TotalDurationOfFlightPath3/0x20000; - PlanePath3Position = PlanePath3Speed * ((time - CesnaMissionStartTime) & 0x1FFFF); - if(time - CesnaMissionStartTime >= 128072) - CesnaMissionStatus = CESNA_STATUS_LANDED; - } + t = TotalDurationOfFlightPath3/0x80000; + PlanePath3Position[0] = CRUISE_SPEED * (time & 0x7FFFF)*t; + PlanePath3Position[1] = CRUISE_SPEED * ((time + 0x80000/4) & 0x7FFFF)*t; + PlanePath3Position[2] = CRUISE_SPEED * ((time + 0x80000/4*2) & 0x7FFFF)*t; + PlanePath3Position[3] = CRUISE_SPEED * ((time + 0x80000/4*3) & 0x7FFFF)*t; + PlanePath3Speed[0] = CRUISE_SPEED*t; + PlanePath3Speed[1] = CRUISE_SPEED*t; + PlanePath3Speed[2] = CRUISE_SPEED*t; + PlanePath3Speed[3] = CRUISE_SPEED*t; - if(DropOffCesnaMissionStatus == CESNA_STATUS_FLYING){ - PlanePath4Speed = CRUISE_SPEED*TotalDurationOfFlightPath4/0x80000; - PlanePath4Position = PlanePath4Speed * ((time - DropOffCesnaMissionStartTime) & 0x7FFFF); - if(time - DropOffCesnaMissionStartTime >= 521288) - DropOffCesnaMissionStatus = CESNA_STATUS_LANDED; + if(FindPlayerVehicle() && (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || + FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)) + LastTimeInPlane = CTimer::GetTimeInMilliseconds(); + else + LastTimeNotInPlane = CTimer::GetTimeInMilliseconds(); + + if(CTimer::GetTimeInMilliseconds() - LastTimeNotInPlane > 10000){ + if(!bCesnasActivated){ + if(CStreaming::HasModelLoaded(MI_DEADDODO)){ + for(i = 0; i < 5; i++){ + CPlane *plane = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE); + plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f); + plane->SetStatus(STATUS_ABANDONED); + plane->bIsLocked = true; + plane->m_nPlaneId = i; + plane->m_nCurPathNode = 0; + plane->m_bTempPlane = true; + CWorld::Add(plane); + } + bCesnasActivated = true; + }else + CStreaming::RequestModel(MI_DEADDODO, 0); + } + + if(!bHelisActivated){ + if(CStreaming::HasModelLoaded(MI_CHOPPER)){ + for(i = 0; i < 4; i++){ + CPlane *plane = new CPlane(MI_CHOPPER, PERMANENT_VEHICLE); + plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f); + plane->SetStatus(STATUS_ABANDONED); + plane->bIsLocked = true; + plane->m_nPlaneId = i; + plane->m_nCurPathNode = 0; + plane->m_bTempPlane = true; + CWorld::Add(plane); + } + bHelisActivated = true; + }else + CStreaming::RequestModel(MI_CHOPPER, 0); + } + }else if(CTimer::GetTimeInMilliseconds() - LastTimeInPlane > 10000) + RemoveTemporaryPlanes(); +} + +void +CPlane::RemoveTemporaryPlanes(void) +{ + int i; + if(!bHelisActivated && !bCesnasActivated) + return; + + i = CPools::GetVehiclePool()->GetSize(); + while(--i >= 0){ + CPlane *plane = (CPlane*)CPools::GetVehiclePool()->GetSlot(i); + if(plane && plane->IsPlane() && plane->m_bTempPlane){ + CWorld::Remove(plane); + delete plane; + } } + bCesnasActivated = false; + bHelisActivated = false; } bool @@ -921,6 +957,7 @@ CPlane::TestRocketCollision(CVector *rocketPos) return false; } +//--MIAMI: unused // BUG: not in CPlane in the game void CPlane::CreateIncomingCesna(void) @@ -944,6 +981,7 @@ CPlane::CreateIncomingCesna(void) printf("CPlane::CreateIncomingCesna(void)\n"); } +//--MIAMI: unused void CPlane::CreateDropOffCesna(void) { @@ -966,8 +1004,21 @@ CPlane::CreateDropOffCesna(void) printf("CPlane::CreateDropOffCesna(void)\n"); } +//--MIAMI: all unused const CVector CPlane::FindDrugPlaneCoordinates(void) { return pDrugRunCesna->GetPosition(); } const CVector CPlane::FindDropOffCesnaCoordinates(void) { return pDropOffCesna->GetPosition(); } bool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LANDED; } bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; } bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; } + +void +CPlane::Load(void) +{ + RemoveTemporaryPlanes(); +} + +void +CPlane::Save(void) +{ + RemoveTemporaryPlanes(); +} diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index e9456bcd..5fb05468 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -29,7 +29,6 @@ struct CPlaneInterpolationLine class CPlane : public CVehicle { public: - // 0x288 int16 m_nPlaneId; int16 m_isFarAway; int16 m_nCurPathNode; @@ -38,6 +37,7 @@ public: bool m_bHasBeenHit; bool m_bIsDrugRunCesna; bool m_bIsDropOffCesna; + bool m_bTempPlane; CPlane(int32 id, uint8 CreatedBy); ~CPlane(void); @@ -53,6 +53,7 @@ public: static void InitPlanes(void); static void Shutdown(void); static CPlaneNode *LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool loop); + static void RemoveTemporaryPlanes(void); static void UpdatePlanes(void); static bool TestRocketCollision(CVector *rocketPos); static void CreateIncomingCesna(void); @@ -62,6 +63,8 @@ public: static bool HasCesnaLanded(void); static bool HasCesnaBeenDestroyed(void); static bool HasDropOffCesnaBeenShotDown(void); + static void Load(void); + static void Save(void); }; extern float LandingPoint; diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp index f4ad346d..74af1375 100644 --- a/src/weapons/Explosion.cpp +++ b/src/weapons/Explosion.cpp @@ -170,6 +170,7 @@ CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionT break; case EXPLOSION_CAR: case EXPLOSION_CAR_QUICK: + case EXPLOSION_BOAT: explosion.m_fRadius = 9.0f; explosion.m_fPower = 300.0f; explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 4250; @@ -205,6 +206,7 @@ CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionT } break; case EXPLOSION_HELI: + case EXPLOSION_HELI2: explosion.m_fRadius = 6.0f; explosion.m_fPower = 300.0f; explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750; diff --git a/src/weapons/Explosion.h b/src/weapons/Explosion.h index c8539cca..cfa75ec1 100644 --- a/src/weapons/Explosion.h +++ b/src/weapons/Explosion.h @@ -10,7 +10,9 @@ enum eExplosionType EXPLOSION_ROCKET, EXPLOSION_CAR, EXPLOSION_CAR_QUICK, + EXPLOSION_BOAT, EXPLOSION_HELI, + EXPLOSION_HELI2, EXPLOSION_MINE, EXPLOSION_BARREL, EXPLOSION_TANK_GRENADE, From 1ff27e3363c4deb027619375ac289a6148cda529 Mon Sep 17 00:00:00 2001 From: majestic Date: Sun, 5 Jul 2020 13:45:09 -0700 Subject: [PATCH 57/85] cosmetic fixes --- src/core/config.h | 1 + src/core/main.cpp | 2 + src/entities/Entity.cpp | 35 ++++ src/entities/Entity.h | 3 +- src/render/Occlusion.cpp | 420 +++++++++++++++++++++++++++++++++++++++ src/render/Occlusion.h | 34 +++- src/vehicles/CarGen.cpp | 7 +- src/vehicles/CarGen.h | 2 +- 8 files changed, 494 insertions(+), 10 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index 798e6bb2..b5a6b343 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -67,6 +67,7 @@ enum Config { NUMATTRIBZONES = 704, NUMOCCLUSIONVOLUMES = 350, + NUMACTIVEOCCLUDERS = 48, PATHNODESIZE = 4500, diff --git a/src/core/main.cpp b/src/core/main.cpp index 6e6092f3..8b4ad471 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -61,6 +61,7 @@ #include "MemoryCard.h" #include "SceneEdit.h" #include "debugmenu.h" +#include "Occlusion.h" GlobalScene Scene; @@ -930,6 +931,7 @@ Render2dStuff(void) CGarages::PrintMessages(); CPad::PrintErrorMessage(); CFont::DrawFonts(); + COcclusion::Render(); #ifdef DEBUGMENU DebugMenuRender(); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 394b8162..fb59f791 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -31,6 +31,7 @@ #include "Ped.h" #include "Dummy.h" #include "WindModifiers.h" +#include "Occlusion.h" //--MIAMI: file almost done (see TODO) @@ -1157,3 +1158,37 @@ bool IsEntityPointerValid(CEntity* pEntity) } return false; } + +bool CEntity::IsEntityOccluded(void) { + return false; + + CVector coors; + float width, height; + + if (!COcclusion::NumActiveOccluders || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height)) + return false; + + float area = Max(width, height) * GetBoundRadius() * 0.9f; + + for (int i = 0; i < COcclusion::NumActiveOccluders; i++) { + if (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) { + if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) { + return true; + } + + if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) { + CVector min = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.min; + CVector max = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.max; + + if (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + + return true; + } + } + } + + return false; +} \ No newline at end of file diff --git a/src/entities/Entity.h b/src/entities/Entity.h index c3e4cc3b..7570110b 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -156,8 +156,7 @@ public: bool GetIsOnScreenComplex(void); bool IsVisible(void) { return m_rwObject && bIsVisible && GetIsOnScreen(); } bool IsVisibleComplex(void) { return m_rwObject && bIsVisible && GetIsOnScreenComplex(); } -// TODO(MIAMI): - bool IsEntityOccluded(void) { return false; } + bool IsEntityOccluded(void); int16 GetModelIndex(void) const { return m_modelIndex; } void UpdateRwFrame(void); void SetupBigBuilding(void); diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp index 1c4e4266..b31cc11e 100644 --- a/src/render/Occlusion.cpp +++ b/src/render/Occlusion.cpp @@ -1,13 +1,34 @@ #include "common.h" #include "Occlusion.h" +#include "Game.h" +#include "Camera.h" +#include "Vector.h" +#include "Draw.h" +#include "Timer.h" +#include "RwHelper.h" int32 COcclusion::NumOccludersOnMap; int16 COcclusion::FarAwayList; int16 COcclusion::NearbyList; int16 COcclusion::ListWalkThroughFA; int16 COcclusion::PreviousListWalkThroughFA; +int16 COcclusion::NumActiveOccluders; COccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES]; +CActiveOccluder COcclusion::aActiveOccluders[NUMACTIVEOCCLUDERS]; + +CVector gCenterOnScreen; + +float gMinYInOccluder; +float gMinXInOccluder; +float gMaxYInOccluder; +float gMaxXInOccluder; + +bool gOccluderCoorsValid[8]; +CVector gOccluderCoorsOnScreen[8]; +CVector gOccluderCoors[8]; + +bool bDisplayOccDebugStuff = false; void COcclusion::Init(void) @@ -17,6 +38,7 @@ COcclusion::Init(void) NearbyList = -1; ListWalkThroughFA = -1; PreviousListWalkThroughFA = -1; + bDisplayOccDebugStuff = false; } void @@ -38,7 +60,405 @@ COcclusion::AddOne(float x, float y, float z, float width, float length, float h FarAwayList = NumOccludersOnMap++; } +bool +COccluder::NearCamera() { + return (TheCamera.GetPosition() - CVector(x, y, z)).Magnitude() - (Max(width, length) / 2.0f) < 250.0f; +} + +bool +DoesInfiniteLineCrossFiniteLine(float p1X, float p1Y, float p2X, float p2Y, float lineX, float lineY, float lineDX, float lineDY) +{ + float side1 = (p1X - lineX) * lineDX - (p1Y - lineY) * lineDY; + float side2 = (p2X - lineX) * lineDX - (p2Y - lineY) * lineDY; + return side1 * side2 < 0.0f; // if points lie on opposite sides of the infinte line, the line between them crosses it +} + +bool DoesInfiniteLineTouchScreen(float p1X, float p1Y, float p2X, float p2Y) { + if (p1X > 0.0f && p1Y > 0.0f && SCREEN_WIDTH > p1X && SCREEN_HEIGHT > p1Y) + return true; + + return (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, p1X, p1Y, p2X, p2Y) || + DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y) || + DoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y) || + DoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y)); +} + +bool IsPointInsideLine(float lineX, float lineY, float lineDX, float lineDY, float pX, float pY, float area = 0.0f) { + return (pX - lineX) * lineDY - (pY - lineY) * lineDX >= area; +} + +bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh) { + *out = TheCamera.m_viewMatrix * in; + + if (out->z <= 1.0f) return false; + + float recip = 1.0f / out->z; + out->x *= SCREEN_WIDTH * recip; + out->y *= SCREEN_HEIGHT * recip; + + float fovScale = DefaultFOV / CDraw::GetFOV(); + + *outw = fovScale * recip * SCREEN_WIDTH; + *outh = fovScale * recip * SCREEN_HEIGHT; + + return true; +} + +bool CalcScreenCoors(CVector const &in, CVector *out) { + *out = TheCamera.m_viewMatrix * in; + + if (out->z <= 1.0f) return false; + + float recip = 1.0f / out->z; + out->x *= SCREEN_WIDTH * recip; + out->y *= SCREEN_HEIGHT * recip; + + return true; +} + +bool +COccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) { + if (!gOccluderCoorsValid[corner1] && !gOccluderCoorsValid[corner2]) + return false; + + float x1, y1, x2, y2; + + CVector origin3d, direction3d; + if (!gOccluderCoorsValid[corner1]) { + float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f); + float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f); + float ratio = clipDist2 / (clipDist1 + clipDist2); + CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; + + if (!CalcScreenCoors(clippedCoors, &origin3d, &x1, &y1)) + return true; + } + else { + origin3d = gOccluderCoorsOnScreen[corner1]; + } + + if (!gOccluderCoorsValid[corner2]) { + float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f); + float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f); + float ratio = clipDist1 / (clipDist1 + clipDist2); + CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; + + if (!CalcScreenCoors(clippedCoors, &direction3d, &x2, &y2)) + return true; + } + else { + direction3d = gOccluderCoorsOnScreen[corner2]; + } + + gMinXInOccluder = Min(Min(gMinXInOccluder, origin3d.x), direction3d.x); + gMaxXInOccluder = Max(Max(gMaxXInOccluder, origin3d.x), direction3d.x); + gMinYInOccluder = Min(Min(gMinYInOccluder, origin3d.y), direction3d.y); + gMaxYInOccluder = Max(Max(gMaxYInOccluder, origin3d.y), direction3d.y); + + CVector2D origin = (CVector2D)origin3d; + CVector2D direction = (CVector2D)direction3d - origin; + + if (!IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, gCenterOnScreen.x, gCenterOnScreen.y, 0.0f)) { + origin += direction; + direction *= -1.0f; + } + + float magnitude = direction.Magnitude(); + + occl->lines[occl->linesCount].origin = origin; + occl->lines[occl->linesCount].direction = direction / magnitude; + occl->lines[occl->linesCount].length = magnitude; + + if (!DoesInfiniteLineTouchScreen(origin.x, origin.y, direction.x, direction.y)) + return !IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f, 0.0f); + + occl->linesCount++; + + return false; +} + +bool +COccluder::ProcessOneOccluder(CActiveOccluder *occl) { + float outX, outY; + + occl->linesCount = 0; + CVector pos(x, y, z); + + if (!CalcScreenCoors(pos, &gCenterOnScreen, &outX, &outY) || gCenterOnScreen.z < -150.0f || gCenterOnScreen.z > 300.0f) { + return false; + } + + occl->radius = Max(width, length) * 0.35f + gCenterOnScreen.z; + + CVector vec[3]; + + vec[0].x = width / 2.0f * Sin(angle / 63556.0f*TWOPI); + vec[0].y = -width / 2.0f * Cos(angle / 63556.0f*TWOPI); + vec[0].z = 0.0f; + + vec[1].x = length / 2.0f * Cos(angle / 63556.0f*TWOPI); + vec[1].y = length / 2.0f * Sin(angle / 63556.0f*TWOPI); + vec[1].z = 0.0f; + + vec[2].x = 0.0f; + vec[2].y = 0.0f; + vec[2].z = height / 2.0f; + + bool aChecks[6]; int counter = -1; + for (int i = 0; i < 3; i++) { + aChecks[++counter] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f; + aChecks[++counter] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f; + } + + //calculating vertices of a box + gOccluderCoors[0] = pos + vec[0] + vec[1] + vec[2]; + gOccluderCoors[1] = pos - vec[0] + vec[1] + vec[2]; + gOccluderCoors[2] = pos + vec[0] - vec[1] + vec[2]; + gOccluderCoors[3] = pos - vec[0] - vec[1] + vec[2]; + gOccluderCoors[4] = pos + vec[0] + vec[1] - vec[2]; + gOccluderCoors[5] = pos - vec[0] + vec[1] - vec[2]; + gOccluderCoors[6] = pos + vec[0] - vec[1] - vec[2]; + gOccluderCoors[7] = pos - vec[0] - vec[1] - vec[2]; + + for(int i = 0; i < 8; i++) + gOccluderCoorsValid[i] = CalcScreenCoors(gOccluderCoors[i], &gOccluderCoorsOnScreen[i], &outX, &outY); + + gMinYInOccluder = 999999.875f; + gMinXInOccluder = 999999.875f; + gMaxYInOccluder = -999999.875f; + gMaxXInOccluder = -999999.875f; + + if (aChecks[2] != aChecks[0] && ProcessLineSegment(0, 4, occl)) + return false; + if (aChecks[3] != aChecks[0] && ProcessLineSegment(2, 6, occl)) + return false; + if (aChecks[4] != aChecks[0] && ProcessLineSegment(0, 2, occl)) + return false; + if (aChecks[5] != aChecks[0] && ProcessLineSegment(4, 6, occl)) + return false; + if (aChecks[2] != aChecks[1] && ProcessLineSegment(1, 5, occl)) + return false; + if (aChecks[3] != aChecks[1] && ProcessLineSegment(3, 7, occl)) + return false; + if (aChecks[4] != aChecks[1] && ProcessLineSegment(1, 3, occl)) + return false; + if (aChecks[5] != aChecks[1] && ProcessLineSegment(5, 7, occl)) + return false; + if (aChecks[4] != aChecks[2] && ProcessLineSegment(0, 1, occl)) + return false; + if (aChecks[3] != aChecks[4] && ProcessLineSegment(2, 3, occl)) + return false; + if (aChecks[5] != aChecks[3] && ProcessLineSegment(6, 7, occl)) + return false; + if (aChecks[2] != aChecks[5] && ProcessLineSegment(4, 5, occl)) + return false; + + if (gMaxXInOccluder - gMinXInOccluder < SCREEN_WIDTH * 0.1f || + gMaxYInOccluder - gMinYInOccluder < SCREEN_HEIGHT * 0.07f) + return false; + + return true; +} + +bool +COcclusion::OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2) { + for (int i = 0; i < occl1->linesCount; i++) { + for (int j = 0; j < occl2->linesCount; j++) { + if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x, + occl2->lines[j].direction.y, occl1->lines[i].origin.x, occl1->lines[i].origin.y, 0.0f)) + return false; + + + if (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x, + occl2->lines[j].direction.y, (occl1->lines[i].origin.x + occl1->lines[i].direction.x * occl1->lines[i].length), + (occl1->lines[i].origin.y + occl1->lines[i].direction.y * occl1->lines[i].length), 0.0f)) + return false; + } + } + + return true; +} + void COcclusion::ProcessBeforeRendering(void) { + NumActiveOccluders = 0; + + if (CGame::currArea != AREA_MAIN_MAP) + return; + + if (ListWalkThroughFA == -1) { + PreviousListWalkThroughFA = -1; + ListWalkThroughFA = FarAwayList; + } + + int i; + for (i = 0; i < 16 && ListWalkThroughFA != -1; i++) { + if (aOccluders[ListWalkThroughFA].NearCamera()) { + int prevListWalkThroughFA = ListWalkThroughFA; + + if (PreviousListWalkThroughFA == -1) { + FarAwayList = aOccluders[ListWalkThroughFA].listIndex; + } + else { + aOccluders[PreviousListWalkThroughFA].listIndex = aOccluders[ListWalkThroughFA].listIndex; + } + + int prevNearbyList = NearbyList; + ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex; + NearbyList = prevListWalkThroughFA; + aOccluders[prevListWalkThroughFA].listIndex = prevNearbyList; + } + else { + PreviousListWalkThroughFA = ListWalkThroughFA; + ListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex; + } + } + + int prevNearbyList = -1; + int tmpNearbyList = NearbyList; + int indexTmpNearbyList, storeTmpNearbyList, prevFarAwayList; + while (tmpNearbyList != -1) + { + if (NumActiveOccluders < NUMACTIVEOCCLUDERS && aOccluders[tmpNearbyList].ProcessOneOccluder(&aActiveOccluders[NumActiveOccluders])) + ++NumActiveOccluders; + + indexTmpNearbyList = tmpNearbyList; + if (aOccluders[indexTmpNearbyList].NearCamera()) + { + prevNearbyList = tmpNearbyList; + tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex; + + } + else + { + storeTmpNearbyList = tmpNearbyList; + if (prevNearbyList == -1) { + NearbyList = aOccluders[indexTmpNearbyList].listIndex; + } + else { + aOccluders[prevNearbyList].listIndex = aOccluders[indexTmpNearbyList].listIndex; + } + tmpNearbyList = aOccluders[indexTmpNearbyList].listIndex; + prevFarAwayList = FarAwayList; + FarAwayList = storeTmpNearbyList; + aOccluders[storeTmpNearbyList].listIndex = prevFarAwayList; + } + } + + //printf("NumActiveOccluders = %d\n", NumActiveOccluders); + + for (i = 0; i < NumActiveOccluders; i++) { + for (int j = 0; j < NumActiveOccluders; j++) { + if (i != j || aActiveOccluders[j].radius < aActiveOccluders[i].radius) { + if (OccluderHidesBehind(&aActiveOccluders[i], &aActiveOccluders[j])) { + for (int k = i; k < NumActiveOccluders - 1; k++) { + for (int l = 0; l < aActiveOccluders[k].linesCount; l++) + aActiveOccluders[k].lines[l] = aActiveOccluders[k + 1].lines[l]; + aActiveOccluders[k].linesCount = aActiveOccluders[k + 1].linesCount; + aActiveOccluders[k].radius = aActiveOccluders[k + 1].radius; + } + } + } + } + } } + +bool CActiveOccluder::IsPointWithinOcclusionArea(float pX, float pY, float area) { + for (int i = 0; i < linesCount; i++) { + if (!IsPointInsideLine(lines[i].origin.x, lines[i].origin.y, lines[i].direction.x, lines[i].direction.y, pX, pY, area)) + return false; + } + + return true; +} + +bool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float height) { + return false; + + CVector coors; + float outW, outH; + + if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &outW, &outH)) + return false; + + float side = CVector(width, length, height).Magnitude() / 4.0f; + float area = Max(outW, outH) * side; + + CVector minCorner, maxCorner; + + minCorner.x = pos.x - width / 2.0f; + minCorner.y = pos.y - length / 2.0f; + minCorner.z = pos.z - height / 2.0f; + + maxCorner.x = pos.x + width / 2.0f; + maxCorner.y = pos.y + length / 2.0f; + maxCorner.z = pos.z + height / 2.0f; + + for (int i = 0; i < NumActiveOccluders; i++) { + if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) { + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) + return true; + + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) { + if (CalcScreenCoors(minCorner, &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(maxCorner.x, maxCorner.y, minCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(maxCorner.x, minCorner.y, maxCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + if (CalcScreenCoors(CVector(minCorner.x, maxCorner.y, maxCorner.z), &coors, &outW, &outH) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue; + + return true; + } + } + } + + return false; +} + +bool COcclusion::IsPositionOccluded(CVector pos, float side) { + return false; + + CVector coors; + float width, height; + + if (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &width, &height)) + return false; + + float area = Max(width, height) * side; + + for (int i = 0; i < NumActiveOccluders; i++) { + if (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) + if (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) + return true; + } + + return false; +} + +void COcclusion::Render() { + if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200)) + return; + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, FALSE); + + for (int i = 0; i < NumActiveOccluders; i++) { + for (int j = 0; j < aActiveOccluders[i].linesCount; j++) { + RwIm2DVertex vertexbufferT[2]; + RwIm2DVertexSetScreenX(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.x); + RwIm2DVertexSetScreenY(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.y); + RwIm2DVertexSetScreenX(&vertexbufferT[1], + aActiveOccluders[i].lines[j].origin.x + aActiveOccluders[i].lines[j].direction.x * aActiveOccluders[i].lines[j].length); + RwIm2DVertexSetScreenY(&vertexbufferT[1], + aActiveOccluders[i].lines[j].origin.y + aActiveOccluders[i].lines[j].direction.y * aActiveOccluders[i].lines[j].length); + RwIm2DVertexSetIntRGBA(&vertexbufferT[0], 255, 255, 0, 255); + RwIm2DVertexSetIntRGBA(&vertexbufferT[1], 255, 255, 0, 255); + RwIm2DRenderLine(vertexbufferT, 2, 0, 1); + } + } + + DefinedState(); +} \ No newline at end of file diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h index 0d3e26e9..9b7ba34f 100644 --- a/src/render/Occlusion.h +++ b/src/render/Occlusion.h @@ -1,5 +1,21 @@ #pragma once +struct ActiveOccluderLine { + CVector2D origin; + CVector2D direction; + float length; +}; + +class CActiveOccluder { + +public: + ActiveOccluderLine lines[6]; + int32 linesCount; + float radius; + + bool IsPointWithinOcclusionArea(float x, float y, float area); +}; + class COccluder { public: @@ -7,6 +23,10 @@ public: int16 x, y, z; uint16 angle; int16 listIndex; + + bool NearCamera(); + bool ProcessOneOccluder(CActiveOccluder *occl); + bool ProcessLineSegment(int corner1, int corner2, CActiveOccluder* occl); }; class COcclusion @@ -17,13 +37,19 @@ public: static int16 NearbyList; static int16 ListWalkThroughFA; static int16 PreviousListWalkThroughFA; + static int16 NumActiveOccluders; static COccluder aOccluders[NUMOCCLUSIONVOLUMES]; + static CActiveOccluder aActiveOccluders[NUMACTIVEOCCLUDERS]; static void Init(void); static void AddOne(float x, float y, float z, float width, float length, float height, float angle); - static void ProcessBeforeRendering(void); - - //TODO: - static bool IsAABoxOccluded(CVector pos, float, float, float) { return false; } + static void ProcessBeforeRendering(void); + static bool OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2); + static bool IsAABoxOccluded(CVector pos, float width, float length, float height); + static bool IsPositionOccluded(CVector pos, float side); + static void Render(); }; + +bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh); +bool CalcScreenCoors(CVector const &in, CVector *out); \ No newline at end of file diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 2a048881..4b83cc81 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -16,6 +16,7 @@ #include "VisibilityPlugins.h" #include "World.h" #include "Zones.h" +#include "Occlusion.h" uint8 CTheCarGenerators::ProcessCounter; uint32 CTheCarGenerators::NumOfCarGenerators; @@ -151,7 +152,7 @@ void CCarGenerator::Process() { if (m_nVehicleHandle == -1 && (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) && - m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayer()) + m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayers()) DoInternalProcessing(); if (m_nVehicleHandle == -1) return; @@ -203,14 +204,14 @@ bool CCarGenerator::CheckForBlockage(int32 mi) return false; } -bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer() +bool CCarGenerator::CheckIfWithinRangeOfAnyPlayers() { CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos; float distance = direction.Magnitude(); float farclip = 110.0f * TheCamera.GenerationDistMultiplier; float nearclip = farclip - 20.0f; bool canBeRemoved = (m_nModelIndex > 0 && CModelInfo::IsBoatModel(m_nModelIndex) && 165.0f * TheCamera.GenerationDistMultiplier > distance && - TheCamera.IsSphereVisible(m_vecPos, 0.0f)); // TODO(MIAMI) COcclision::IsPositionOccluded(m_vecPos, 0.0f) + TheCamera.IsSphereVisible(m_vecPos, 0.0f) && COcclusion::IsPositionOccluded(m_vecPos, 0.0f)); if (distance >= farclip || canBeRemoved){ if (m_bIsBlocking) m_bIsBlocking = false; diff --git a/src/vehicles/CarGen.h b/src/vehicles/CarGen.h index 684f93ee..fccbee96 100644 --- a/src/vehicles/CarGen.h +++ b/src/vehicles/CarGen.h @@ -30,7 +30,7 @@ public: 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(int32 mi); - bool CheckIfWithinRangeOfAnyPlayer(); + bool CheckIfWithinRangeOfAnyPlayers(); void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; } }; From efd49962d281c1c32aff300cd7fb5f9e24c28571 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Jul 2020 19:32:20 +0200 Subject: [PATCH 58/85] avoid UB --- src/core/Camera.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 340dbaee..44749fd7 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3622,7 +3622,7 @@ bool CCamera::IsPointVisible(const CVector ¢er, const CMatrix *mat) { RwV3d c; - c = *(RwV3d*)¢er; + c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y < CDraw::GetNearClipZ()) return false; if(c.y > CDraw::GetFarClipZ()) return false; @@ -3637,7 +3637,7 @@ bool CCamera::IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat) { RwV3d c; - c = *(RwV3d*)¢er; + c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y + radius < CDraw::GetNearClipZ()) return false; if(c.y - radius > CDraw::GetFarClipZ()) return false; From 2612c9f12cf0e787e5b3bac955a5488b101111e8 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Jul 2020 19:31:59 +0200 Subject: [PATCH 59/85] CPlaneTrails and CPlaneBanners done --- src/core/Camera.cpp | 4 +- src/render/Fluff.cpp | 295 ++++++++++++++++++++++++++++++++++-- src/render/Fluff.h | 22 ++- src/render/RenderBuffer.cpp | 3 +- src/render/RenderBuffer.h | 10 +- src/render/Rubbish.h | 2 + src/render/Sprite2d.cpp | 4 +- src/vehicles/Plane.cpp | 8 +- 8 files changed, 321 insertions(+), 27 deletions(-) diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 900c1b64..eeb8630a 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -4031,7 +4031,7 @@ bool CCamera::IsPointVisible(const CVector ¢er, const CMatrix *mat) { RwV3d c; - c = *(RwV3d*)¢er; + c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y < CDraw::GetNearClipZ()) return false; if(c.y > CDraw::GetFarClipZ()) return false; @@ -4046,7 +4046,7 @@ bool CCamera::IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat) { RwV3d c; - c = *(RwV3d*)¢er; + c = center; RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix); if(c.y + radius < CDraw::GetNearClipZ()) return false; if(c.y - radius > CDraw::GetFarClipZ()) return false; diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 067d0742..fc6e6853 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -1,11 +1,14 @@ #include "common.h" #include "main.h" +#include "RenderBuffer.h" #include "Entity.h" #include "Fluff.h" #include "Camera.h" #include "Sprite.h" #include "Coronas.h" +#include "Rubbish.h" +#include "Timecycle.h" #include "General.h" #include "Timer.h" #include "Clock.h" @@ -18,17 +21,276 @@ #include "Bones.h" #include "World.h" +CPlaneTrail CPlaneTrails::aArray[6]; +RwImVertexIndex TrailIndices[32] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 +}; + +void +CPlaneTrail::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(m_time); i++) + m_time[i] = 0; +} + +void +CPlaneTrail::Render(float visibility) +{ + int i; + int numVerts = 0; + if(!TheCamera.IsSphereVisible(m_pos[0], 1000.0f)) + return; + + int alpha = visibility*110.0f; + if(alpha == 0) + return; + + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + int32 time = CTimer::GetTimeInMilliseconds() - m_time[i]; + if(time > 30000) + m_time[i] = 0; + if(m_time[i] != 0){ + float fade = (30000.0f - time) / 10000.0f; + fade = Min(fade, 1.0f); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[numVerts], 255, 255, 255, (int)(alpha*fade)); + RwIm3DVertexSetPos(&TempBufferRenderVertices[numVerts], m_pos[i].x, m_pos[i].y, m_pos[i].z); + numVerts++; + } + } + if(numVerts > 1){ + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + if(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, TrailIndices, (numVerts-1)*2); + RwIm3DEnd(); + } + } +} + +void +CPlaneTrail::RegisterPoint(CVector pos) +{ + int i; + bool bNewPoint = false; + if(m_time[0] != 0 && CTimer::GetTimeInMilliseconds() - m_time[0] > 2000){ + bNewPoint = true; + for(i = ARRAY_SIZE(m_pos)-1; i > 0; i--){ + m_pos[i] = m_pos[i-1]; + m_time[i] = m_time[i-1]; + } + } + m_pos[0] = pos; + if(bNewPoint || m_time[0] == 0) + m_time[0] = CTimer::GetTimeInMilliseconds(); +} + +void +CPlaneTrails::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Init(); +} + +void +CPlaneTrails::Update(void) +{ + CVector planePos; + + planePos.x = 1590.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = 1200.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 550.0f; + RegisterPoint(planePos, 3); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(101, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(101, planePos, 2000.0f, 0.0f); + } + + planePos.x = 1000.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = -1600.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 500.0f; + RegisterPoint(planePos, 4); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(102, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(102, planePos, 2000.0f, 0.0f); + } + + planePos.x = 1100.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.y = 700.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI); + planePos.z = 600.0f; + RegisterPoint(planePos, 5); + if(CClock::GetHours() > 22 || CClock::GetHours() < 7){ + if(CTimer::GetTimeInMilliseconds() & 0x200) + CCoronas::RegisterCorona(103, 255, 0, 0, 255, planePos, 5.0f, 2000.0f, + CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, + CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + else + CCoronas::UpdateCoronaCoors(103, planePos, 2000.0f, 0.0f); + } +} + +void +CPlaneTrails::Render(void) +{ + int i; + float visibility = Min(1.0f-CWeather::Foggyness, 1.0f-CWeather::CloudCoverage); + visibility = Min(visibility, 1.0f-CWeather::Rain); + visibility = Min(Max(Max(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen()), CTimeCycle::GetSkyTopBlue())/256.0f, visibility); + if(visibility > 0.0001f) + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Render(visibility); +} void CPlaneTrails::RegisterPoint(CVector pos, uint32 id) { - // TODO + aArray[id].RegisterPoint(pos); +} + + + +CPlaneBanner CPlaneBanners::aArray[5]; + +void +CPlaneBanner::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + m_pos[i].x = i; + m_pos[i].y = 0.0f; + m_pos[i].z = -60.0f; + } +} + +void +CPlaneBanner::Update(void) +{ + int i; + if(m_pos[0].z > -50.0f){ + m_pos[0].z -= 0.05f*CTimer::GetTimeStep(); + m_pos[0].z = Max(m_pos[0].z, -100.0f); + for(i = 1; i < ARRAY_SIZE(m_pos); i++){ + CVector dist = m_pos[i] - m_pos[i-1]; + float len = dist.Magnitude(); + if(len > 8.0f) + m_pos[i] = m_pos[i-1] + dist/len*8.0f; + } + } +} + +void +CPlaneBanner::Render(void) +{ + int i; + if(m_pos[0].z > -50.0f){ + float camDist = (TheCamera.GetPosition() - m_pos[0]).Magnitude(); + if(TheCamera.IsSphereVisible(m_pos[4], 32.0f) && camDist < 300.0f){ + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + int alpha = camDist < 250.0f ? 160 : (300.0f-camDist)/(300.0f-250.0f)*160; + + TempBufferVerticesStored += 2; + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, alpha); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[0], m_pos[2].x, m_pos[2].y, m_pos[2].z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[1], m_pos[2].x, m_pos[2].y, m_pos[2].z - 4.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[0], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[1], 0.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f); + for(i = 2; i < 8; i++){ + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], 255, 255, 255, alpha); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], 255, 255, 255, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0], m_pos[i].x, m_pos[i].y, m_pos[i].z); + RwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1], m_pos[i].x, m_pos[i].y, m_pos[i].z - 4.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], (i-2)/5.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f); + RwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], (i-2)/5.0f); + RwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f); + TempBufferRenderIndexList[TempBufferIndicesStored+0] = TempBufferVerticesStored-2; + TempBufferRenderIndexList[TempBufferIndicesStored+1] = TempBufferVerticesStored-1; + TempBufferRenderIndexList[TempBufferIndicesStored+2] = TempBufferVerticesStored+1; + TempBufferRenderIndexList[TempBufferIndicesStored+3] = TempBufferVerticesStored-2; + TempBufferRenderIndexList[TempBufferIndicesStored+4] = TempBufferVerticesStored+1; + TempBufferRenderIndexList[TempBufferIndicesStored+5] = TempBufferVerticesStored; + TempBufferVerticesStored += 2; + TempBufferIndicesStored += 6; + } + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[2])); + +#ifdef FIX_BUGS + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV)){ +#else + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 0)){ +#endif + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored); + RwIm3DEnd(); + } + + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + + TempBufferVerticesStored = 0; + TempBufferIndicesStored = 0; + } + } +} + +void +CPlaneBanner::RegisterPoint(CVector pos) +{ + m_pos[0] = pos; +} + +void +CPlaneBanners::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Init(); +} + +void +CPlaneBanners::Update(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Update(); +} + +void +CPlaneBanners::Render(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aArray); i++) + aArray[i].Render(); } void CPlaneBanners::RegisterPoint(CVector pos, uint32 id) { - // TODO + aArray[id].RegisterPoint(pos); } bool CSmokeTrails::CigOn = false; @@ -125,7 +387,9 @@ CMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS]; void CMovingThings::Init() { + CPlaneTrails::Init(); CSmokeTrails::Init(); + CPlaneBanners::Init(); StartCloseList.m_pNext = &CMovingThings::EndCloseList; StartCloseList.m_pPrev = nil; @@ -174,14 +438,19 @@ void CMovingThings::Shutdown() int i; for (i = 0; i < ARRAY_SIZE(aScrollBars); ++i) aScrollBars[i].SetVisibility(false); +/* for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i) aTowerClocks[i].SetVisibility(false); for (i = 0; i < ARRAY_SIZE(aDigitalClocks); ++i) aDigitalClocks[i].SetVisibility(false); +*/ } void CMovingThings::Update() { + CPlaneBanners::Update(); + CPlaneTrails::Update(); + const int TIME_SPAN = 64; // frames to process all aMovingThings int16 i; @@ -226,6 +495,7 @@ void CMovingThings::Render() if (aScrollBars[i].IsVisible()) aScrollBars[i].Render(); } +/* for (i = 0; i < ARRAY_SIZE(aTowerClocks); ++i) { if (aTowerClocks[i].IsVisible()) @@ -236,8 +506,11 @@ void CMovingThings::Render() if (aDigitalClocks[i].IsVisible()) aDigitalClocks[i].Render(); } +*/ + CPlaneTrails::Render(); CSmokeTrails::Render(); + CPlaneBanners::Render(); } // ---------- CMovingThing ---------- @@ -946,7 +1219,6 @@ CSmokeTrails::Render(void) { void CSmokeTrail::Render(void) { int numVerts = 0; - RwIm3DVertex TempVertexBuffer[16]; if (TheCamera.IsSphereVisible(m_pos[0], 10.0f)) { for (int32 i = 0; i < 16; i++) { @@ -961,8 +1233,8 @@ CSmokeTrail::Render(void) { float posX = (m_pos[i].x + timeSinceSpawned * RandomSmoke[(i - m_seed) & 0xF] * 0.00001f) - offset; float posY = (m_pos[i].y + timeSinceSpawned * RandomSmoke[(i - m_seed + 5) & 0xF] * 0.00001f) - offset; float posZ = m_pos[i].z + timeSinceSpawned * 0.0004f; - RwIm3DVertexSetRGBA(&TempVertexBuffer[i], 200, 200, 200, alpha); - RwIm3DVertexSetPos(&TempVertexBuffer[i], posX, posY, posZ); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 200, 200, 200, alpha); + RwIm3DVertexSetPos(&TempBufferRenderVertices[i], posX, posY, posZ); numVerts++; } } @@ -974,7 +1246,7 @@ CSmokeTrail::Render(void) { RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - if (RwIm3DTransform(TempVertexBuffer, numVerts, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { + if (RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2 * (numVerts - 1)); RwIm3DEnd(); } @@ -1006,13 +1278,12 @@ CSmokeTrails::Update(void) { RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - RwIm3DVertex TempVertexBuffer[2]; - RwIm3DVertexSetRGBA(&TempVertexBuffer[0], 255, 255, 255, 255); - RwIm3DVertexSetPos(&TempVertexBuffer[0], startPos.x, startPos.y, startPos.z); - RwIm3DVertexSetRGBA(&TempVertexBuffer[1], 255, 255, 255, 255); - RwIm3DVertexSetPos(&TempVertexBuffer[1], endPos.x, endPos.y, endPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[0], startPos.x, startPos.y, startPos.z); + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, 255); + RwIm3DVertexSetPos(&TempBufferRenderVertices[1], endPos.x, endPos.y, endPos.z); - if (RwIm3DTransform(TempVertexBuffer, 2, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { + if (RwIm3DTransform(TempBufferRenderVertices, 2, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) { RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2); RwIm3DEnd(); } diff --git a/src/render/Fluff.h b/src/render/Fluff.h index 23b614b8..b8b529f3 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -14,29 +14,43 @@ class CScriptPaths public: }; -// TODO class CPlaneTrail { + CVector m_pos[16]; + int32 m_time[16]; public: + void Init(void); + void Render(float visibility); + void RegisterPoint(CVector pos); }; -// TODO class CPlaneTrails { + static CPlaneTrail aArray[6]; // NB: 3 CPlanes and 3 hardcoded far away ones public: + static void Init(void); + static void Update(void); + static void Render(void); static void RegisterPoint(CVector pos, uint32 id); }; -// TODO class CPlaneBanner { + CVector m_pos[8]; public: + void Init(void); + void Update(void); + void Render(void); + void RegisterPoint(CVector pos); }; -// TODO class CPlaneBanners { + static CPlaneBanner aArray[5]; public: + static void Init(void); + static void Update(void); + static void Render(void); static void RegisterPoint(CVector pos, uint32 id); }; diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp index b4f48a26..687cc76b 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/render/RenderBuffer.cpp @@ -5,8 +5,7 @@ int32 TempBufferVerticesStored; int32 TempBufferIndicesStored; -RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; -RwIm2DVertex *TempVertexBuffer = (RwIm2DVertex*)TempBufferRenderVertices; +VertexBufferUnion TempVertexBuffer; RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; int RenderBuffer::VerticesToBeStored; diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h index 0789dfa5..a0f3e7b9 100644 --- a/src/render/RenderBuffer.h +++ b/src/render/RenderBuffer.h @@ -12,8 +12,14 @@ public: #define TEMPBUFFERVERTSIZE 512 #define TEMPBUFFERINDEXSIZE 1024 +struct VertexBufferUnion +{ + RwIm2DVertex im2d[TEMPBUFFERVERTSIZE]; + RwIm3DVertex im3d[TEMPBUFFERVERTSIZE]; +}; + extern int32 TempBufferVerticesStored; extern int32 TempBufferIndicesStored; -extern RwIm2DVertex *TempVertexBuffer; -extern RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +extern VertexBufferUnion TempVertexBuffer; +#define TempBufferRenderVertices (TempVertexBuffer.im3d) extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; \ No newline at end of file diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h index 2be592fe..52050e20 100644 --- a/src/render/Rubbish.h +++ b/src/render/Rubbish.h @@ -49,3 +49,5 @@ public: static void Init(void); static void Shutdown(void); }; + +extern RwTexture *gpRubbishTexture[4]; diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index b71039e8..cba64e7a 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -432,7 +432,7 @@ void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, void CSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2) { - SetVertices(&TempVertexBuffer[nextBufferVertex], r, c, c, c, c, u0, v0, u1, v1, u3, v3, u2, v2); + SetVertices(&TempVertexBuffer.im2d[nextBufferVertex], r, c, c, c, c, u0, v0, u1, v1, u3, v3, u2, v2); RwImVertexIndex *pIndexList = &TempBufferRenderIndexList[nextBufferIndex]; pIndexList[0] = nextBufferVertex; pIndexList[1] = nextBufferVertex + 1; @@ -457,7 +457,7 @@ CSprite2d::RenderVertexBuffer() { if (nextBufferVertex > 0) { RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempVertexBuffer, nextBufferVertex, TempBufferRenderIndexList, nextBufferIndex); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempVertexBuffer.im2d, nextBufferVertex, TempBufferRenderIndexList, nextBufferIndex); nextBufferVertex = 0; nextBufferIndex = 0; } diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 9ea4a289..a3754854 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -126,9 +126,10 @@ CPlane::ProcessControl(void) if(CReplay::IsPlayingBack()) return; - if(GetModelIndex() == MI_AIRTRAIN) - CPlaneTrails::RegisterPoint(GetPosition(), m_nPlaneId); - else if(GetModelIndex() == MI_DEADDODO) + if(GetModelIndex() == MI_AIRTRAIN){ + if(GetPosition().z > 100.0f) + CPlaneTrails::RegisterPoint(GetPosition(), m_nPlaneId); + }else if(GetModelIndex() == MI_DEADDODO) CPlaneBanners::RegisterPoint(GetPosition(), m_nPlaneId); // Explosion @@ -742,6 +743,7 @@ CPlane::InitPlanes(void) CStreaming::RequestModel(MI_AIRTRAIN, 0); CStreaming::LoadAllRequestedModels(false); + // NB: 3 hardcoded also in CPlaneTrails for(i = 0; i < 3; i++){ CPlane *plane = new CPlane(MI_AIRTRAIN, PERMANENT_VEHICLE); plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f); From 70df13f9d34fd855b78f74d7f1da8423241f8b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 20 Jul 2020 22:47:41 +0300 Subject: [PATCH 60/85] Fixes from miami --- src/control/Script.cpp | 50 ++++----- src/core/Frontend.cpp | 18 ++-- src/core/Frontend.h | 2 +- src/peds/Ped.cpp | 227 ++++++++++++++++------------------------- src/peds/Ped.h | 3 +- src/skel/glfw/glfw.cpp | 4 - 6 files changed, 118 insertions(+), 186 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 27e40106..6eb802b4 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -2823,9 +2823,8 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2)); else UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -2844,9 +2843,8 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); else UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -3425,9 +3423,8 @@ int8 CRunningScript::ProcessCommands100To199(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((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -3452,9 +3449,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); else UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -3671,9 +3667,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -3690,9 +3685,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) float y2 = *(float*)&ScriptParams[5]; float z2 = *(float*)&ScriptParams[6]; UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -4429,9 +4423,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -4449,9 +4442,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float z2 = *(float*)&ScriptParams[6]; UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -7279,9 +7271,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -7296,9 +7287,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index e67e939a..6e4e8917 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -956,10 +956,10 @@ CMenuManager::Draw() CFont::SetDropShadowPosition(0); if (!CheckHover(MENU_X(30.0f), MENU_X(30.0f) + CFont::GetStringWidth(backTx), SCREEN_SCALE_FROM_BOTTOM(125.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f))) { m_nHoverOption = HOVEROPTION_NOT_HOVERING; - m_nCurrOption = m_nPrevOption = 0; + m_nCurrOption = m_nOptionMouseHovering = 0; } else { m_nHoverOption = HOVEROPTION_RANDOM_ITEM; - m_nCurrOption = m_nPrevOption = 1; + m_nCurrOption = m_nOptionMouseHovering = 1; } return; } @@ -1256,7 +1256,7 @@ CMenuManager::Draw() static int oldOption = -99; static int oldScreen = m_nCurrScreen; - m_nPrevOption = rowToCheck; + m_nOptionMouseHovering = rowToCheck; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrOption = rowToCheck; m_bShowMouse = true; @@ -1980,10 +1980,10 @@ CMenuManager::DrawControllerSetupScreen() float curOptY = i * rowHeight + yStart; if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { - if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) + if (m_nOptionMouseHovering != i && m_nCurrExLayer == HOVEROPTION_LIST) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0); - m_nPrevOption = i; + m_nOptionMouseHovering = i; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = i; @@ -2694,7 +2694,7 @@ CMenuManager::DrawPlayerSetupScreen() if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) { if (m_nMousePosY > MENU_Y(rowStartY) && m_nMousePosY < MENU_Y(rowEndY)) { - m_nPrevOption = rowIdx; + m_nOptionMouseHovering = rowIdx; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrExLayer = HOVEROPTION_LIST; } @@ -4025,7 +4025,7 @@ CMenuManager::ProcessButtonPresses(void) if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESUME && #endif (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } } else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { @@ -4039,7 +4039,7 @@ CMenuManager::ProcessButtonPresses(void) OutputDebugString("FRONTEND RADIO STATION CHANGED"); } else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } #else @@ -4126,7 +4126,7 @@ CMenuManager::ProcessButtonPresses(void) break; case HOVEROPTION_RANDOM_ITEM: if (((m_nCurrOption != 0) || (m_nCurrScreen != MENUPAGE_PAUSE_MENU)) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } break; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 758e29aa..7b0e2f4b 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -518,7 +518,7 @@ public: int32 m_nHoverOption; int32 m_nCurrScreen; int32 m_nCurrOption; - int32 m_nPrevOption; + int32 m_nOptionMouseHovering; int32 m_nPrevScreen; uint32 field_558; int32 m_nCurrSaveSlot; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 92eb8b13..549efad6 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -383,7 +383,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) weapon.m_nTimer = 0; } - m_lastFightMove = FIGHTMOVE_NULL; + m_curFightMove = FIGHTMOVE_NULL; GiveWeapon(WEAPONTYPE_UNARMED, 0); m_wepAccuracy = 60; m_lastWepDam = -1; @@ -471,7 +471,7 @@ CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround) currentPedState = currentPed->m_nPedState; - if (currentPedState == PED_FALL || currentPedState == PED_GETUP || currentPedState == PED_DIE || currentPedState == PED_DEAD) { + if (currentPed->OnGroundOrGettingUp()) { if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) { if (currentPedState == PED_DEAD) { foundDead = 1; @@ -1821,7 +1821,7 @@ void CPed::PlayFootSteps(void) { if (bDoBloodyFootprints) { - if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) { + if (m_bloodyFootprintCountOrDeathTime != 0 && m_bloodyFootprintCountOrDeathTime < 300) { m_bloodyFootprintCountOrDeathTime--; if (m_bloodyFootprintCountOrDeathTime == 0) @@ -2716,7 +2716,7 @@ CPed::SetObjective(eObjective newObj) } */ - m_objective = newObj; + m_objective = OBJECTIVE_NONE; m_prevObjective = OBJECTIVE_NONE; } else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) { SetObjectiveTimer(0); @@ -3364,9 +3364,7 @@ CPed::CheckForPointBlankPeds(CPed *pedToVerify) if (neededTurn > PI) neededTurn = 2*PI - neededTurn; - PedState nearPedState = nearPed->m_nPedState; - - if (nearPedState == PED_FALL || nearPedState == PED_GETUP || nearPedState == PED_DIE || nearPedState == PED_DEAD || nearPedState == PED_DIVE_AWAY) + if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY) return NO_POINT_BLANK_PED; if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) { @@ -3652,56 +3650,7 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi case WEAPONTYPE_BASEBALLBAT: if (bMeleeProof) return false; -#ifdef VC_PED_PORTS - if (/*method != WEAPONTYPE_KATANA || */ - damagedBy != FindPlayerPed() - || FindPlayerPed()->m_nPedState != PED_FIGHT - /*|| FindPlayerPed()->m_lastFightMove != 28 && FindPlayerPed()->m_lastFightMove != 29 */ - || CGeneral::GetRandomNumber() & 3) { - if (m_nPedState == PED_FALL) { - if (IsPedHeadAbovePos(-0.3f)) { - dieAnim = NUM_ANIMS; - } else { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) - dieAnim = ANIM_FLOOR_HIT_F; - else - dieAnim = ANIM_FLOOR_HIT; - dieDelta = dieDelta * 2.0f; - dieSpeed = 0.5f; - } - } else if (damagedBy != FindPlayerPed()) { // || FindPlayerPed()->m_lastFightMove != 29) - //if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_lastFightMove != 30) { - switch (direction) { - case 0: - dieAnim = ANIM_KO_SKID_FRONT; - break; - case 1: - dieAnim = ANIM_KO_SPIN_R; - break; - case 2: - dieAnim = ANIM_KO_SKID_BACK; - break; - case 3: - dieAnim = ANIM_KO_SPIN_L; - break; - default: - break; - } - //} else { - // dieAnim = ANIM_KO_SHOT_STOM; - //} - } else { - dieAnim = ANIM_KO_SHOT_FACE; - } - } else { - dieAnim = ANIM_KO_SHOT_FACE; - // SpawnFlyingComponent in VC - RemoveBodyPart(PED_HEAD, direction); - headShot = true; - willLinger = true; - } -#else if (m_nPedState == PED_FALL) { if (IsPedHeadAbovePos(-0.3f)) { dieAnim = NUM_ANIMS; @@ -3731,7 +3680,6 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi break; } } -#endif break; case WEAPONTYPE_COLT45: case WEAPONTYPE_UZI: @@ -4853,11 +4801,11 @@ CPed::StartFightAttack(uint8 buttonPressure) CPed *pedOnGround = nil; if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) { - m_lastFightMove = FIGHTMOVE_GROUNDKICK; + m_curFightMove = FIGHTMOVE_GROUNDKICK; } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) { - m_lastFightMove = FIGHTMOVE_ROUNDHOUSE; + m_curFightMove = FIGHTMOVE_ROUNDHOUSE; } else { - m_lastFightMove = FIGHTMOVE_STDPUNCH; + m_curFightMove = FIGHTMOVE_STDPUNCH; } if (pedOnGround && IsPlayer()) { @@ -4871,7 +4819,7 @@ CPed::StartFightAttack(uint8 buttonPressure) SetLookFlag(pedOnGround, true); SetLookTimer(1500); } - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; m_takeAStepAfterAttack = false; @@ -4999,9 +4947,9 @@ CPed::FightStrike(CVector &touchedNodePos) for (int i = 0; i < m_numNearPeds; i++) { nearPed = m_nearPeds[i]; if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) - maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_lastFightMove].strikeRadius + 0.1f; + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f; else - maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_lastFightMove].strikeRadius; + maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius; if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) { CVector nearPedCentre; @@ -5017,9 +4965,7 @@ CPed::FightStrike(CVector &touchedNodePos) ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump()); else #endif - if (nearPed->m_nPedState == PED_FALL - || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE - || !nearPed->IsPedHeadAbovePos(-0.3f)) { + if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) { ourCol = &CTempColModels::ms_colModelPedGroundHit; } else { #ifdef ANIMATE_PED_COL_MODEL @@ -5034,7 +4980,7 @@ CPed::FightStrike(CVector &touchedNodePos) attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center; attackDistance -= touchedNodePos; CColSphere *ourPieces = ourCol->spheres; - float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius; + float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius; // We can beat him too if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) { @@ -5055,7 +5001,7 @@ CPed::FightStrike(CVector &touchedNodePos) float oldVictimHealth = nearPed->m_fHealth; CVector bloodPos = 0.5f * attackDistance + touchedNodePos; - int damageMult = tFightMoves[m_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; + int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1; CVector2D diff (GetPosition() - nearPed->GetPosition()); int direction = nearPed->GetLocalDirection(diff); @@ -5067,7 +5013,7 @@ CPed::FightStrike(CVector &touchedNodePos) } // Change direction if we used kick. - if (m_lastFightMove == FIGHTMOVE_KICK) { + if (m_curFightMove == FIGHTMOVE_KICK) { if (CGeneral::GetRandomNumber() & 1) { direction++; if (direction > 3) @@ -5083,16 +5029,16 @@ CPed::FightStrike(CVector &touchedNodePos) else unk2 = damageMult; - nearPed->StartFightDefend(direction, tFightMoves[m_lastFightMove].hitLevel, unk2); + nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2); PlayHitSound(nearPed); m_fightState = FIGHTSTATE_JUST_ATTACKED; - RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId)->speed = 0.6f; + RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f; if (!nearPed->DyingOrDead()) { nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction); } if (CGame::nastyGame - && tFightMoves[m_lastFightMove].hitLevel > HITLEVEL_MEDIUM + && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM && nearPed->m_nPedState == PED_DIE && nearPed->GetIsOnScreen()) { @@ -5102,7 +5048,7 @@ CPed::FightStrike(CVector &touchedNodePos) CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0); } } - if (nearPed->m_nPedState != PED_FALL && nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) { + if (!nearPed->OnGround()) { float curVictimHealth = nearPed->m_fHealth; if (curVictimHealth > 0.0f && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer() @@ -5122,7 +5068,7 @@ CPed::FightStrike(CVector &touchedNodePos) nearPed->bIsStanding = false; float moveMult; - if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) { + if (m_curFightMove == FIGHTMOVE_GROUNDKICK) { moveMult = Min(damageMult * 0.6f, 4.0f); } else { if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) { @@ -5434,21 +5380,21 @@ CPed::PlayHitSound(CPed *hitTo) }; // This is why first dimension is between FightMove 1 and 12. - if (m_lastFightMove == FIGHTMOVE_NULL || m_lastFightMove >= FIGHTMOVE_HITFRONT) + if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT) return; uint16 soundId; // And this is why second dimension is between 13 and 22. - if (hitTo->m_lastFightMove <= FIGHTMOVE_GROUNDKICK || hitTo->m_lastFightMove >= FIGHTMOVE_IDLE2NORM) { + if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; - if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; - } else { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; - } } else { - soundId = hitSoundsByFightMoves[m_lastFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_lastFightMove - FIGHTMOVE_HITFRONT]; + if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; + } else { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; + } } if (soundId != NO_SND) @@ -6124,7 +6070,7 @@ CPed::EndFight(uint8 endType) if (m_nPedState != PED_FIGHT) return; - m_lastFightMove = FIGHTMOVE_NULL; + m_curFightMove = FIGHTMOVE_NULL; RestorePreviousState(); CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE); if (animAssoc) @@ -6353,24 +6299,27 @@ CPed::Fall(void) void CPed::Fight(void) { - CAnimBlendAssociation *currentAssoc = nil, *animAssoc; + CAnimBlendAssociation *currentAssoc, *animAssoc; bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse; float angleToFace, nextAngle; bool goForward = false; int nextFightMove; - switch (m_lastFightMove) { + switch (m_curFightMove) { case FIGHTMOVE_NULL: return; case FIGHTMOVE_IDLE2NORM: - m_lastFightMove = FIGHTMOVE_NULL; + m_curFightMove = FIGHTMOVE_NULL; RestorePreviousState(); + + // FIX: Uninitialized + currentAssoc = nil; break; case FIGHTMOVE_IDLE: - // currentAssoc = nil; + currentAssoc = nil; break; default: - currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId); + currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); break; } @@ -6387,12 +6336,12 @@ CPed::Fight(void) } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) { float animTime = currentAssoc->currentTime; - FightMove &curMove = tFightMoves[m_lastFightMove]; + FightMove &curMove = tFightMoves[m_curFightMove]; if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) { CVector touchingNodePos(0.0f, 0.0f, 0.0f); - switch (m_lastFightMove) { + switch (m_curFightMove) { case FIGHTMOVE_STDPUNCH: case FIGHTMOVE_PUNCHHOOK: case FIGHTMOVE_BODYBLOW: @@ -6418,9 +6367,9 @@ CPed::Fight(void) break; } - if (m_lastFightMove == FIGHTMOVE_PUNCHJAB) { + if (m_curFightMove == FIGHTMOVE_PUNCHJAB) { touchingNodePos += 0.1f * GetForward(); - } else if (m_lastFightMove == FIGHTMOVE_PUNCHHOOK) { + } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) { touchingNodePos += 0.22f * GetForward(); } FightStrike(touchingNodePos); @@ -6440,7 +6389,7 @@ CPed::Fight(void) if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) { // Notice that it increases fight move index, because we're in combo! - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_lastFightMove].animId, 8.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength); m_fightButtonPressure = 0; @@ -6448,7 +6397,7 @@ CPed::Fight(void) } } } else { - if (curMove.startFireTime > 0.0f && m_lastFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) { + if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) { if (IsPlayer()) currentAssoc->speed = 1.3f; else @@ -6504,8 +6453,7 @@ CPed::Fight(void) if (neededTurn > PI) neededTurn = TWOPI - neededTurn; - PedState nearPedState = nearPed->m_nPedState; - if (nearPedState != PED_FALL && nearPedState != PED_GETUP && nearPedState != PED_DIE && nearPedState != PED_DEAD) { + if (!nearPed->OnGroundOrGettingUp()) { if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) { canAffectMultiplePeople = false; @@ -6546,7 +6494,7 @@ CPed::Fight(void) goForward = true; } - } else if (nearPedState != PED_DEAD || pedOnGround) { + } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) { if (!nearPed->IsPedHeadAbovePos(-0.3f)) { canAffectMultiplePeople = false; nextFightMove = FIGHTMOVE_GROUNDKICK; @@ -6600,8 +6548,7 @@ CPed::Fight(void) nextAngle = CGeneral::LimitRadianAngle(angleToFace); m_fRotationDest = nextAngle; m_fRotationCur = m_fRotationDest; - PedState fightingPedState = m_pedInObjective->m_nPedState; - if (fightingPedState != PED_FALL && fightingPedState != PED_GETUP && fightingPedState != PED_DIE && fightingPedState != PED_DEAD) { + if (!m_pedInObjective->OnGroundOrGettingUp()) { if (fightingPedDist >= 0.8f || !canKneeHead) { @@ -6650,8 +6597,8 @@ CPed::Fight(void) } if (nextFightMove != FIGHTMOVE_IDLE) { - m_lastFightMove = nextFightMove; - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); + m_curFightMove = nextFightMove; + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) { @@ -6661,21 +6608,21 @@ CPed::Fight(void) m_fightButtonPressure = 0; } m_fightState = FIGHTSTATE_NO_MOVE; - } else if (m_takeAStepAfterAttack && m_lastFightMove != FIGHTMOVE_SHUFFLE_F + } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F #ifndef FIX_BUGS && CheckForPedsOnGroundToAttack(this, nil) == 4) { #else && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) { #endif - m_lastFightMove = FIGHTMOVE_SHUFFLE_F; - animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId); + m_curFightMove = FIGHTMOVE_SHUFFLE_F; + animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId); if (animAssoc) { animAssoc->SetCurrentTime(0.0f); animAssoc->blendDelta = 4.0f; animAssoc->SetRun(); } else { - animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 32.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f); } animAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; @@ -6685,13 +6632,13 @@ CPed::Fight(void) } else if (m_takeAStepAfterAttack) { EndFight(ENDFIGHT_FAST); - } else if (m_lastFightMove == FIGHTMOVE_IDLE) { + } else if (m_curFightMove == FIGHTMOVE_IDLE) { if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) { EndFight(ENDFIGHT_NORMAL); } } else { - m_lastFightMove = FIGHTMOVE_IDLE; + m_curFightMove = FIGHTMOVE_IDLE; if (IsPlayer()) m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500; else @@ -6781,7 +6728,7 @@ CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg) { CPed *ped = (CPed*)arg; - if (tFightMoves[ped->m_lastFightMove].animId == animAssoc->animId) { + if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) { ped->m_fightState = FIGHTSTATE_MOVE_FINISHED; animAssoc->blendDelta = -1000.0f; } @@ -7527,9 +7474,9 @@ CPed::Flee(void) if (!m_collidingEntityWhileFleeing) return; - double damagingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; + double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; - if (damagingThingPriorityMult <= 1.5) { + if (collidingThingPriorityMult <= 1.5) { double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints( GetPosition().x, @@ -7538,35 +7485,34 @@ CPed::Flee(void) m_collidingEntityWhileFleeing->GetPosition().y); angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity); - // It includes projectiles, but is everything collides with us included? - double angleToFleeDamagingThing = CGeneral::GetRadianAngleBetweenPoints( + double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints( m_vecDamageNormal.x, m_vecDamageNormal.y, 0.0f, 0.0f); - angleToFleeDamagingThing = CGeneral::LimitRadianAngle(angleToFleeDamagingThing); + angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing); - if (angleToFleeEntity - PI > angleToFleeDamagingThing) - angleToFleeDamagingThing += TWOPI; - else if (PI + angleToFleeEntity < angleToFleeDamagingThing) - angleToFleeDamagingThing -= TWOPI; + if (angleToFleeEntity - PI > angleToFleeCollidingThing) + angleToFleeCollidingThing += TWOPI; + else if (PI + angleToFleeEntity < angleToFleeCollidingThing) + angleToFleeCollidingThing -= TWOPI; - if (damagingThingPriorityMult <= 1.0f) { + if (collidingThingPriorityMult <= 1.0f) { // Range [0.0, 1.0] - float angleToFleeBoth = (angleToFleeDamagingThing + angleToFleeEntity) * 0.5f; + float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f; if (m_fRotationDest - PI > angleToFleeBoth) angleToFleeBoth += TWOPI; else if (PI + m_fRotationDest < angleToFleeBoth) angleToFleeBoth -= TWOPI; - m_fRotationDest = (1.0f - damagingThingPriorityMult) * m_fRotationDest + damagingThingPriorityMult * angleToFleeBoth; + m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth; } else { // Range (1.0, 1.5] - double adjustedMult = (damagingThingPriorityMult - 1.0f) * 2.0f; - m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeDamagingThing; + double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f; + m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing; } } else { m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( @@ -8564,8 +8510,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) CPed::InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection); CPed::SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true); - if ((m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD) - && !m_pCollidingEntity && + if (OnGround() && !m_pCollidingEntity && (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) { m_pCollidingEntity = car; @@ -14992,7 +14937,7 @@ CPed::PreRender(void) CVector speed = FindPlayerSpeed(); if (Abs(speed.x) <= 0.05f && Abs(speed.y) <= 0.05f) { - if (m_nPedState != PED_FALL && !DyingOrDead() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + if (!OnGround() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { if (!IsPedHeadAbovePos(0.3f) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED)) { doSplashUp = false; } @@ -16201,7 +16146,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) Say(SOUND_PED_DEFEND); switch (hitLevel) { case HITLEVEL_GROUND: - m_lastFightMove = FIGHTMOVE_HITONFLOOR; + m_curFightMove = FIGHTMOVE_HITONFLOOR; break; case HITLEVEL_LOW: #ifndef VC_PED_PORTS @@ -16218,52 +16163,52 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) return; } #endif - m_lastFightMove = FIGHTMOVE_HITBODY; + m_curFightMove = FIGHTMOVE_HITBODY; break; case HITLEVEL_HIGH: switch (direction) { case 1: - m_lastFightMove = FIGHTMOVE_HITLEFT; + m_curFightMove = FIGHTMOVE_HITLEFT; break; case 2: - m_lastFightMove = FIGHTMOVE_HITBACK; + m_curFightMove = FIGHTMOVE_HITBACK; break; case 3: - m_lastFightMove = FIGHTMOVE_HITRIGHT; + m_curFightMove = FIGHTMOVE_HITRIGHT; break; default: if (unk <= 5) - m_lastFightMove = FIGHTMOVE_HITHEAD; + m_curFightMove = FIGHTMOVE_HITHEAD; else - m_lastFightMove = FIGHTMOVE_HITBIGSTEP; + m_curFightMove = FIGHTMOVE_HITBIGSTEP; break; } break; default: switch (direction) { case 1: - m_lastFightMove = FIGHTMOVE_HITLEFT; + m_curFightMove = FIGHTMOVE_HITLEFT; break; case 2: - m_lastFightMove = FIGHTMOVE_HITBACK; + m_curFightMove = FIGHTMOVE_HITBACK; break; case 3: - m_lastFightMove = FIGHTMOVE_HITRIGHT; + m_curFightMove = FIGHTMOVE_HITRIGHT; break; default: if (unk <= 5) - m_lastFightMove = FIGHTMOVE_HITCHEST; + m_curFightMove = FIGHTMOVE_HITCHEST; else - m_lastFightMove = FIGHTMOVE_HITBIGSTEP; + m_curFightMove = FIGHTMOVE_HITBIGSTEP; break; } break; } if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f)) - m_lastFightMove = FIGHTMOVE_HITONFLOOR; + m_curFightMove = FIGHTMOVE_HITONFLOOR; if (m_nPedState == PED_FIGHT) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); moveAssoc->SetCurrentTime(0.0f); moveAssoc->SetFinishCallback(FinishFightMoveCB, this); if (IsPlayer()) @@ -16272,7 +16217,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) m_takeAStepAfterAttack = 0; m_fightButtonPressure = 0; } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) { - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f); moveAssoc->SetCurrentTime(0.0f); moveAssoc->speed = 1.3f; } else { @@ -16302,7 +16247,7 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) SetMoveState(PEDMOVE_NONE); m_nStoredMoveState = PEDMOVE_NONE; CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f; - CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f); + CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f); moveAssoc->SetFinishCallback(FinishFightMoveCB, this); m_fightState = FIGHTSTATE_NO_MOVE; m_takeAStepAfterAttack = false; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index d600c409..63d8e598 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -480,7 +480,7 @@ public: uint8 m_wepAccuracy; CEntity *m_pPointGunAt; CVector m_vecHitLastPos; - uint32 m_lastFightMove; + uint32 m_curFightMove; uint8 m_fightButtonPressure; FightState m_fightState; bool m_takeAStepAfterAttack; @@ -802,6 +802,7 @@ public: bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool OnGroundOrGettingUp(void) { return OnGround() || m_nPedState == PED_GETUP; } bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 21aace7a..376c0a11 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -64,10 +64,6 @@ static psGlobalType PsGlobal; #undef MAKEPOINTS #define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l))) -#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } -#define JIF(x) if (FAILED(hr=(x))) \ - {debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;} - unsigned long _dwMemAvailPhys; RwUInt32 gGameState; From 5bedca7692490914ad2545767a6f1aa1fd46f386 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Jul 2020 23:25:04 +0200 Subject: [PATCH 61/85] fixed COcclusion --- src/core/FileLoader.cpp | 2 +- src/core/re3.cpp | 2 + src/entities/Entity.cpp | 3 +- src/render/Occlusion.cpp | 116 ++++++++++++++++++++++----------------- src/render/Occlusion.h | 7 ++- 5 files changed, 74 insertions(+), 56 deletions(-) diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index a29d26fa..86ebb5dd 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1279,7 +1279,7 @@ CFileLoader::LoadOcclusionVolume(const char *line) &x, &y, &z, &width, &length, &height, &angle); - COcclusion::AddOne(x, y, z, width, length, z + height/2.0f, angle); + COcclusion::AddOne(x, y, z + height/2.0f, width, length, height, angle); } diff --git a/src/core/re3.cpp b/src/core/re3.cpp index b11fb5c7..f7a895c3 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -4,6 +4,7 @@ #include "crossplatform.h" #include "patcher.h" #include "Renderer.h" +#include "Occlusion.h" #include "Credits.h" #include "Camera.h" #include "Weather.h" @@ -495,6 +496,7 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Render", "Frame limiter", &FrontEndMenuManager.m_PrefsFrameLimiter, nil); DebugMenuAddVarBool8("Render", "VSynch", &FrontEndMenuManager.m_PrefsVsync, nil); DebugMenuAddVar("Render", "Max FPS", &RsGlobal.maxFPS, nil, 1, 1, 1000, nil); + DebugMenuAddVarBool8("Render", "Occlusion debug", &bDisplayOccDebugStuff, nil); DebugMenuAddVarBool8("Render", "Show Ped Paths", &gbShowPedPaths, nil); DebugMenuAddVarBool8("Render", "Show Car Paths", &gbShowCarPaths, nil); DebugMenuAddVarBool8("Render", "Show Car Path Links", &gbShowCarPathsLinks, nil); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index f85dda21..63ea03fc 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -1160,12 +1160,11 @@ bool IsEntityPointerValid(CEntity* pEntity) } bool CEntity::IsEntityOccluded(void) { - return false; CVector coors; float width, height; - if (!COcclusion::NumActiveOccluders || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height)) + if (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height)) return false; float area = Max(width, height) * GetBoundRadius() * 0.9f; diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp index b31cc11e..c2f220e9 100644 --- a/src/render/Occlusion.cpp +++ b/src/render/Occlusion.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "main.h" #include "Occlusion.h" #include "Game.h" #include "Camera.h" @@ -28,7 +29,7 @@ bool gOccluderCoorsValid[8]; CVector gOccluderCoorsOnScreen[8]; CVector gOccluderCoors[8]; -bool bDisplayOccDebugStuff = false; +bool bDisplayOccDebugStuff; void COcclusion::Init(void) @@ -55,7 +56,7 @@ COcclusion::AddOne(float x, float y, float z, float width, float length, float h aOccluders[NumOccludersOnMap].height = height; while(angle < 0.0f) angle += 360.0f; while(angle > 360.0f) angle -= 360.0f; - aOccluders[NumOccludersOnMap].angle = angle * UINT16_MAX/360.0f; + aOccluders[NumOccludersOnMap].angle = angle/360.0f * UINT16_MAX; aOccluders[NumOccludersOnMap].listIndex = FarAwayList; FarAwayList = NumOccludersOnMap++; } @@ -68,19 +69,19 @@ COccluder::NearCamera() { bool DoesInfiniteLineCrossFiniteLine(float p1X, float p1Y, float p2X, float p2Y, float lineX, float lineY, float lineDX, float lineDY) { - float side1 = (p1X - lineX) * lineDX - (p1Y - lineY) * lineDY; - float side2 = (p2X - lineX) * lineDX - (p2Y - lineY) * lineDY; + float side1 = (p1X - lineX) * lineDY - (p1Y - lineY) * lineDX; + float side2 = (p2X - lineX) * lineDY - (p2Y - lineY) * lineDX; return side1 * side2 < 0.0f; // if points lie on opposite sides of the infinte line, the line between them crosses it } -bool DoesInfiniteLineTouchScreen(float p1X, float p1Y, float p2X, float p2Y) { - if (p1X > 0.0f && p1Y > 0.0f && SCREEN_WIDTH > p1X && SCREEN_HEIGHT > p1Y) +bool DoesInfiniteLineTouchScreen(float lineX, float lineY, float lineDX, float lineDY) { + if (lineX > 0.0f && lineY > 0.0f && SCREEN_WIDTH > lineX && SCREEN_HEIGHT > lineY) return true; - return (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, p1X, p1Y, p2X, p2Y) || - DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y) || - DoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y) || - DoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, p1X, p1Y, p2X, p2Y)); + return (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) || + DoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY)); } bool IsPointInsideLine(float lineX, float lineY, float lineDX, float lineDY, float pX, float pY, float area = 0.0f) { @@ -123,18 +124,18 @@ COccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) { float x1, y1, x2, y2; - CVector origin3d, direction3d; + CVector p1, p2; if (!gOccluderCoorsValid[corner1]) { float clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f); float clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f); float ratio = clipDist2 / (clipDist1 + clipDist2); CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; - if (!CalcScreenCoors(clippedCoors, &origin3d, &x1, &y1)) + if (!CalcScreenCoors(clippedCoors, &p1, &x1, &y1)) return true; } else { - origin3d = gOccluderCoorsOnScreen[corner1]; + p1 = gOccluderCoorsOnScreen[corner1]; } if (!gOccluderCoorsValid[corner2]) { @@ -143,21 +144,22 @@ COccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) { float ratio = clipDist1 / (clipDist1 + clipDist2); CVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1]; - if (!CalcScreenCoors(clippedCoors, &direction3d, &x2, &y2)) + if (!CalcScreenCoors(clippedCoors, &p2, &x2, &y2)) return true; } else { - direction3d = gOccluderCoorsOnScreen[corner2]; + p2 = gOccluderCoorsOnScreen[corner2]; } - gMinXInOccluder = Min(Min(gMinXInOccluder, origin3d.x), direction3d.x); - gMaxXInOccluder = Max(Max(gMaxXInOccluder, origin3d.x), direction3d.x); - gMinYInOccluder = Min(Min(gMinYInOccluder, origin3d.y), direction3d.y); - gMaxYInOccluder = Max(Max(gMaxYInOccluder, origin3d.y), direction3d.y); + gMinXInOccluder = Min(Min(gMinXInOccluder, p1.x), p2.x); + gMaxXInOccluder = Max(Max(gMaxXInOccluder, p1.x), p2.x); + gMinYInOccluder = Min(Min(gMinYInOccluder, p1.y), p2.y); + gMaxYInOccluder = Max(Max(gMaxYInOccluder, p1.y), p2.y); - CVector2D origin = (CVector2D)origin3d; - CVector2D direction = (CVector2D)direction3d - origin; + CVector2D origin = p1; + CVector2D direction = p2 - p1; + // Make sure lines are counter-clockwise around center if (!IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, gCenterOnScreen.x, gCenterOnScreen.y, 0.0f)) { origin += direction; direction *= -1.0f; @@ -192,22 +194,23 @@ COccluder::ProcessOneOccluder(CActiveOccluder *occl) { CVector vec[3]; - vec[0].x = width / 2.0f * Sin(angle / 63556.0f*TWOPI); - vec[0].y = -width / 2.0f * Cos(angle / 63556.0f*TWOPI); + vec[0].x = length / 2.0f * Sin(GetAngle()); + vec[0].y = -length / 2.0f * Cos(GetAngle()); vec[0].z = 0.0f; - vec[1].x = length / 2.0f * Cos(angle / 63556.0f*TWOPI); - vec[1].y = length / 2.0f * Sin(angle / 63556.0f*TWOPI); + vec[1].x = width / 2.0f * Cos(GetAngle()); + vec[1].y = width / 2.0f * Sin(GetAngle()); vec[1].z = 0.0f; vec[2].x = 0.0f; vec[2].y = 0.0f; vec[2].z = height / 2.0f; - bool aChecks[6]; int counter = -1; + // Figure out if we see the front or back of a face + bool bFrontFace[6]; for (int i = 0; i < 3; i++) { - aChecks[++counter] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f; - aChecks[++counter] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f; + bFrontFace[i*2+0] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f; + bFrontFace[i*2+1] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f; } //calculating vertices of a box @@ -228,31 +231,32 @@ COccluder::ProcessOneOccluder(CActiveOccluder *occl) { gMaxYInOccluder = -999999.875f; gMaxXInOccluder = -999999.875f; - if (aChecks[2] != aChecks[0] && ProcessLineSegment(0, 4, occl)) + // Between two differently facing sides we see an edge, so process those + if (bFrontFace[2] != bFrontFace[0] && ProcessLineSegment(0, 4, occl)) return false; - if (aChecks[3] != aChecks[0] && ProcessLineSegment(2, 6, occl)) + if (bFrontFace[3] != bFrontFace[0] && ProcessLineSegment(2, 6, occl)) return false; - if (aChecks[4] != aChecks[0] && ProcessLineSegment(0, 2, occl)) + if (bFrontFace[4] != bFrontFace[0] && ProcessLineSegment(0, 2, occl)) return false; - if (aChecks[5] != aChecks[0] && ProcessLineSegment(4, 6, occl)) + if (bFrontFace[5] != bFrontFace[0] && ProcessLineSegment(4, 6, occl)) return false; - if (aChecks[2] != aChecks[1] && ProcessLineSegment(1, 5, occl)) + if (bFrontFace[2] != bFrontFace[1] && ProcessLineSegment(1, 5, occl)) return false; - if (aChecks[3] != aChecks[1] && ProcessLineSegment(3, 7, occl)) + if (bFrontFace[3] != bFrontFace[1] && ProcessLineSegment(3, 7, occl)) return false; - if (aChecks[4] != aChecks[1] && ProcessLineSegment(1, 3, occl)) + if (bFrontFace[4] != bFrontFace[1] && ProcessLineSegment(1, 3, occl)) return false; - if (aChecks[5] != aChecks[1] && ProcessLineSegment(5, 7, occl)) + if (bFrontFace[5] != bFrontFace[1] && ProcessLineSegment(5, 7, occl)) return false; - if (aChecks[4] != aChecks[2] && ProcessLineSegment(0, 1, occl)) + if (bFrontFace[4] != bFrontFace[2] && ProcessLineSegment(0, 1, occl)) return false; - if (aChecks[3] != aChecks[4] && ProcessLineSegment(2, 3, occl)) + if (bFrontFace[3] != bFrontFace[4] && ProcessLineSegment(2, 3, occl)) return false; - if (aChecks[5] != aChecks[3] && ProcessLineSegment(6, 7, occl)) + if (bFrontFace[5] != bFrontFace[3] && ProcessLineSegment(6, 7, occl)) return false; - if (aChecks[2] != aChecks[5] && ProcessLineSegment(4, 5, occl)) + if (bFrontFace[2] != bFrontFace[5] && ProcessLineSegment(4, 5, occl)) return false; - + if (gMaxXInOccluder - gMinXInOccluder < SCREEN_WIDTH * 0.1f || gMaxYInOccluder - gMinYInOccluder < SCREEN_HEIGHT * 0.07f) return false; @@ -346,18 +350,18 @@ COcclusion::ProcessBeforeRendering(void) } } - //printf("NumActiveOccluders = %d\n", NumActiveOccluders); - for (i = 0; i < NumActiveOccluders; i++) { for (int j = 0; j < NumActiveOccluders; j++) { - if (i != j || aActiveOccluders[j].radius < aActiveOccluders[i].radius) { + if (i != j && aActiveOccluders[j].radius < aActiveOccluders[i].radius) { if (OccluderHidesBehind(&aActiveOccluders[i], &aActiveOccluders[j])) { for (int k = i; k < NumActiveOccluders - 1; k++) { - for (int l = 0; l < aActiveOccluders[k].linesCount; l++) + for (int l = 0; l < aActiveOccluders[k + 1].linesCount; l++) aActiveOccluders[k].lines[l] = aActiveOccluders[k + 1].lines[l]; aActiveOccluders[k].linesCount = aActiveOccluders[k + 1].linesCount; aActiveOccluders[k].radius = aActiveOccluders[k + 1].radius; } + NumActiveOccluders--; + i--; } } } @@ -374,7 +378,6 @@ bool CActiveOccluder::IsPointWithinOcclusionArea(float pX, float pY, float area) } bool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float height) { - return false; CVector coors; float outW, outH; @@ -415,7 +418,6 @@ bool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float h } bool COcclusion::IsPositionOccluded(CVector pos, float side) { - return false; CVector coors; float width, height; @@ -434,6 +436,10 @@ bool COcclusion::IsPositionOccluded(CVector pos, float side) { return false; } +#include "Lines.h" + +RwIm2DVertex vertexbufferT[2]; + void COcclusion::Render() { if (!bDisplayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200)) return; @@ -445,15 +451,23 @@ void COcclusion::Render() { RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, FALSE); + float recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera); for (int i = 0; i < NumActiveOccluders; i++) { for (int j = 0; j < aActiveOccluders[i].linesCount; j++) { - RwIm2DVertex vertexbufferT[2]; RwIm2DVertexSetScreenX(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.x); RwIm2DVertexSetScreenY(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.y); - RwIm2DVertexSetScreenX(&vertexbufferT[1], + RwIm2DVertexSetScreenZ(&vertexbufferT[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&vertexbufferT[0], RwCameraGetNearClipPlane(Scene.camera)); + RwIm2DVertexSetRecipCameraZ(&vertexbufferT[0], recipz); + + RwIm2DVertexSetScreenX(&vertexbufferT[1], aActiveOccluders[i].lines[j].origin.x + aActiveOccluders[i].lines[j].direction.x * aActiveOccluders[i].lines[j].length); - RwIm2DVertexSetScreenY(&vertexbufferT[1], + RwIm2DVertexSetScreenY(&vertexbufferT[1], aActiveOccluders[i].lines[j].origin.y + aActiveOccluders[i].lines[j].direction.y * aActiveOccluders[i].lines[j].length); + RwIm2DVertexSetScreenZ(&vertexbufferT[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&vertexbufferT[1], RwCameraGetNearClipPlane(Scene.camera)); + RwIm2DVertexSetRecipCameraZ(&vertexbufferT[1], recipz); + RwIm2DVertexSetIntRGBA(&vertexbufferT[0], 255, 255, 0, 255); RwIm2DVertexSetIntRGBA(&vertexbufferT[1], 255, 255, 0, 255); RwIm2DRenderLine(vertexbufferT, 2, 0, 1); @@ -461,4 +475,4 @@ void COcclusion::Render() { } DefinedState(); -} \ No newline at end of file +} diff --git a/src/render/Occlusion.h b/src/render/Occlusion.h index 9b7ba34f..9a415f88 100644 --- a/src/render/Occlusion.h +++ b/src/render/Occlusion.h @@ -19,7 +19,7 @@ public: class COccluder { public: - int16 width, length, height; + int16 length, width, height; int16 x, y, z; uint16 angle; int16 listIndex; @@ -27,6 +27,7 @@ public: bool NearCamera(); bool ProcessOneOccluder(CActiveOccluder *occl); bool ProcessLineSegment(int corner1, int corner2, CActiveOccluder* occl); + float GetAngle(void) { return angle*TWOPI/UINT16_MAX; } }; class COcclusion @@ -52,4 +53,6 @@ public: }; bool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh); -bool CalcScreenCoors(CVector const &in, CVector *out); \ No newline at end of file +bool CalcScreenCoors(CVector const &in, CVector *out); + +extern bool bDisplayOccDebugStuff; From 6dbc0c7ddac9e4cce9e4565f5d24e36c3c76cc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 21 Jul 2020 06:41:41 +0300 Subject: [PATCH 62/85] a cute mistake --- src/peds/Ped.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 549efad6..bbb8b2ae 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1946,7 +1946,7 @@ CPed::PlayFootSteps(void) CVector particlePos = GetPosition() + GetForward() * 0.3f; particlePos.z -= 1.2f; - CVector particleDir = m_vecMoveSpeed * 0.75f; + CVector particleDir = m_vecMoveSpeed * -0.75f; particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f); CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0); From 0fba76a5652b3d9c4a3ecb809a601208fceed11d Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Jul 2020 09:58:53 +0200 Subject: [PATCH 63/85] made NPC heli rotors rotate --- src/core/config.h | 2 +- src/vehicles/Plane.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/vehicles/Plane.h | 9 +++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/core/config.h b/src/core/config.h index 14489491..ef2c9b17 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -273,7 +273,7 @@ enum Config { // Vehicles #define EXPLODING_AIRTRAIN // can blow up jumbo jet with rocket launcher -//#define REMOVE_TREADABLE_PATHFIND +#define CPLANE_ROTORS // make the rotors of the NPC police heli rotate // Pickups //#define MONEY_MESSAGES diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index a3754854..ffe9ffbf 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -16,6 +16,7 @@ #include "Fluff.h" #include "World.h" #include "HandlingMgr.h" +#include "Heli.h" #include "Plane.h" //--MIAMI: file done @@ -88,6 +89,9 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) m_level = LEVEL_GENERIC; m_isFarAway = false; +#ifdef CPLANE_ROTORS + m_fRotorRotation = 0.0f; +#endif } CPlane::~CPlane() @@ -99,6 +103,21 @@ void CPlane::SetModelIndex(uint32 id) { CVehicle::SetModelIndex(id); +#ifdef CPLANE_ROTORS + int i; + for(i = 0; i < NUM_PLANE_NODES; i++) + m_aPlaneNodes[i] = nil; + if(GetModelIndex() == MI_CHOPPER){ + // This is surprisingly annoying... + RwFrame *heliNodes[NUM_HELI_NODES]; + for(i = 0; i < NUM_HELI_NODES; i++) + heliNodes[i] = nil; + CClumpModelInfo::FillFrameArray(GetClump(), heliNodes); + m_aPlaneNodes[PLANE_TOPROTOR] = heliNodes[HELI_TOPROTOR]; + m_aPlaneNodes[PLANE_BACKROTOR] = heliNodes[HELI_BACKROTOR]; + }else + CClumpModelInfo::FillFrameArray(GetClump(), m_aPlaneNodes); +#endif } void @@ -629,6 +648,29 @@ CPlane::PreRender(void) CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); } + +#ifdef CPLANE_ROTORS + CMatrix mat; + CVector pos; + m_fRotorRotation += 3.14f/6.5f; + if(m_fRotorRotation > 6.28f) + m_fRotorRotation -= 6.28f; + + if(m_aPlaneNodes[PLANE_TOPROTOR]){ + mat.Attach(RwFrameGetMatrix(m_aPlaneNodes[PLANE_TOPROTOR])); + pos = mat.GetPosition(); + mat.SetRotateZ(m_fRotorRotation); + mat.Translate(pos); + mat.UpdateRW(); + } + if(m_aPlaneNodes[PLANE_BACKROTOR]){ + mat.Attach(RwFrameGetMatrix(m_aPlaneNodes[PLANE_BACKROTOR])); + pos = mat.GetPosition(); + mat.SetRotateX(m_fRotorRotation); + mat.Translate(pos); + mat.UpdateRW(); + } +#endif } void diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index 5fb05468..c8f02048 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -4,6 +4,11 @@ enum ePlaneNodes { +#ifdef CPLANE_ROTORS + // for heli + PLANE_TOPROTOR, + PLANE_BACKROTOR, +#endif PLANE_WHEEL_FRONT = 2, PLANE_WHEEL_READ, NUM_PLANE_NODES @@ -29,6 +34,10 @@ struct CPlaneInterpolationLine class CPlane : public CVehicle { public: +#ifdef CPLANE_ROTORS + RwFrame *m_aPlaneNodes[NUM_PLANE_NODES]; + float m_fRotorRotation; +#endif int16 m_nPlaneId; int16 m_isFarAway; int16 m_nCurPathNode; From d4d6290403ffbbd0bf7321866cb532da23ef2847 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Jul 2020 11:11:58 +0200 Subject: [PATCH 64/85] fixed to renderer --- src/render/Renderer.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 9ebbc1bb..d02ecec5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -311,7 +311,11 @@ enum Visbility VIS_STREAMME }; +#ifdef FIX_BUGS +#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier) +#else #define LOD_DISTANCE 300.0f +#endif #define FADE_DISTANCE 20.0f #define STREAM_DISTANCE 30.0f @@ -674,14 +678,7 @@ CRenderer::ScanWorld(void) poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y); ScanSectorPoly(poly, 3, ScanSectorList_Subway); }else{ - if(f <= LOD_DISTANCE){ - poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); - poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); - poly[1].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPLEFT].x); - poly[1].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPLEFT].y); - poly[2].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPRIGHT].x); - poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y); - }else{ + if(f > LOD_DISTANCE){ // priority poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); @@ -698,8 +695,16 @@ CRenderer::ScanWorld(void) poly[1].y = CWorld::GetSectorY(vectors[CORNER_LOD_LEFT].y); poly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x); poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y); + ScanSectorPoly(poly, 3, ScanSectorList); + }else{ + poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); + poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); + poly[1].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPLEFT].x); + poly[1].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPLEFT].y); + poly[2].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPRIGHT].x); + poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y); + ScanSectorPoly(poly, 3, ScanSectorList); } - ScanSectorPoly(poly, 3, ScanSectorList); #ifdef NO_ISLAND_LOADING ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL)); ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_COMMERCIAL)); From 34b162d2c91601689a00131201e62e1f14b84e8e Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Jul 2020 11:12:15 +0200 Subject: [PATCH 65/85] fixed to renderer --- src/render/Renderer.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 329a8c9a..e608a609 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -317,7 +317,11 @@ enum Visbility VIS_STREAMME }; +#ifdef FIX_BUGS +#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier) +#else #define LOD_DISTANCE 300.0f +#endif #define FADE_DISTANCE 20.0f #define STREAM_DISTANCE 30.0f @@ -419,6 +423,8 @@ CRenderer::SetupEntityVisibility(CEntity *ent) // whose draw dist is > LOD_DISTANCE-FADE_DISTANCE, i.e. 280 // because decreasing dist here makes the object visible above LOD_DISTANCE // before fading normally once below LOD_DISTANCE. + // aha! this must be a workaround for the fact that we're not taking + // the LOD multiplier into account here anywhere if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE) dist += mi->GetLargestLodDistance() - LOD_DISTANCE; #endif @@ -751,14 +757,7 @@ CRenderer::ScanWorld(void) }else #endif { - if(f <= LOD_DISTANCE){ - poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); - poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); - poly[1].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPLEFT].x); - poly[1].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPLEFT].y); - poly[2].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPRIGHT].x); - poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y); - }else{ + if(f > LOD_DISTANCE){ // priority poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); @@ -775,8 +774,16 @@ CRenderer::ScanWorld(void) poly[1].y = CWorld::GetSectorY(vectors[CORNER_LOD_LEFT].y); poly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x); poly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y); + ScanSectorPoly(poly, 3, ScanSectorList); + }else{ + poly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x); + poly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y); + poly[1].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPLEFT].x); + poly[1].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPLEFT].y); + poly[2].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPRIGHT].x); + poly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y); + ScanSectorPoly(poly, 3, ScanSectorList); } - ScanSectorPoly(poly, 3, ScanSectorList); ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel)); ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC)); From eb90e94f55f269637e0e931ffa4a527a8afe2536 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Jul 2020 13:06:59 +0200 Subject: [PATCH 66/85] update librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 556f6af1..853fa449 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 556f6af1b5a15d5ba1a2254a95076578cd160185 +Subproject commit 853fa44982dcb02d8e6bbe40045ee5c594c78e52 From bde159291c0f511fac313973394d4159218811b4 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Jul 2020 13:07:21 +0200 Subject: [PATCH 67/85] update librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 556f6af1..853fa449 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 556f6af1b5a15d5ba1a2254a95076578cd160185 +Subproject commit 853fa44982dcb02d8e6bbe40045ee5c594c78e52 From 4cf6024cdbd0d6ad3f12ae187dc7b2c51cae0913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 21 Jul 2020 20:22:52 +0300 Subject: [PATCH 68/85] cosmetic changes --- src/peds/Ped.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index bbb8b2ae..e134ac5d 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1821,7 +1821,7 @@ void CPed::PlayFootSteps(void) { if (bDoBloodyFootprints) { - if (m_bloodyFootprintCountOrDeathTime != 0 && m_bloodyFootprintCountOrDeathTime < 300) { + if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) { m_bloodyFootprintCountOrDeathTime--; if (m_bloodyFootprintCountOrDeathTime == 0) @@ -9823,7 +9823,7 @@ CPed::ProcessControl(void) || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL) #endif ) { - if (m_nPedStateTimer <= 1000 && m_nPedStateTimer) { + if (m_nPedStateTimer > 0 && m_nPedStateTimer <= 1000) { forceDir = GetPosition() - m_vecHitLastPos; } else { m_nPedStateTimer = 0; @@ -13712,7 +13712,7 @@ CPed::ProcessObjective(void) #endif } if (bObjectiveCompleted - || m_objectiveTimer != 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { + || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { RestorePreviousObjective(); if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer) m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1; From 7d51995640c6ad822c983249acf7aa765aa055b8 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Wed, 22 Jul 2020 03:23:12 +0300 Subject: [PATCH 69/85] Remove hacky way of injecting PS2 matfx on RW 3.3, remove static patcher --- src/audio/AudioLogic.cpp | 2 +- src/core/Game.cpp | 6 ++ src/core/patcher.cpp | 94 ------------------------- src/core/patcher.h | 144 --------------------------------------- src/core/re3.cpp | 1 - src/rw/RwMatFX.cpp | 113 ++++++++++++++++++++++++++---- src/skel/glfw/glfw.cpp | 2 - src/skel/win/win.cpp | 2 - 8 files changed, 105 insertions(+), 259 deletions(-) delete mode 100644 src/core/patcher.cpp delete mode 100644 src/core/patcher.h diff --git a/src/audio/AudioLogic.cpp b/src/audio/AudioLogic.cpp index 8fd2c2c9..7c7e96d2 100644 --- a/src/audio/AudioLogic.cpp +++ b/src/audio/AudioLogic.cpp @@ -2538,7 +2538,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) return true; velocityChange = Min(0.75f, velocityChange); - multiplier = (velocityChange - 0.0005f) * 1.3342229f; + multiplier = (velocityChange - 0.0005f) / (1499.0f / 2000.0f); CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); vol = (30.f * multiplier); m_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index fe073d29..f6275133 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -149,6 +149,10 @@ CGame::InitialiseOnceBeforeRW(void) return true; } +#if !defined(LIBRW) && defined(PS2_MATFX) +void ReplaceMatFxCallback(); +#endif + bool CGame::InitialiseRenderWare(void) { @@ -199,6 +203,8 @@ CGame::InitialiseRenderWare(void) #else rw::MatFX::modulateEnvMap = false; #endif +#elif defined(PS2_MATFX) + ReplaceMatFxCallback(); #endif CFont::Initialise(); diff --git a/src/core/patcher.cpp b/src/core/patcher.cpp deleted file mode 100644 index 83e06886..00000000 --- a/src/core/patcher.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#define WITHWINDOWS -#include "common.h" -#include "patcher.h" - -#include -#include - -StaticPatcher *StaticPatcher::ms_head; - -StaticPatcher::StaticPatcher(Patcher func) - : m_func(func) -{ - m_next = ms_head; - ms_head = this; -} - -void -StaticPatcher::Apply() -{ - StaticPatcher *current = ms_head; - while(current){ - current->Run(); - current = current->m_next; - } - ms_head = nil; -} -#ifdef _WIN32 -std::vector usedAddresses; - -static DWORD protect[2]; -static uint32 protect_address; -static uint32 protect_size; - -void -Protect_internal(uint32 address, uint32 size) -{ - protect_address = address; - protect_size = size; - VirtualProtect((void*)address, size, PAGE_EXECUTE_READWRITE, &protect[0]); -} - -void -Unprotect_internal(void) -{ - VirtualProtect((void*)protect_address, protect_size, protect[0], &protect[1]); -} - -void -InjectHook_internal(uint32 address, uint32 hook, int type) -{ - if(std::any_of(usedAddresses.begin(), usedAddresses.end(), - [address](uint32 value) { return value == address; })) { - debug("Used address %#06x twice when injecting hook\n", address); - } - - usedAddresses.push_back(address); - - - switch(type){ - case PATCH_JUMP: - VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &protect[0]); - *(uint8*)address = 0xE9; - break; - case PATCH_CALL: - VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &protect[0]); - *(uint8*)address = 0xE8; - break; - default: - VirtualProtect((void*)(address + 1), 4, PAGE_EXECUTE_READWRITE, &protect[0]); - break; - } - - *(ptrdiff_t*)(address + 1) = hook - address - 5; - if(type == PATCH_NOTHING) - VirtualProtect((void*)(address + 1), 4, protect[0], &protect[1]); - else - VirtualProtect((void*)address, 5, protect[0], &protect[1]); -} -#else -void -Protect_internal(uint32 address, uint32 size) -{ -} - -void -Unprotect_internal(void) -{ -} - -void -InjectHook_internal(uint32 address, uint32 hook, int type) -{ -} -#endif diff --git a/src/core/patcher.h b/src/core/patcher.h deleted file mode 100644 index 2722b6fd..00000000 --- a/src/core/patcher.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once - -#define WRAPPER __declspec(naked) -#define DEPRECATED __declspec(deprecated) -#define EAXJMP(a) { _asm mov eax, a _asm jmp eax } -#define VARJMP(a) { _asm jmp a } -#define WRAPARG(a) UNREFERENCED_PARAMETER(a) - -#include //memset - -enum -{ - PATCH_CALL, - PATCH_JUMP, - PATCH_NOTHING, -}; - -enum -{ - III_10 = 1, - III_11, - III_STEAM, - VC_10, - VC_11, - VC_STEAM -}; - -extern int gtaversion; - -class StaticPatcher -{ -private: - using Patcher = void(*)(); - - Patcher m_func; - StaticPatcher *m_next; - static StaticPatcher *ms_head; - - void Run() { m_func(); } -public: - StaticPatcher(Patcher func); - static void Apply(); -}; - -template -inline T AddressByVersion(uint32_t addressIII10, uint32_t addressIII11, uint32_t addressIIISteam, uint32_t addressvc10, uint32_t addressvc11, uint32_t addressvcSteam) -{ - if(gtaversion == -1){ - if(*(uint32_t*)0x5C1E75 == 0xB85548EC) gtaversion = III_10; - else if(*(uint32_t*)0x5C2135 == 0xB85548EC) gtaversion = III_11; - else if(*(uint32_t*)0x5C6FD5 == 0xB85548EC) gtaversion = III_STEAM; - else if(*(uint32_t*)0x667BF5 == 0xB85548EC) gtaversion = VC_10; - else if(*(uint32_t*)0x667C45 == 0xB85548EC) gtaversion = VC_11; - else if(*(uint32_t*)0x666BA5 == 0xB85548EC) gtaversion = VC_STEAM; - else gtaversion = 0; - } - switch(gtaversion){ - case III_10: - return (T)addressIII10; - case III_11: - return (T)addressIII11; - case III_STEAM: - return (T)addressIIISteam; - case VC_10: - return (T)addressvc10; - case VC_11: - return (T)addressvc11; - case VC_STEAM: - return (T)addressvcSteam; - default: - return (T)0; - } -} - -inline bool -is10(void) -{ - return gtaversion == III_10 || gtaversion == VC_10; -} - -inline bool -isIII(void) -{ - return gtaversion >= III_10 && gtaversion <= III_STEAM; -} - -inline bool -isVC(void) -{ - return gtaversion >= VC_10 && gtaversion <= VC_STEAM; -} - -#define PTRFROMCALL(addr) (uint32_t)(*(uint32_t*)((uint32_t)addr+1) + (uint32_t)addr + 5) -#define INTERCEPT(saved, func, a) \ -{ \ - saved = PTRFROMCALL(a); \ - InjectHook(a, func); \ -} - -void InjectHook_internal(uint32 address, uint32 hook, int type); -void Protect_internal(uint32 address, uint32 size); -void Unprotect_internal(void); - -template inline void -Patch(AT address, T value) -{ - Protect_internal((uint32)address, sizeof(T)); - *(T*)address = value; - Unprotect_internal(); -} - -template inline void -Nop(AT address, unsigned int nCount) -{ - Protect_internal((uint32)address, nCount); - memset((void*)address, 0x90, nCount); - Unprotect_internal(); -} - -template inline void -InjectHook(uintptr_t address, T hook, unsigned int nType = PATCH_NOTHING) -{ - InjectHook_internal(address, reinterpret_cast((void *&)hook), nType); -} - -inline void ExtractCall(void *dst, uint32_t a) -{ - *(uint32_t*)dst = (uint32_t)(*(uint32_t*)(a+1) + a + 5); -} -template -inline void InterceptCall(void *dst, T func, uint32_t a) -{ - ExtractCall(dst, a); - InjectHook(a, func); -} -template -inline void InterceptVmethod(void *dst, T func, uint32_t a) -{ - *(uint32_t*)dst = *(uint32_t*)a; - Patch(a, func); -} - -#define STARTPATCHES static StaticPatcher Patcher([](){ -#define ENDPATCHES }); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index d6319f3a..8c0020d0 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -2,7 +2,6 @@ #define WITHWINDOWS #include "common.h" #include "crossplatform.h" -#include "patcher.h" #include "Renderer.h" #include "Credits.h" #include "Camera.h" diff --git a/src/rw/RwMatFX.cpp b/src/rw/RwMatFX.cpp index 1e64c560..3533eb24 100644 --- a/src/rw/RwMatFX.cpp +++ b/src/rw/RwMatFX.cpp @@ -2,9 +2,8 @@ #define WITHD3D #include "common.h" -#ifdef RWLIBS -#include "patcher.h" -#endif +#include "rwcore.h" +#include "rpmatfx.h" struct MatFXNothing { int pad[5]; int effect; }; @@ -47,16 +46,16 @@ struct MatFX int effects; }; -#ifdef RWLIBS extern "C" { extern int MatFXMaterialDataOffset; extern int MatFXAtomicDataOffset; + void _rpMatFXD3D8AtomicMatFXEnvRender(RxD3D8InstanceData* inst, int flags, int sel, RwTexture* texture, RwTexture* envMap); + void _rpMatFXD3D8AtomicMatFXRenderBlack(RxD3D8InstanceData *inst); + void _rpMatFXD3D8AtomicMatFXBumpMapRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *bumpMap, RwTexture *envMap); + void _rpMatFXD3D8AtomicMatFXDualPassRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *dualTexture); } -#else -int &MatFXMaterialDataOffset = *(int*)0x66188C; -int &MatFXAtomicDataOffset = *(int*)0x66189C; -#endif + #ifdef PS2_MATFX @@ -218,12 +217,96 @@ _rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int se RwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); } -#ifdef RWLIBS -STARTPATCHES - InjectHook((uintptr)&_rpMatFXD3D8AtomicMatFXEnvRender, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP); -ENDPATCHES -#endif +void +_rwD3D8EnableClippingIfNeeded(void *object, RwUInt8 type) +{ + int clip; + if (type == rpATOMIC) + clip = !RwD3D8CameraIsSphereFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), RpAtomicGetWorldBoundingSphere((RpAtomic *)object)); + else + clip = !RwD3D8CameraIsBBoxFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), &((RpWorldSector *)object)->tightBoundingBox); + RwD3D8SetRenderState(D3DRS_CLIPPING, clip); +} -#endif +void +_rwD3D8AtomicMatFXRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags) +{ + RwBool lighting; + RwBool forceBlack; + RxD3D8ResEntryHeader *header; + RxD3D8InstanceData *inst; + RwInt32 i; -#endif + if (flags & rpGEOMETRYPRELIT) { + RwD3D8SetRenderState(D3DRS_COLORVERTEX, 1); + RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); + } else { + RwD3D8SetRenderState(D3DRS_COLORVERTEX, 0); + RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); + } + + _rwD3D8EnableClippingIfNeeded(object, type); + + RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting); + if (lighting || flags & rpGEOMETRYPRELIT) { + forceBlack = FALSE; + } else { + forceBlack = TRUE; + RwD3D8SetTexture(nil, 0); + RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(0, 0, 0, 255)); + RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); + RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR); + } + + header = (RxD3D8ResEntryHeader *)(repEntry + 1); + inst = (RxD3D8InstanceData *)(header + 1); + for (i = 0; i < header->numMeshes; i++) { + if (forceBlack) + _rpMatFXD3D8AtomicMatFXRenderBlack(inst); + else { + if (lighting) + RwD3D8SetSurfaceProperties(&inst->material->color, &inst->material->surfaceProps, flags & rpGEOMETRYMODULATEMATERIALCOLOR); + MatFX *matfx = *RWPLUGINOFFSET(MatFX *, inst->material, MatFXMaterialDataOffset); + int effect = matfx ? matfx->effects : rpMATFXEFFECTNULL; + switch (effect) { + case rpMATFXEFFECTNULL: + default: + _rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, inst->material->texture); + break; + case rpMATFXEFFECTBUMPMAP: + _rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, nil); + break; + case rpMATFXEFFECTENVMAP: + { + // TODO: matfx switch in the settings + //_rpMatFXD3D8AtomicMatFXEnvRender(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex); + _rpMatFXD3D8AtomicMatFXEnvRender_ps2(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex); + break; + } + case rpMATFXEFFECTBUMPENVMAP: + _rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, matfx->fx[1].e.envTex); + break; + case rpMATFXEFFECTDUAL: + _rpMatFXD3D8AtomicMatFXDualPassRender(inst, flags, inst->material->texture, matfx->fx[0].d.dualTex); + break; + } + } + inst++; + } + + if (forceBlack) { + RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); + RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + } +} + +void +ReplaceMatFxCallback() +{ + RxD3D8AllInOneSetRenderCallBack( + RxPipelineFindNodeByName(RpMatFXGetD3D8Pipeline(rpMATFXD3D8ATOMICPIPELINE), RxNodeDefinitionGetD3D8AtomicAllInOne()->name, nil, nil), + _rwD3D8AtomicMatFXRenderCallback); +} +#endif // PS2_MATFX + +#endif // !LIBRW diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 376c0a11..630b3345 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -16,7 +16,6 @@ #include "platform.h" #include "crossplatform.h" -#include "patcher.h" #include "main.h" #include "FileMgr.h" #include "Text.h" @@ -1378,7 +1377,6 @@ main(int argc, char *argv[]) #endif RwV2d pos; RwInt32 i; -// StaticPatcher::Apply(); #ifndef _WIN32 struct sigaction act; diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index a57f4846..9795bde9 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -76,7 +76,6 @@ static psGlobalType PsGlobal; {debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;} #include "common.h" -#include "patcher.h" #include "main.h" #include "FileMgr.h" #include "Text.h" @@ -1926,7 +1925,6 @@ WinMain(HINSTANCE instance, RwV2d pos; RwInt32 argc, i; RwChar **argv; - StaticPatcher::Apply(); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); #if 0 From c813630aad7c2fc98e0038bbc6362aad040e8d46 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 22 Jul 2020 14:02:14 +0200 Subject: [PATCH 70/85] update librw --- librw | 2 +- src/fakerw/fake.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/librw b/librw index 853fa449..4883b03f 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 853fa44982dcb02d8e6bbe40045ee5c594c78e52 +Subproject commit 4883b03f2b8f060c04f054573e8f345878e93a11 diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 7a2b136e..0bc69abe 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -308,7 +308,7 @@ ConvertTexRaster(rw::Raster *ras) Image *img = ras->toImage(); ras->destroy(); - img->unindex(); + img->unpalettize(); ras = Raster::createFromImage(img); img->destroy(); return ras; From fdb262bca00da25e96529085cc1ca8d2d8e59c37 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 22 Jul 2020 14:02:29 +0200 Subject: [PATCH 71/85] update librw --- librw | 2 +- src/fakerw/fake.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/librw b/librw index 853fa449..4883b03f 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 853fa44982dcb02d8e6bbe40045ee5c594c78e52 +Subproject commit 4883b03f2b8f060c04f054573e8f345878e93a11 diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index f95845a8..ef5f361f 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -307,7 +307,7 @@ ConvertTexRaster(rw::Raster *ras) Image *img = ras->toImage(); ras->destroy(); - img->unindex(); + img->unpalettize(); ras = Raster::createFromImage(img); img->destroy(); return ras; From f40f44b14e028c4bb2bee2e898c210e3f41b20bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 21 Jul 2020 05:59:31 +0300 Subject: [PATCH 72/85] Peds, Hud, CFO 1/2, fixes - including zone names --- src/audio/soundlist.h | 2 +- src/control/Phones.cpp | 1 - src/control/Script.cpp | 40 +- src/core/Frontend.cpp | 365 ++++-- src/core/Frontend.h | 13 +- src/core/General.h | 2 +- src/core/{MenuScreens.h => MenuScreens.cpp} | 8 +- src/core/Pad.cpp | 5 +- src/core/Radar.cpp | 6 +- src/core/User.cpp | 8 + src/core/User.h | 1 + src/core/Zones.cpp | 2 +- src/core/config.h | 1 - src/entities/Entity.cpp | 17 + src/entities/Entity.h | 1 + src/math/maths.h | 2 + src/peds/Ped.cpp | 1267 ++++++++++++------- src/peds/Ped.h | 11 +- src/peds/PedDebug.cpp | 10 +- src/peds/PlayerPed.cpp | 117 +- src/peds/PlayerPed.h | 4 +- src/render/Hud.cpp | 332 ++--- src/render/Hud.h | 1 + src/render/Renderer.cpp | 8 +- src/render/WaterLevel.cpp | 22 +- src/skel/glfw/glfw.cpp | 9 +- src/skel/platform.h | 1 + src/skel/win/win.cpp | 24 +- src/skel/win/win.h | 3 +- src/vehicles/Automobile.cpp | 2 +- 30 files changed, 1467 insertions(+), 818 deletions(-) rename src/core/{MenuScreens.h => MenuScreens.cpp} (98%) diff --git a/src/audio/soundlist.h b/src/audio/soundlist.h index 05a0d7c3..2a5b83cf 100644 --- a/src/audio/soundlist.h +++ b/src/audio/soundlist.h @@ -188,7 +188,7 @@ enum eSound : uint16 SOUND_186, // makes same sound with 40 SOUND_187, // makes same sound with 46 SOUND_MELEE_ATTACK_START, - SOUND_189, + SOUND_SKATING, SOUND_WEAPON_MINIGUN_ATTACK, SOUND_WEAPON_MINIGUN_2, SOUND_WEAPON_MINIGUN_3, diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 71f6c8e5..4f1703f2 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -284,7 +284,6 @@ CPhoneInfo::Initialise(void) CBuilding *building = pool->GetSlot(i); if (building) { if (building->GetModelIndex() == MI_PHONEBOOTH1) { - assert(m_nMax < ARRAY_SIZE(m_aPhones) && "NUMPHONES should be increased"); CPhone *maxPhone = &m_aPhones[m_nMax]; maxPhone->m_nState = PHONE_STATE_FREE; maxPhone->m_vecPos = building->GetPosition(); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index e1ab0310..88a62f4e 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3225,9 +3225,8 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2)); else UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -3246,9 +3245,8 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) UpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); else UpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -4061,9 +4059,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -4080,9 +4077,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) float y2 = *(float*)&ScriptParams[5]; float z2 = *(float*)&ScriptParams[6]; UpdateCompareFlag(vehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -4799,9 +4795,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -4819,9 +4814,8 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float z2 = *(float*)&ScriptParams[6]; UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); - if (!ScriptParams[7]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); + if (ScriptParams[7]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2); return 0; @@ -7676,9 +7670,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; @@ -7693,9 +7686,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; UpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2)); - if (!ScriptParams[5]) - return 0; - CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); + if (ScriptParams[5]) + CTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT); if (CTheScripts::DbgFlag) CTheScripts::DrawDebugSquare(x1, y1, x2, y2); return 0; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 4c205675..a3b15ac1 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -24,7 +24,6 @@ #include "GenericGameStorage.h" #include "Script.h" #include "Camera.h" -#include "MenuScreens.h" #include "ControllerConfig.h" #include "Vehicle.h" #include "MBlur.h" @@ -214,75 +213,6 @@ ScaleAndCenterX(float x) // --- Functions not in the game/inlined starts -bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); -void DoRWStuffEndOfFrame(void); - -#ifdef PS2_LIKE_MENU -void -CMenuManager::SwitchToNewScreen(int8 screen) -{ - if (reverseAlpha) { - m_nPrevScreen = m_nCurrScreen; - m_nCurrScreen = pendingScreen; - m_nCurrOption = pendingOption; - reverseAlpha = false; - if (updateDelay) - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); - } - if (withReverseAlpha) { - pendingOption = option; - pendingScreen = screen; - reverseAlpha = true; - } else { - m_nPrevScreen = m_nCurrScreen; - m_nCurrScreen = screen; - m_nCurrOption = option; - if (updateDelay) - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); - } - m_nMenuFadeAlpha = 255; -} -#else - -// --MIAMI: Done except using VC's gMenuPages -void -CMenuManager::SwitchToNewScreen(int8 screen) -{ - bMenuChangeOngoing = true; - DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); - DrawBackground(true); - DoRWStuffEndOfFrame(); - DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); - DrawBackground(true); - DoRWStuffEndOfFrame(); - m_nPrevScreen = m_nCurrScreen; - m_ShowEmptyBindingError = false; - ResetHelperText(); - - ThingsToDoBeforeLeavingPage(); - - if (screen == -2) { - int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; - int oldOption = (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry))); - - m_nCurrOption = oldOption; - m_nCurrScreen = oldScreen; - } else if (screen == 0) { - m_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu; - m_nCurrOption = 0; - } else { - m_nCurrOption = 0; - m_nCurrScreen = screen; - } - - if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) - m_nCurrOption = 8; - m_nMenuFadeAlpha = 0; - m_nOptionHighlightTransitionBlend = 0; - m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); -} -#endif - inline void CMenuManager::ScrollUpListByOne() { @@ -349,7 +279,6 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) } } -// TODO(Miami) inline void CMenuManager::ThingsToDoBeforeLeavingPage() { @@ -373,13 +302,123 @@ CMenuManager::ThingsToDoBeforeLeavingPage() CPlayerSkin::EndFrontendSkinEdit(); } - if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { - m_nTotalListRow = 0; +#ifdef CUSTOM_FRONTEND_OPTIONS + for (int i = 0; i < numCustomFrontendOptions; i++) { + FrontendOption& option = customFrontendOptions[i]; + if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) { + if (option.returnPrevPageFunc) + option.returnPrevPageFunc(); + + if (m_nCurrOption == option.screenOptionOrder && option.type == FEOPTION_DYNAMIC) + option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + + if (option.onlyApplyOnEnter) + option.displayedValue = *option.value; + } } +#endif +} + +int8 +CMenuManager::GetPreviousPageOption() +{ +#ifndef CUSTOM_FRONTEND_OPTIONS + return (!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry : + (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry)))); +#else + int8 prevPage = aScreens[m_nCurrScreen].m_PreviousPage; + + if (prevPage == -1) // Game also does same + return 0; + + prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage; + + for (int i = 0; i < NUM_MENUROWS; i++) { + if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) { + return i; + } + } + + // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?) + return (!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry : + (m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry)))); +#endif } // ------ Functions not in the game/inlined ends +bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha); +void DoRWStuffEndOfFrame(void); + +#ifdef PS2_LIKE_MENU +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + if (reverseAlpha) { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = pendingScreen; + m_nCurrOption = pendingOption; + reverseAlpha = false; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + if (withReverseAlpha) { + pendingOption = option; + pendingScreen = screen; + reverseAlpha = true; + } else { + m_nPrevScreen = m_nCurrScreen; + m_nCurrScreen = screen; + m_nCurrOption = option; + if (updateDelay) + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); + } + m_nMenuFadeAlpha = 255; +} +#else + +// --MIAMI: Done +void +CMenuManager::SwitchToNewScreen(int8 screen) +{ + bMenuChangeOngoing = true; + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); + DrawBackground(true); + DoRWStuffEndOfFrame(); + m_nPrevScreen = m_nCurrScreen; + m_ShowEmptyBindingError = false; + ResetHelperText(); + + ThingsToDoBeforeLeavingPage(); + + if (screen == -2) { + int oldScreen = aScreens[m_nCurrScreen].m_PreviousPage; + int oldOption = GetPreviousPageOption(); + + m_nCurrOption = oldOption; + m_nCurrScreen = oldScreen; + } else if (screen == 0) { + m_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu; + m_nCurrOption = 0; + } else { + m_nCurrOption = 0; + m_nCurrScreen = screen; + } + + if (m_nPrevScreen == MENUPAGE_SKIN_SELECT || m_nPrevScreen == MENUPAGE_KEYBOARD_CONTROLS) + m_nTotalListRow = 0; + + if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) + m_nCurrOption = 8; + m_nMenuFadeAlpha = 0; + m_nOptionHighlightTransitionBlend = 0; + m_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode(); +} +#endif + CMenuManager::CMenuManager() { m_StatsScrollSpeed = 150.0f; @@ -463,7 +502,7 @@ CMenuManager::Initialise(void) DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); DoRWStuffEndOfFrame(); m_AllowNavigation = false; - m_menuTransitionProgress = -50; + m_menuTransitionProgress = -50; // to start from black m_nMenuFadeAlpha = 0; m_nCurrOption = 0; m_nOptionHighlightTransitionBlend = 0; @@ -1172,6 +1211,32 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) rightText = TheText.Get("FEA_NM3"); } break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) { + leftText = (wchar*)option.leftText; + if (option.type == FEOPTION_SELECT) { + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) + option.displayedValue = 0; + + rightText = (wchar*)option.rightTexts[option.displayedValue]; + + } else if (option.type == FEOPTION_DYNAMIC) { + if (option.drawFunc) { + bool isOptionDisabled = false; + rightText = option.drawFunc(&isOptionDisabled); + if (isOptionDisabled) + CFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255))); + } + } + } else { + debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options is borked"); + } + + break; +#endif } // Highlight trapezoid @@ -1326,6 +1391,24 @@ CMenuManager::DrawStandardMenus(bool drawCurrScreen) } } #endif +#ifdef CUSTOM_FRONTEND_OPTIONS + static int lastOption = m_nCurrOption; + + if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_TRIGGERFUNC) { + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu]; + if (option.onlyApplyOnEnter && m_nCurrOption != i) + option.displayedValue = *option.value; + + if (m_nCurrOption != lastOption && lastOption == i) { + FrontendOption& oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu]; + if (oldOption.type == FEOPTION_DYNAMIC) + oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS); + } + } + + if (i == MAX_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i + 1].m_EntryName[0] == '\0') + lastOption = m_nCurrOption; +#endif // TODO(Miami): check // Sliders @@ -1955,10 +2038,10 @@ CMenuManager::DrawControllerSetupScreen() float curOptY = i * rowHeight + yStart; if (m_nMousePosY > MENU_Y(curOptY) && m_nMousePosY < MENU_Y(rowHeight + curOptY)) { - if (m_nPrevOption != i && m_nCurrExLayer == HOVEROPTION_LIST) + if (m_nOptionMouseHovering != i && m_nCurrExLayer == HOVEROPTION_LIST) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); - m_nPrevOption = i; + m_nOptionMouseHovering = i; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrExLayer = HOVEROPTION_LIST; m_nSelectedListRow = i; @@ -2660,7 +2743,7 @@ CMenuManager::DrawPlayerSetupScreen() if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) { if (m_nMousePosY > MENU_Y(rowStartY) && m_nMousePosY < MENU_Y(rowEndY)) { - m_nPrevOption = rowIdx; + m_nOptionMouseHovering = rowIdx; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrExLayer = HOVEROPTION_LIST; } @@ -3023,6 +3106,10 @@ CMenuManager::InitialiseChangedLanguageSettings() default: break; } + +#ifdef CUSTOM_FRONTEND_OPTIONS + CustomFrontendOptionsPopulate(); +#endif } } @@ -3618,7 +3705,7 @@ CMenuManager::ProcessButtonPresses(void) m_nMousePosY < MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y + MENU_DEFAULT_LINE_HEIGHT)) { static int oldScreen = m_nCurrScreen; - m_nPrevOption = rowToCheck; + m_nOptionMouseHovering = rowToCheck; if (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) { m_nCurrOption = rowToCheck; m_bShowMouse = true; @@ -3632,7 +3719,7 @@ CMenuManager::ProcessButtonPresses(void) break; } if (m_bShowMouse && m_nMenuFadeAlpha == 255) { - m_nPrevOption = oldOption; + m_nOptionMouseHovering = oldOption; m_nCurrOption = oldOption; } } @@ -3641,7 +3728,7 @@ CMenuManager::ProcessButtonPresses(void) if (oldOption != m_nCurrOption) { if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LABEL) { ++m_nCurrOption; - ++m_nPrevOption; + ++m_nOptionMouseHovering; } m_nOptionHighlightTransitionBlend = 0; DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0); @@ -3923,7 +4010,7 @@ CMenuManager::ProcessButtonPresses(void) if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESUME && #endif (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } } else if (CPad::GetPad(0)->GetLeftMouseJustDown()) { @@ -3937,7 +4024,7 @@ CMenuManager::ProcessButtonPresses(void) OutputDebugString("FRONTEND RADIO STATION CHANGED"); } else if (m_nHoverOption == HOVEROPTION_RANDOM_ITEM && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESUME) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } #else @@ -4024,7 +4111,7 @@ CMenuManager::ProcessButtonPresses(void) break; case HOVEROPTION_RANDOM_ITEM: if (((m_nCurrOption != 0) || (m_nCurrScreen != MENUPAGE_PAUSE_MENU)) { - m_nCurrOption = m_nPrevOption; + m_nCurrOption = m_nOptionMouseHovering; optionSelected = true; } break; @@ -4358,26 +4445,6 @@ CMenuManager::ProcessButtonPresses(void) InitialiseChangedLanguageSettings(); SaveSettings(); break; -#ifdef MORE_LANGUAGES - case MENUACTION_LANG_PL: - m_PrefsLanguage = LANGUAGE_POLISH; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_RUS: - m_PrefsLanguage = LANGUAGE_RUSSIAN; - m_bFrontEnd_ReloadObrTxtGxt = true; - CMenuManager::InitialiseChangedLanguageSettings(); - SaveSettings(); - break; - case MENUACTION_LANG_JAP: - m_PrefsLanguage = LANGUAGE_JAPANESE; - m_bFrontEnd_ReloadObrTxtGxt = true; - InitialiseChangedLanguageSettings(); - SaveSettings(); - break; -#endif case MENUACTION_POPULATESLOTS_CHANGEMENU: PcSaveHelper.PopulateSlotInfo(); @@ -4540,7 +4607,6 @@ CMenuManager::ProcessButtonPresses(void) } else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) { ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); - MousePointerStateHelper.GetMouseSetUp(); ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); #if !defined RW_GL3 if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { @@ -4595,6 +4661,33 @@ CMenuManager::ProcessButtonPresses(void) } break; } +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; + if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { + if (option.type == FEOPTION_SELECT) { + if (!option.onlyApplyOnEnter) { + option.displayedValue++; + if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0) + option.displayedValue = 0; + } + option.changeFunc(option.displayedValue); + *option.value = option.displayedValue; + + } else if (option.type == FEOPTION_DYNAMIC) { + option.buttonPressFunc(FEOPTION_ACTION_SELECT); + } else if (option.type == FEOPTION_REDIRECT) { + ChangeScreen(option.to, option.option, true, option.fadeIn); + } else if (option.type == FEOPTION_GOBACK) { + goBack = true; + } + } else { + debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options are borked"); + } + + break; +#endif } } ProcessOnOffMenuOptions(); @@ -4641,6 +4734,9 @@ CMenuManager::ProcessButtonPresses(void) if (oldScreen != -1) { ThingsToDoBeforeLeavingPage(); + if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) { + m_nTotalListRow = 0; + } #ifdef PS2_LIKE_MENU if (!bottomBarActive && @@ -4797,6 +4893,36 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; +#ifdef CUSTOM_FRONTEND_OPTIONS + case MENUACTION_TRIGGERFUNC: + FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu]; + if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) { + if (option.type == FEOPTION_SELECT) { + if (changeValueBy > 0) { + option.displayedValue++; + if (option.displayedValue >= option.numRightTexts) + option.displayedValue = 0; + } else { + option.displayedValue--; + if (option.displayedValue < 0) + option.displayedValue = option.numRightTexts - 1; + } + if (!option.onlyApplyOnEnter) { + option.changeFunc(option.displayedValue); + *option.value = option.displayedValue; + } + } else if (option.type == FEOPTION_DYNAMIC) { + option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); + } + else { + debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder); + assert(0 && "Custom frontend options are borked"); + } + + break; +#endif } ProcessOnOffMenuOptions(); if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) { @@ -4890,13 +5016,6 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); SaveSettings(); break; -#ifdef FREE_CAM - case MENUACTION_FREECAM: - TheCamera.bFreeCam = !TheCamera.bFreeCam; - DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); - SaveSettings(); - break; -#endif } } @@ -5010,7 +5129,7 @@ CMenuManager::ProcessFileActions() } } -// --MIAMI: Done except DxInput things, are they even needed? +// --MIAMI: Done void CMenuManager::SwitchMenuOnAndOff() { @@ -5036,7 +5155,12 @@ CMenuManager::SwitchMenuOnAndOff() m_bMenuActive = !m_bMenuActive; if (m_bMenuActive) { - // TODO(Miami): DxInput?? +#if defined RW_D3D9 || defined RWLIBS + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } +#endif Initialise(); LoadAllTextures(); @@ -5049,8 +5173,12 @@ CMenuManager::SwitchMenuOnAndOff() DoRWStuffEndOfFrame(); DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); DoRWStuffEndOfFrame(); - - // TODO(Miami): DxInput?? +#if defined RW_D3D9 || defined RWLIBS + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(true); + } +#endif #ifdef PS2_LIKE_MENU bottomBarActive = false; @@ -5095,7 +5223,12 @@ CMenuManager::SwitchMenuOnAndOff() m_bMenuActive = true; m_OnlySaveMenu = true; - // TODO(Miami): DxInput?? +#if defined RW_D3D9 || defined RWLIBS + if (_InputMouseNeedsExclusive()) { + _InputShutdownMouse(); + _InputInitialiseMouse(false); + } +#endif Initialise(); LoadAllTextures(); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 327bf6fa..83d86d5b 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -265,17 +265,9 @@ enum eMenuAction MENUACTION_DYNAMICACOUSTIC, MENUACTION_MOUSESTEER, MENUACTION_UNK110, -#ifdef MORE_LANGUAGES - MENUACTION_LANG_PL, - MENUACTION_LANG_RUS, - MENUACTION_LANG_JAP, -#endif #ifdef IMPROVED_VIDEOMODE MENUACTION_SCREENMODE, #endif -#ifdef FREE_CAM - MENUACTION_FREECAM, -#endif #ifdef LEGACY_MENU_OPTIONS MENUACTION_CTRLVIBRATION, MENUACTION_CTRLCONFIG, @@ -547,7 +539,7 @@ public: int32 m_nMouseOldPosY; int32 m_nHoverOption; bool m_bShowMouse; - int32 m_nPrevOption; + int32 m_nOptionMouseHovering; bool m_bStartWaitingForKeyBind; bool m_bWaitingForNewKeyBind; bool m_bKeyChangeNotProcessed; @@ -664,6 +656,7 @@ public: void ScrollDownListByOne(); void PageUpList(bool); void PageDownList(bool); + int8 GetPreviousPageOption(); // uint8 GetNumberOfMenuOptions(); }; @@ -673,6 +666,6 @@ VALIDATE_SIZE(CMenuManager, 0x688); #endif extern CMenuManager FrontEndMenuManager; - +extern CMenuScreen aScreens[]; #endif \ No newline at end of file diff --git a/src/core/General.h b/src/core/General.h index dbf169e9..7ab444a4 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -108,7 +108,7 @@ public: if (angle >= TWOPI) angle -= TWOPI; - return (int)floorf(angle / DEGTORAD(45.0f)); + return (int)Floor(angle / DEGTORAD(45.0f)); } // Unlike usual string comparison functions, these don't care about greater or lesser diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.cpp similarity index 98% rename from src/core/MenuScreens.h rename to src/core/MenuScreens.cpp index 3f9631c8..6fbf597b 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.cpp @@ -1,6 +1,8 @@ -#pragma once +#include "common.h" +#include "Frontend.h" +#ifdef PC_MENU -// --MIAMI: Done except commented things +// If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp. CMenuScreen aScreens[] = { // MENUPAGE_STATS = 0 @@ -341,3 +343,5 @@ CMenuScreen aScreens[] = { }, #endif }; + +#endif diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 97cc1786..83930c41 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -39,6 +39,7 @@ #include "General.h" #include "Fluff.h" #include "Gangs.h" +#include "platform.h" #ifdef GTA_PS2 #include "eetypes.h" @@ -671,7 +672,7 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() #if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) - _InputInitialiseMouse(); + _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); if ( PSGLOBAL(mouse) != nil ) { @@ -725,7 +726,7 @@ void CPad::UpdateMouse() { #if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) - _InputInitialiseMouse(); + _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); DIMOUSESTATE2 state; diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index c359793c..559a8cd6 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -778,8 +778,8 @@ void CRadar::DrawRadarMap() DrawRadarMask(); // top left ist (0, 0) - int x = floorf((vec2DRadarOrigin.x - RADAR_MIN_X) / RADAR_TILE_SIZE); - int y = ceilf((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - RADAR_MIN_Y) / RADAR_TILE_SIZE); + int x = Floor((vec2DRadarOrigin.x - RADAR_MIN_X) / RADAR_TILE_SIZE); + int y = Ceil((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - RADAR_MIN_Y) / RADAR_TILE_SIZE); StreamRadarSections(x, y); RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); @@ -1332,7 +1332,7 @@ void CRadar::Shutdown() void CRadar::StreamRadarSections(const CVector &posn) { - StreamRadarSections(floorf((2000.0f + posn.x) / 500.0f), ceilf(7.0f - (2000.0f + posn.y) / 500.0f)); + StreamRadarSections(Floor((2000.0f + posn.x) / 500.0f), Ceil(7.0f - (2000.0f + posn.y) / 500.0f)); } void CRadar::StreamRadarSections(int32 x, int32 y) diff --git a/src/core/User.cpp b/src/core/User.cpp index 56e37ac4..53196d03 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -74,6 +74,14 @@ CPlaceName::Display() CHud::SetZoneName(text); } +void +CPlaceName::ProcessAfterFrontEndShutDown(void) +{ + CHud::m_pLastZoneName = nil; + CHud::m_ZoneState = 0; + m_nAdditionalTimer = 250; +} + CCurrentVehicle::CCurrentVehicle() { Init(); diff --git a/src/core/User.h b/src/core/User.h index 153ef57b..dd53a40a 100644 --- a/src/core/User.h +++ b/src/core/User.h @@ -16,6 +16,7 @@ public: void Init(); void Process(); void Display(); + void ProcessAfterFrontEndShutDown(); }; class CCurrentVehicle diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 87e85da5..3095b36d 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -104,7 +104,7 @@ CTheZones::Init(void) NavigationZoneArray[0].maxy = 2000.0f; NavigationZoneArray[0].maxz = 500.0f; NavigationZoneArray[0].level = LEVEL_GENERIC; - NavigationZoneArray[0].type = ZONE_NAVIG; + NavigationZoneArray[0].type = ZONE_DEFAULT; m_CurrLevel = LEVEL_GENERIC; diff --git a/src/core/config.h b/src/core/config.h index 14489491..4110b131 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -285,7 +285,6 @@ enum Config { #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle // #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward #define CANCELLABLE_CAR_ENTER -//#define PEDS_REPORT_CRIMES_ON_PHONE // Camera #define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 63ea03fc..4c88c485 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -620,6 +620,23 @@ CEntity::PruneReferences(void) } } +// Clean up the reference from *pent -> 'this' +void +CEntity::CleanUpOldReference(CEntity **pent) +{ + CReference* ref, ** lastnextp; + lastnextp = &m_pFirstReference; + for (ref = m_pFirstReference; ref; ref = ref->next) { + if (ref->pentity == pent) { + *lastnextp = ref->next; + ref->next = CReferences::pEmptyList; + CReferences::pEmptyList = ref; + break; + } + lastnextp = &ref->next; + } +} + void CEntity::UpdateRpHAnim(void) { diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 7570110b..fd01b6f8 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -168,6 +168,7 @@ public: void RegisterReference(CEntity **pent); void ResolveReferences(void); void PruneReferences(void); + void CleanUpOldReference(CEntity **pent); #ifdef PED_SKIN void UpdateRpHAnim(void); diff --git a/src/math/maths.h b/src/math/maths.h index 51b0ef10..8d68bf64 100644 --- a/src/math/maths.h +++ b/src/math/maths.h @@ -15,3 +15,5 @@ inline float Sqrt(float x) { return sqrtf(x); } inline float RecipSqrt(float x, float y) { return x/Sqrt(y); } inline float RecipSqrt(float x) { return RecipSqrt(1.0f, x); } inline float Pow(float x, float y) { return powf(x, y); } +inline float Floor(float x) { return floorf(x); } +inline float Ceil(float x) { return ceilf(x); } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 557aafa3..7db2124d 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -428,6 +428,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIgnoreThreatsBehindObjects = false; bNeverEverTargetThisPed = false; + bCrouchWhenScared = false; + bKnockedOffBike = false; + b158_8 = false; b158_10 = false; bBoughtIceCream = false; b158_40 = false; @@ -2315,6 +2318,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } +// --MIAMI: Done static void particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) { @@ -2324,10 +2328,15 @@ particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) case SURFACE_GRAVEL: case SURFACE_PAVEMENT: case SURFACE_SAND: + case SURFACE_SAND_BEACH: + case SURFACE_CONCRETE_BEACH: for (int i = 0; i < times; ++i) { CVector adjustedPos = pos; adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + // ?? + CGeneral::GetRandomNumber(); + CGeneral::GetRandomNumber(); CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0); } break; @@ -2336,10 +2345,10 @@ particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) } } +// --MIAMI: Done static void particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times) { -#ifdef PC_PARTICLE for (int i = 0; i < times; i++) { CVector adjustedPos = pos; adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); @@ -2348,21 +2357,20 @@ particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times) CVector direction = ped->GetForward() * -0.05f; CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200); } -#else - for ( int32 i = 0; i < times; i++ ) - { - CVector adjustedPos = pos; - adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - - CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200); - } -#endif } +// --MIAMI: Done void CPed::PlayFootSteps(void) { + CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); + CAnimBlendAssociation *walkRunAssoc = nil; + float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f; + bool isSkater = m_pedStats == CPedStats::ms_apPedStats[PEDSTAT_SKATER]; + + CVector footPosL(0.0f, 0.0f, 0.0f), footPosR(0.0f, 0.0f, 0.0f); + bool footPosLok = false, footPosRok = false; + if (bDoBloodyFootprints) { if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) { m_bloodyFootprintCountOrDeathTime--; @@ -2375,10 +2383,6 @@ CPed::PlayFootSteps(void) if (!bIsStanding) return; - CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); - CAnimBlendAssociation *walkRunAssoc = nil; - float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f; - for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) { if (assoc->flags & ASSOC_WALK) { walkRunAssoc = assoc; @@ -2388,96 +2392,200 @@ CPed::PlayFootSteps(void) } } -#ifdef GTA_PS2_STUFF - CAnimBlendAssociation *runStopAsoc = NULL; - - if ( IsPlayer() ) - { - runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); - - if ( runStopAsoc == NULL ) - runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); - } - - if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f ) - { - { - CVector pos(0.0f, 0.0f, 0.0f); - TransformToNode(pos, PED_FOOTL); - - pos.z -= 0.1f; - pos += GetForward()*0.2f; - particleProduceFootDust(this, pos, 0.02f, 1); - } - - { - CVector pos(0.0f, 0.0f, 0.0f); - TransformToNode(pos, PED_FOOTR); - - pos.z -= 0.1f; - pos += GetForward()*0.2f; - particleProduceFootDust(this, pos, 0.02f, 1); - } - } -#endif - - if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) { - float stepStart = 1 / 15.0f; + + float stepStart = 1.f / 15.f; float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart; float currentTime = walkRunAssoc->currentTime; - int stepPart = 0; - if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart) - stepPart = 1; - else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd) - stepPart = 2; + if (isSkater) { + // both are unused + static float stepStartSection = 1.0f; + static float animSections = 15.f; - if (stepPart != 0) { - DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f); - CVector footPos(0.0f, 0.0f, 0.0f); - TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR); - - CVector forward = GetForward(); - - footPos.z -= 0.1f; - footPos += 0.2f * forward; - - if (bDoBloodyFootprints) { - CVector2D top(forward * 0.26f); - CVector2D right(GetRight() * 0.14f); - - CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos, - top.x, top.y, - right.x, right.y, - 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); - - if (m_bloodyFootprintCountOrDeathTime <= 20) { - m_bloodyFootprintCountOrDeathTime = 0; - bDoBloodyFootprints = false; - } else { - m_bloodyFootprintCountOrDeathTime -= 20; + float moveStart, soundVolume, skateTime; + if (walkRunAssoc->animId == ANIM_WALK) { + moveStart = 0.0f; + skateTime = 8.f / 15.f; + } else { + moveStart = 0.0f; + skateTime = 5.f / 15.f; + } + switch (CSurfaceTable::GetAdhesionGroup(m_nSurfaceTouched)) { + case ADHESIVE_LOOSE: + if (CGeneral::GetRandomNumber() % 128) { + m_vecAnimMoveDelta *= 0.5f; + } else { + SetFall(0, ANIM_KO_SKID_BACK, false); + } + soundVolume = 0.5f; + break; + case ADHESIVE_SAND: + if (CGeneral::GetRandomNumber() % 64) { + m_vecAnimMoveDelta *= 0.2f; + } else { + SetFall(0, ANIM_KO_SKID_BACK, false); + } + soundVolume = 0.2f; + break; + case ADHESIVE_WET: + m_vecAnimMoveDelta *= 0.3f; + soundVolume = 0.2f; + break; + default: + soundVolume = 1.f; + break; + } + if (soundVolume > 0.2f && currentTime > moveStart && currentTime - walkRunAssoc->timeStep <= moveStart) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SKATING, ((int)(127.f * soundVolume) | (walkRunAssoc->animId << 8))); + } else if (soundVolume > 0.2f) { + if (currentTime > skateTime && currentTime - walkRunAssoc->timeStep <= skateTime) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_SKATING, ((int)(127.f * soundVolume) | (walkRunAssoc->animId << 8))); } } - if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { - if(IsPlayer()) - particleProduceFootDust(this, footPos, 0.0f, 4); + + } else { + int stepPart = 0; + + // This section is shortened/optimized for sanity. + + if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart) + stepPart = 1; + else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd) + stepPart = 2; + + if (stepPart != 0) { + CVector adjustedFootPos; + if (stepPart == 1) { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_STEP_START, 1.0f); + TransformToNode(footPosL, PED_FOOTL); + footPosLok = true; + adjustedFootPos = footPosL; + } else { + DMAudio.PlayOneShot(m_audioEntityId, SOUND_STEP_END, 1.0f); + TransformToNode(footPosR, PED_FOOTR); + footPosRok = true; + adjustedFootPos = footPosR; + } + + CVector forward = GetForward(); + + adjustedFootPos.z -= 0.1f; + adjustedFootPos += 0.2f * forward; + + if (bDoBloodyFootprints) { + CVector2D top(forward * 0.26f); + CVector2D right(GetRight() * (stepPart == 1 ? 0.14f : 0.1f)); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPos, + top.x, top.y, + right.x, right.y, + 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); + + if (m_bloodyFootprintCountOrDeathTime <= 20) { + m_bloodyFootprintCountOrDeathTime = 0; + bDoBloodyFootprints = false; + } else { + m_bloodyFootprintCountOrDeathTime -= 20; + } + } + if (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) { + CVector2D top(forward * -0.26f); + CVector2D right(GetRight() * (stepPart == 1 ? 0.1f : 0.14f)); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPos, + top.x, top.y, + right.x, right.y, + 120, 250, 250, 50, 4.0f, 5000.0f, 1.0f); + } + if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { + if (IsPlayer()) + particleProduceFootDust(this, adjustedFootPos, 0.0f, 4); + + } else if (stepPart == 2) { + particleProduceFootSplash(this, adjustedFootPos, 0.15f, 4); + } } -#ifdef PC_PARTICLE - else if(stepPart == 2) -#else - else -#endif - { - particleProduceFootSplash(this, footPos, 0.15f, 4); + } + } + + if (IsPlayer() && !walkRunAssoc && bIsLanding) { + if (!footPosLok) + TransformToNode(footPosL, PED_FOOTL); + + CVector forward = GetForward(); + + CVector adjustedFootPosL = footPosL; + adjustedFootPosL.z -= 0.1f; + adjustedFootPosL += 0.2f * forward; + if (bDoBloodyFootprints) { + CVector2D top(forward * 0.26f); + CVector2D right(GetRight() * 0.14f); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosL, + top.x, top.y, + right.x, right.y, + 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); + + if (m_bloodyFootprintCountOrDeathTime <= 20) { + m_bloodyFootprintCountOrDeathTime = 0; + bDoBloodyFootprints = false; + } + else { + m_bloodyFootprintCountOrDeathTime -= 20; + } + } + if (!isSkater) { + if (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) { + CVector2D top(forward * -0.26f); + CVector2D right(GetRight() * 0.14f); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosL, + top.x, top.y, + right.x, right.y, + 120, 250, 250, 50, 4.0f, 5000.0f, 1.0f); + } + } + if(!footPosRok) + TransformToNode(footPosR, PED_FOOTR); + + CVector adjustedFootPosR = footPosR; + adjustedFootPosR.z -= 0.1f; + adjustedFootPosR += 0.2f * forward; + + if (bDoBloodyFootprints) { + CVector2D top(forward * 0.26f); + CVector2D right(GetRight() * 0.1f); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosR, + top.x, top.y, + right.x, right.y, + 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); + + if (m_bloodyFootprintCountOrDeathTime <= 20) { + m_bloodyFootprintCountOrDeathTime = 0; + bDoBloodyFootprints = false; + } else { + m_bloodyFootprintCountOrDeathTime -= 20; + } + } + if (!isSkater) { + if (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) { + CVector2D top(forward * -0.26f); + CVector2D right(GetRight() * 0.14f); + + CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosR, + top.x, top.y, + right.x, right.y, + 120, 250, 250, 50, 4.0f, 5000.0f, 1.0f); } } } if (m_nSurfaceTouched == SURFACE_WATER) { + CRGBA rubberSmokeColor(255, 255, 255, 196); float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { -#ifdef PC_PARTICLE float particleSize = pedSpeed * 2.0f; if (particleSize < 0.25f) @@ -2489,19 +2597,23 @@ CPed::PlayFootSteps(void) CVector particlePos = GetPosition() + GetForward() * 0.3f; particlePos.z -= 1.2f; - CVector particleDir = m_vecMoveSpeed * 0.75f; + CVector particleDir = m_vecMoveSpeed * -0.75f; particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f); - CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, particlePos, particleDir, nil, 0.5f * particleSize, CRGBA(0,0,0,0), 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, rubberSmokeColor, 0, 0, 0, 0); + } - particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); - CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0); -#else - CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f; - CVector particleDir = m_vecMoveSpeed * 0.45f; - particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); - CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255)); -#endif + if (m_nPedState == PED_JUMP) { + CVector particlePos = GetPosition(); + particlePos.z -= 0.1f; + + CVector particleDir(0.0f, 0.075f, 0.0f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, particlePos, particleDir, nil, 0.005f, CRGBA(0, 0, 0, 0), 0, 0, 0, 0); + particleDir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + particleDir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + particleDir.z -= CGeneral::GetRandomNumberInRange(0.025f, 0.05f); + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, 0.5f, rubberSmokeColor, 0, 0, 0, 0); } } } @@ -3186,13 +3298,16 @@ CPed::SetObjective(eObjective newObj, void *entity) m_pNextPathNode = nil; bUsePedNodeSeek = false; - // TODO(Miami): Clean up old references + if (m_pedInObjective) + m_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective); + if (m_pLookTarget) + m_pLookTarget->CleanUpOldReference(&m_pLookTarget); - // m_pLookTarget = (CEntity*)entity; // duplicate + m_pLookTarget = (CEntity*)entity; m_pedInObjective = (CPed*)entity; m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); - m_pLookTarget = (CEntity*)entity; + // m_pLookTarget = (CEntity*)entity; // duplicate m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget); break; case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: @@ -3201,10 +3316,11 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING: case OBJECTIVE_HASSLE_CHAR: case OBJECTIVE_GUARD_ATTACK: - // TODO(Miami): Clean up old references - m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); + if (m_pedInObjective) + m_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective); m_pedInObjective = (CPed*)entity; + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); break; case OBJECTIVE_FOLLOW_CHAR_IN_FORMATION: @@ -3229,8 +3345,8 @@ CPed::SetObjective(eObjective newObj, void *entity) break; case OBJECTIVE_DESTROY_OBJECT: - // TODO(Miami): Clean up old references - + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); m_pPointGunAt = (CPed*)entity; if (entity) ((CEntity*)entity)->RegisterReference((CEntity**) &m_pPointGunAt); @@ -3928,7 +4044,6 @@ CPed::ClearAll(void) bIsPointingGunAt = false; bRenderPedInCar = true; bKnockedUpIntoAir = false; - bCrouchWhenScared = false; bKnockedOffBike = false; m_pCollidingEntity = nil; } @@ -4921,14 +5036,18 @@ CPed::RestorePreviousState(void) } } -// TODO(Miami): Clean up old references +// --MIAMI: Done void CPed::SetAimFlag(CEntity *to) { bIsAimingGun = true; bIsRestoringGun = false; + if (m_pLookTarget) + m_pLookTarget->CleanUpOldReference(&m_pLookTarget); m_pLookTarget = to; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); + if (m_pSeekTarget) + m_pSeekTarget->CleanUpOldReference(&m_pSeekTarget); m_pSeekTarget = to; m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); m_lookTimer = 0; @@ -5294,7 +5413,8 @@ CPed::SetAttack(CEntity *victim) return; } - // TODO(Miami): Clean up old referene + if (m_pSeekTarget) + m_pSeekTarget->CleanUpOldReference(&m_pSeekTarget); m_pSeekTarget = victim; if (m_pSeekTarget) m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); @@ -5939,9 +6059,9 @@ CPed::ChooseAttackPlayer(uint8 buttonPressure, bool fightWithWeapon) if (victimPed) { float adjustedAngleDiff = victimAngle - m_fRotationCur + DEGTORAD(30.0f); if (adjustedAngleDiff < 0.0f) - adjustedAngleDiff = adjustedAngleDiff + TWOPI; + adjustedAngleDiff += TWOPI; - int16 dir = floorf(adjustedAngleDiff / DEGTORAD(60.0f)); + int16 dir = Floor(adjustedAngleDiff / DEGTORAD(60.0f)); // Just focus on who we're fighting with, don't care peds on ground if (numPedsWeCanReach < 2 || fightWithWeapon) { @@ -6570,15 +6690,15 @@ CPed::PlayHitSound(CPed *hitTo) uint16 soundId; // And this is why second dimension is between 18 and 27. - if (hitTo->m_curFightMove <= FIGHTMOVE_GROUNDKICK || hitTo->m_curFightMove >= FIGHTMOVE_IDLE2NORM) { + if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) { + soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; + } else { if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) { soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT]; } else { soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT]; } - } else { - soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT]; } if (soundId != NO_SND) @@ -7754,6 +7874,9 @@ CPed::Fight(void) case FIGHTMOVE_IDLE2NORM: m_curFightMove = FIGHTMOVE_NULL; RestorePreviousState(); + + // FIX: Uninitialized + currentAssoc = nil; break; case FIGHTMOVE_IDLE: currentAssoc = nil; @@ -8477,8 +8600,9 @@ CPed::Wait(void) else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) { if (m_pedInObjective) { if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { - - // VC also calls CleanUpOldReference here for old LookTarget. + + if (m_pLookTarget) + m_pLookTarget->CleanUpOldReference(&m_pLookTarget); m_pLookTarget = m_pedInObjective; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); @@ -8955,7 +9079,7 @@ void CPed::FollowPath(void) { m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId]; - if (m_pathNodeTimer != 0 && CTimer::GetTimeInMilliseconds() > m_pathNodeTimer) { + if (m_pathNodeTimer > 0 && CTimer::GetTimeInMilliseconds() > m_pathNodeTimer) { RestorePreviousState(); ClearFollowPath(); m_pathNodeTimer = 0; @@ -10872,7 +10996,8 @@ CPed::ProcessControl(void) Say(SOUND_PED_TAXI_CALL); } } else { - // TODO(Miami): CleanUpOldReference + if (m_pLookTarget) + m_pLookTarget->CleanUpOldReference(&m_pLookTarget); m_pLookTarget = m_pedInObjective; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); @@ -11260,7 +11385,7 @@ CPed::ProcessControl(void) || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL) #endif ) { - if (m_nPedStateTimer <= 1000 && m_nPedStateTimer != 0) { + if (m_nPedStateTimer > 0 && m_nPedStateTimer <= 1000) { forceDir = GetPosition() - m_vecHitLastPos; } else { m_nPedStateTimer = 0; @@ -14097,356 +14222,29 @@ CPed::ProcessObjective(void) } case OBJECTIVE_KILL_CHAR_ON_FOOT: { - bool killPlayerInNoPoliceZone = false; if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) { SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle); break; } if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) { + bObjectiveCompleted = true; ClearLookFlag(); - bObjectiveCompleted = true; SetMoveAnim(); break; } - if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice()) - killPlayerInNoPoliceZone = true; + if (m_pedInObjective) { + int status; + if (GetWeapon()->IsTypeMelee()) + status = KillCharOnFootMelee(carOrOurPos, targetCarOrHisPos, distWithTarget); + else + status = KillCharOnFootArmed(carOrOurPos, targetCarOrHisPos, distWithTarget); - if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) { - if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee()) - bNotAllowedToDuck = true; - } else { - if (!m_pedInObjective->bInVehicle) { - if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) { - bNotAllowedToDuck = false; - bCrouchWhenShooting = false; - } else if (DuckAndCover()) { - break; - } - } else { - bNotAllowedToDuck = false; - bCrouchWhenShooting = false; - } - } - if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) { - SetMoveState(PEDMOVE_STILL); - break; - } - if (m_pedInObjective->IsPlayer()) { - CPlayerPed *player = FindPlayerPed(); - if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops - || player->m_pWanted->m_bIgnoredByEveryone - || m_pedInObjective->bIsInWater - || m_pedInObjective->m_nPedState == PED_ARRESTED) { - - if (m_nPedState != PED_ARREST_PLAYER) - SetIdle(); - - break; - } - } - CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); - float wepRange = wepInfo->m_fRange; - float wepRangeAdjusted; - if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { - wepRangeAdjusted = wepRange / 3.0f; - } else { - if (m_nPedState == PED_FIGHT) { - if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK)) - wepRange = 2.0f; - } else { - wepRange = 1.3f; - } - wepRangeAdjusted = wepRange; - } - if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) { - wepRangeAdjusted = 2.5f; - } - if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP - && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) { - SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); - break; - } - if (m_pedInObjective->m_fHealth <= 0.0f) { - bObjectiveCompleted = true; - bScriptObjectiveCompleted = true; - SetMoveAnim(); - break; - } - float distWithTargetSc = distWithTarget.Magnitude(); - if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { - CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle; - if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED - || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) { - SetIdle(); + if (status == WATCH_UNTIL_HE_DISAPPEARS) return; - } - SetLookFlag(vehOfTarget, false); - if (m_nPedState != PED_CARJACK) { - if (m_pedInObjective->m_nPedState != PED_ARRESTED) { - if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE - && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) { - - // I hope so - CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); - CVector maxShotPos = vehOfTarget->GetPosition() - ourHead; - maxShotPos.Normalise(); - maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead; - - CWorld::bIncludeDeadPeds = true; - CColPoint foundCol; - CEntity *foundEnt; - CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, - true, true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = false; - if (foundEnt == vehOfTarget) { - SetAttack(vehOfTarget); - m_pPointGunAt = vehOfTarget; - if (vehOfTarget) - vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt); - - SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); - if (distWithTargetSc <= m_distanceToCountSeekDone) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500)); - SetMoveState(PEDMOVE_STILL); - } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); - } - } - } - else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { - if (vehOfTarget) { - if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { - GoToNearestDoor(vehOfTarget); - } else { - m_vehEnterType = 0; - if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) { - m_vehEnterType = CAR_DOOR_LF; - } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) { - m_vehEnterType = CAR_DOOR_RF; - } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) { - m_vehEnterType = CAR_DOOR_LR; - } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) { - m_vehEnterType = CAR_DOOR_RR; - } - // Unused - // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType); - SetSeekCar(vehOfTarget, m_vehEnterType); - SetMoveState(PEDMOVE_RUN); - } - } - } - } - } - SetMoveAnim(); - break; - } - if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { - SetLookFlag(m_pedInObjective, false); - TurnBody(); - } - if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) { - if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() - || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) { - - ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective); - return; - } - } - if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) { - if (distWithTargetSc > wepRange - || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() - || m_pedInObjective->m_nPedState == PED_ARRESTED - || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f - || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) { - - if (m_pedInObjective->EnteringCar()) - wepRangeAdjusted = 2.0f; - - if (bUsePedNodeSeek) { - CVector bestCoords(0.0f, 0.0f, 0.0f); - m_vecSeekPos = m_pedInObjective->GetPosition(); - - if (!m_pNextPathNode) - FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); - - if (m_pNextPathNode) - m_vecSeekPos = m_pNextPathNode->GetPosition(); - - SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); - } else { - SetSeek(m_pedInObjective, wepRangeAdjusted); - } - bCrouchWhenShooting = false; - if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) { - if (wepRange <= 5.0f) { - if (m_pedInObjective->IsPlayer() - && FindPlayerPed()->m_bSpeedTimerFlag - && (IsGangMember() || m_nPedType == PEDTYPE_COP) - && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) { - GiveWeapon(WEAPONTYPE_COLT45, 1000); - SetCurrentWeapon(WEAPONTYPE_COLT45); - } - } else { - bStopAndShoot = true; - } - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - break; - } - bStopAndShoot = false; - SetMoveAnim(); + if (status == CANT_ATTACK) break; - } } - if (m_attackTimer < CTimer::GetTimeInMilliseconds() - && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { - if (bIsDucking) { - CAnimBlendAssociation *duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (duckAnim) { - duckAnim->blendDelta = -2.0f; - break; - } - bIsDucking = false; - } else if (wepRange <= 5.0f) { - SetMoveState(PEDMOVE_STILL); - SetAttack(m_pedInObjective); - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( - m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, - GetPosition().x, GetPosition().y); - SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f)); - SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f)); - bObstacleShowedUpDuringKillObjective = false; - - } else { - CVector target; - CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f); - if (m_pedInObjective->IsPed()) - m_pedInObjective->m_pedIK.GetComponentPosition(*(RwV3d *)&target, PED_MID); - else - target = m_pedInObjective->GetPosition(); - - target -= ourHead; - target.Normalise(); - target = target * wepInfo->m_fRange + ourHead; - - CWorld::bIncludeDeadPeds = true; - CEntity *foundEnt = nil; - CColPoint foundCol; - - CWorld::ProcessLineOfSight( - ourHead, target, foundCol, foundEnt, - true, true, true, false, true, false); - CWorld::bIncludeDeadPeds = 0; - if (foundEnt == m_pedInObjective) { - SetAttack(m_pedInObjective); - m_pPointGunAt = m_pedInObjective; - if (m_pedInObjective) - m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt); - - SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f)); - - int time; - if (distWithTargetSc <= wepRangeAdjusted) - time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f); - else - time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); - - SetAttackTimer(time); - bObstacleShowedUpDuringKillObjective = false; - - } else if (foundEnt) { - if (foundEnt->IsPed()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); - bObstacleShowedUpDuringKillObjective = false; - } else { - if (foundEnt->IsObject()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); - bObstacleShowedUpDuringKillObjective = true; - } else if (foundEnt->IsVehicle()) { - SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); - bObstacleShowedUpDuringKillObjective = true; - } else { - SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); - bObstacleShowedUpDuringKillObjective = true; - } - } - - m_fleeFrom = foundEnt; - m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom); - SetPointGunAt(m_pedInObjective); - } - } - } else { - if (!m_pedInObjective->m_pCurrentPhysSurface) - bStopAndShoot = false; - - if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { - - // This is weird... - if (bNotAllowedToDuck && bKindaStayInSamePlace) { - if (!bIsDucking) { - CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!duckAnim || duckAnim->blendDelta < 0.0f) { - CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f); - bIsDucking = true; - } - break; - } else { - CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); - if (!duckAnim || duckAnim->blendDelta < 0.0f) { - bIsDucking = false; - } else { - break; - } - } - } - if (bObstacleShowedUpDuringKillObjective) { - if (m_nPedType == PEDTYPE_COP) { - if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 - || m_fleeFrom && m_fleeFrom->IsObject()) { - wepRangeAdjusted = 6.0f; - } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) { - wepRangeAdjusted = 4.0f; - } else { - wepRangeAdjusted = 2.0f; - } - } else { - wepRangeAdjusted = 2.0f; - } - } - if (distWithTargetSc <= wepRangeAdjusted) { - SetMoveState(PEDMOVE_STILL); - bIsPointingGunAt = true; - if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) { - m_attackTimer = CTimer::GetTimeInMilliseconds(); - SetIdle(); - } - } else { - if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS - && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { - Say(SOUND_PED_ATTACK); - SetSeek(m_pedInObjective, wepRangeAdjusted); - bIsRunning = true; - } - } - } - } - - if (distWithTargetSc < 2.5f && wepRange > 5.0f - && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) { - - SetAttack(m_pedInObjective); - if (m_attackTimer < CTimer::GetTimeInMilliseconds()) { - int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f); - SetAttackTimer(time); - SetShootTimer(time - 500); - } - SetMoveState(PEDMOVE_STILL); - } - if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y); - SetMoveAnim(); break; } @@ -14475,6 +14273,8 @@ CPed::ProcessObjective(void) float safeDistance = 2.0f; if (m_pedInObjective->bInVehicle) safeDistance = 3.0f; + if (m_objective == OBJECTIVE_HASSLE_CHAR) + safeDistance = 1.0f; float distWithTargetSc = distWithTarget.Magnitude(); if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { @@ -14482,6 +14282,8 @@ CPed::ProcessObjective(void) bScriptObjectiveCompleted = true; if (m_nPedState != PED_ATTACK) { SetIdle(); + if (m_pLookTarget) + m_pLookTarget->CleanUpOldReference(&m_pLookTarget); m_pLookTarget = m_pedInObjective; m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); @@ -14490,6 +14292,18 @@ CPed::ProcessObjective(void) SetMoveState(m_pedInObjective->m_nMoveState); else SetMoveState(PEDMOVE_STILL); + + if (m_objective == OBJECTIVE_HASSLE_CHAR) { + Say(SOUND_PED_COP_REACTION); + m_pedInObjective->Say(SOUND_PED_UNK_126); + m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; + m_pedInObjective->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000; + SetObjective(OBJECTIVE_WANDER); + m_pedInObjective->SetObjective(OBJECTIVE_WANDER); + CVector2D dist = GetPosition() - m_pedInObjective->GetPosition(); + m_nPathDir = CGeneral::GetNodeHeadingFromVector(dist.x, dist.y); + m_pedInObjective->m_nPathDir = CGeneral::GetNodeHeadingFromVector(-dist.x, -dist.y); + } } else { SetSeek(m_pedInObjective, safeDistance); if (distWithTargetSc >= 5.0f) { @@ -15382,7 +15196,7 @@ CPed::ProcessObjective(void) #endif } if (bObjectiveCompleted - || m_objectiveTimer != 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { + || m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { RestorePreviousObjective(); if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer) m_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1; @@ -17877,11 +17691,8 @@ CPed::ScanForThreats(void) } if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags || m_nPedType == PEDTYPE_GANG5) { - - // TODO(Miami) - // if (m_threatEntity) - // m_threatEntity->CleanUpOldReference(&m_threatEntity); - + if (m_threatEntity) + m_threatEntity->CleanUpOldReference(&m_threatEntity); m_threatEntity = shooter; m_threatEntity->RegisterReference((CEntity**)&m_threatEntity); return CPedType::GetFlag(shooter->m_nPedType); @@ -18571,6 +18382,8 @@ CPed::UpdateFromLeader(void) m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget); TurnBody(); if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) { + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); m_pPointGunAt = m_threatEntity; if (m_threatEntity) m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt); @@ -20547,6 +20360,536 @@ CPed::PositionAttachedPed() } } +// --MIAMI: Done +int32 +CPed::KillCharOnFootMelee(CVector &ourPos, CVector &targetPos, CVector &distWithTarget) +{ + bool killPlayerInNoPoliceZone = false; + float distWithTargetSc = distWithTarget.Magnitude(); + CPlayerPed *victimPlayer = nil; + if (m_pedInObjective->IsPlayer()) + victimPlayer = (CPlayerPed*)m_pedInObjective; + + if (victimPlayer) { + if (CCullZones::NoPolice() + || m_pedInObjective->m_pCurrentPhysSurface + && m_pedInObjective->m_pCurrentPhysSurface != m_pCurrentPhysSurface + && distWithTargetSc < 5.f) { + + if (victimPlayer && victimPlayer->m_bSpeedTimerFlag && (IsGangMember() || m_nPedType == PEDTYPE_COP) + && CharCreatedBy != MISSION_CHAR) { + GiveWeapon(WEAPONTYPE_COLT45, 1000, 1); + SetCurrentWeapon(WEAPONTYPE_COLT45); + SetMoveState(PEDMOVE_STILL); + bStopAndShoot = true; + b158_8 = true; + return CANT_ATTACK; + } + killPlayerInNoPoliceZone = true; + } + } + bNotAllowedToDuck = false; + bStopAndShoot = false; + b158_8 = false; + if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) { + SetMoveState(PEDMOVE_STILL); + return CANT_ATTACK; + } + if (victimPlayer) { + CPlayerPed *player = FindPlayerPed(); + if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops + || player->m_pWanted->m_bIgnoredByEveryone + || m_pedInObjective->bIsInWater + || m_pedInObjective->m_nPedState == PED_ARRESTED) { + + if (m_nPedState != PED_ARREST_PLAYER) + SetIdle(); + + return CANT_ATTACK; + } + } + if (victimPlayer && m_nPedType != PEDTYPE_COP && CharCreatedBy != MISSION_CHAR + && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) { + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + + return CANT_ATTACK; + } + if (m_pedInObjective->m_fHealth <= 0.0f) { + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + return ATTACK_IN_PROGRESS; + } + bool canReachVictim = false; + uint32 endOfAttack = 0; + CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + + // Already calculated at the start + // float distWithTargetSc = distWithTarget.Magnitude(); + float wepRange = 0.3f; + float wepRangeAdjusted = wepInfo->m_fRange / 2.f; + + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK)) + wepRangeAdjusted -= 0.3f; + + if (distWithTargetSc <= 5.f && victimPlayer && !victimPlayer->m_bDrunkVisualsWearOff) { + + if (m_pedInObjective->EnteringCar() && wepRangeAdjusted > 2.f) { + m_vecSeekPos = m_pedInObjective->GetPosition(); + wepRangeAdjusted = 1.0f; + wepRange = 0.5f; + } else { + int8 attackDir = victimPlayer->FindMeleeAttackPoint(this, distWithTarget, endOfAttack); + if (attackDir == -1) { + m_vecSeekPos = victimPlayer->GetPosition(); + wepRange = 4.0f; + } else { + victimPlayer->GetMeleeAttackCoords(m_vecSeekPos, attackDir, wepRangeAdjusted); + distWithTargetSc = (m_vecSeekPos - GetPosition()).Magnitude(); + canReachVictim = true; + } + } + } else { + m_vecSeekPos = m_pedInObjective->GetPosition(); + wepRange = Max(0.8f, 0.9f * wepRangeAdjusted); + wepRangeAdjusted = 1.1f * wepRangeAdjusted; + if (victimPlayer && victimPlayer->m_bDrunkVisualsWearOff) + victimPlayer = nil; + } + + if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle; + + if (vehOfTarget){ + if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED + || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) { + SetIdle(); + return WATCH_UNTIL_HE_DISAPPEARS; + } + SetLookFlag(vehOfTarget, false); + + if (m_nPedState != PED_CARJACK) { + if (m_pedInObjective->m_nPedState != PED_ARRESTED) { + if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { + + if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { + GoToNearestDoor(vehOfTarget); + } else { + m_vehEnterType = 0; + if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) { + m_vehEnterType = CAR_DOOR_LF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) { + m_vehEnterType = CAR_DOOR_RF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) { + m_vehEnterType = CAR_DOOR_LR; + } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) { + m_vehEnterType = CAR_DOOR_RR; + } + // Unused + // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType); + SetSeekCar(vehOfTarget, m_vehEnterType); + SetMoveState(PEDMOVE_RUN); + } + } + } + } + } + return ATTACK_IN_PROGRESS; + } + if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { + SetLookFlag(m_pedInObjective, false); + if(m_nPedState == PED_IDLE || m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT) + TurnBody(); + } + if (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) { + float maxArrestDist = 1.5f; + if (((CCopPed*)this)->field_601) { + if (m_nPedState == PED_FALL) { + maxArrestDist = 3.5f; + } else if (m_nPedState != PED_DRAG_FROM_CAR) { + ((CCopPed*)this)->field_601 = 0; + } + } + + if (distWithTargetSc < maxArrestDist) { + if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() + || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) { + + ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective); + return WATCH_UNTIL_HE_DISAPPEARS; + } + } + } + + if (distWithTargetSc > wepRange && !bKindaStayInSamePlace && m_nPedState != PED_ATTACK && + (m_nPedState != PED_FIGHT || m_curFightMove == FIGHTMOVE_IDLE) && !killPlayerInNoPoliceZone) { + + bool goForward = false; + + if (m_nPedState == PED_FIGHT) { + if (canReachVictim) { + CVector attackAndVictimDist = m_vecSeekPos - m_pedInObjective->GetPosition(); + CVector victimFarness = attackAndVictimDist / wepRangeAdjusted; + CVector distVec = GetPosition() - m_pedInObjective->GetPosition(); + float distSqr = distVec.MagnitudeSqr(); + if (sq(wepRangeAdjusted) > distSqr && distSqr > 0.05f) { + distVec.Normalise(); + if (DotProduct2D(victimFarness, distVec) > Cos(DEGTORAD(30.f))) + goForward = true; + } + } + } + if (goForward) { + m_curFightMove = FIGHTMOVE_SHUFFLE_F; + CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_SH_BACK, 16.f)->SetFinishCallback(FinishFightMoveCB,this); + m_fightState = FIGHTSTATE_NO_MOVE; + m_fightButtonPressure = 0; + m_takeAStepAfterAttack = false; + + } else if (bUsePedNodeSeek && !canReachVictim) { + CVector bestCoords(0.0f, 0.0f, 0.0f); + + if (!m_pNextPathNode) + FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); + + if (m_pNextPathNode) + m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); + + SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); + } else { + if (canReachVictim) + SetSeek(m_vecSeekPos, wepRange); + else + SetSeek(m_pedInObjective, wepRange); + } + return ATTACK_IN_PROGRESS; + } + + if (m_attackTimer < CTimer::GetTimeInMilliseconds() + && distWithTargetSc < wepRangeAdjusted && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + + if (bIsDucking) { + CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!duckAnim) + duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); + if (!duckAnim) + duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH); + + if (duckAnim) { + duckAnim->flags |= ASSOC_DELETEFADEDOUT; + duckAnim->blendDelta = -4.0f; + } + bIsDucking = false; + return CANT_ATTACK; + } + + if (canReachVictim || !victimPlayer) { + SetMoveState(PEDMOVE_STILL); + SetAttack(m_pedInObjective); + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, + GetPosition().x, GetPosition().y); + SetShootTimer(CGeneral::GetRandomNumberInRange(0.f, 500.f)); + + int time; + if (endOfAttack <= CTimer::GetTimeInMilliseconds()) + time = CGeneral::GetRandomNumberInRange(100.0f, 1500.0f); + else + time = endOfAttack - CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(400.0f, 1500.0f); + + SetAttackTimer(time); + bObstacleShowedUpDuringKillObjective = false; + } + return ATTACK_IN_PROGRESS; + } else { + if (!m_pedInObjective->m_pCurrentPhysSurface && m_pCurrentPhysSurface && b158_8) { + b158_8 = false; + bStopAndShoot = false; + } + + if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + SetMoveState(PEDMOVE_STILL); + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) + StartFightAttack(0); + } + return ATTACK_IN_PROGRESS; + } +} + +// --MIAMI: Done +int32 +CPed::KillCharOnFootArmed(CVector &ourPos, CVector &targetPos, CVector &distWithTarget) +{ + bool killPlayerInNoPoliceZone = false; + if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice()) + killPlayerInNoPoliceZone = true; + + if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) { + if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee()) + bNotAllowedToDuck = true; + } else { + if (!m_pedInObjective->bInVehicle) { + if (m_pedInObjective->GetWeapon()->IsTypeMelee()) { + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + } else if (DuckAndCover()) { + return CANT_ATTACK; + } + } else { + bNotAllowedToDuck = false; + bCrouchWhenShooting = false; + } + } + if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) { + SetMoveState(PEDMOVE_STILL); + return CANT_ATTACK; + } + if (m_pedInObjective->IsPlayer()) { + CPlayerPed *player = FindPlayerPed(); + if (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops + || player->m_pWanted->m_bIgnoredByEveryone + || m_pedInObjective->bIsInWater + || m_pedInObjective->m_nPedState == PED_ARRESTED) { + + if (m_nPedState != PED_ARREST_PLAYER) + SetIdle(); + + return CANT_ATTACK; + } + } + if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP + && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) { + SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + + return CANT_ATTACK; + } + if (m_pedInObjective->m_fHealth <= 0.0f) { + bObjectiveCompleted = true; + bScriptObjectiveCompleted = true; + return CANT_ATTACK; + } + CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + float wepRange = wepInfo->m_fRange; + float wepRangeAdjusted = wepRange / 3.f; + + float distWithTargetSc = distWithTarget.Magnitude(); + if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + CVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle; + if (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED + || m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) { + SetIdle(); + return WATCH_UNTIL_HE_DISAPPEARS; + } + SetLookFlag(vehOfTarget, false); + if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) + TurnBody(); + + if (m_nPedState != PED_CARJACK) { + if (m_pedInObjective->m_nPedState != PED_ARRESTED) { + if (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) { + + SetAttack(vehOfTarget); + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); + + m_pPointGunAt = vehOfTarget; + if (vehOfTarget) + vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt); + + SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000)); + if (distWithTargetSc <= m_distanceToCountSeekDone) { + SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500)); + SetMoveState(PEDMOVE_STILL); + } else { + SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000)); + } + return ATTACK_IN_PROGRESS; + } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) { + if (vehOfTarget) { + if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) { + GoToNearestDoor(vehOfTarget); + } else { + m_vehEnterType = 0; + if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) { + m_vehEnterType = CAR_DOOR_LF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) { + m_vehEnterType = CAR_DOOR_RF; + } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) { + m_vehEnterType = CAR_DOOR_LR; + } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) { + m_vehEnterType = CAR_DOOR_RR; + } + // Unused + // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType); + SetSeekCar(vehOfTarget, m_vehEnterType); + SetMoveState(PEDMOVE_RUN); + } + } + } + } + } + return ATTACK_IN_PROGRESS; + } + if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) { + SetLookFlag(m_pedInObjective, false); + TurnBody(); + } + if (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) { + float maxArrestDist = 1.5f; + if (((CCopPed*)this)->field_601) { + if (m_nPedState == PED_FALL) { + maxArrestDist = 3.5f; + } else if (m_nPedState != PED_DRAG_FROM_CAR) { + ((CCopPed*)this)->field_601 = 0; + } + } + + if (distWithTargetSc < maxArrestDist) { + if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() + || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) { + + ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective); + return WATCH_UNTIL_HE_DISAPPEARS; + } + } + } + /* + if (distWithTargetSc > 0.1f) { + junk code + } */ + + if (m_shotTime != 0 && m_ceaseAttackTimer != 0) { + if (CTimer::GetTimeInMilliseconds() > m_ceaseAttackTimer + m_shotTime) { + ClearLookFlag(); + bObjectiveCompleted = true; + m_shotTime = 0; + return CANT_ATTACK; + } + } + + if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !bDuckAndCover && !killPlayerInNoPoliceZone) { + if (distWithTargetSc > wepRange + || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() + || m_pedInObjective->m_nPedState == PED_ARRESTED + || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f) { + + if (m_pedInObjective->EnteringCar()) + wepRangeAdjusted = 2.0f; + + if (bUsePedNodeSeek) { + CVector bestCoords(0.0f, 0.0f, 0.0f); + m_vecSeekPos = m_pedInObjective->GetPosition(); + + if (!m_pNextPathNode) + FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); + + if (m_pNextPathNode) + m_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed); + + SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); + } else { + SetSeek(m_pedInObjective, wepRangeAdjusted); + } + if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) { + bStopAndShoot = true; + b158_8 = true; + SetMoveState(PEDMOVE_STILL); + } else if (b158_8) { + bStopAndShoot = false; + b158_8 = false; + } + return ATTACK_IN_PROGRESS; + } + } + if (m_attackTimer < CTimer::GetTimeInMilliseconds() + && distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { + + if (bIsDucking && !bCrouchWhenShooting) { + CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN); + if (!duckAnim) + duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW); + if (!duckAnim) + duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_CROUCH); + + if (duckAnim) { + duckAnim->flags |= ASSOC_DELETEFADEDOUT; + duckAnim->blendDelta = -4.0f; + } + bIsDucking = false; + return CANT_ATTACK; + } + bObstacleShowedUpDuringKillObjective = false; + SetAttack(m_pedInObjective); + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); + + m_pPointGunAt = m_pedInObjective; + if (m_pedInObjective) + m_pedInObjective->RegisterReference((CEntity**)&m_pPointGunAt); + + SetShootTimer(CGeneral::GetRandomNumberInRange(900.0f, 1500.0f)); + + int time; + if (distWithTargetSc <= wepRangeAdjusted) + time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f); + else + time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); + + SetAttackTimer(time); + } else { + if (!m_pedInObjective->m_pCurrentPhysSurface && b158_8) { + b158_8 = false; + bStopAndShoot = false; + } + + if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { + if (bNotAllowedToDuck && bKindaStayInSamePlace && !bIsDucking && bCrouchWhenShooting) { + SetDuck(CGeneral::GetRandomNumberInRange(4000, 5000), false); + return CANT_ATTACK; + } + if (bObstacleShowedUpDuringKillObjective) { + if (m_nPedType == PEDTYPE_COP) { + if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 + || m_fleeFrom && m_fleeFrom->IsObject()) { + wepRangeAdjusted = 6.0f; + } else if (m_fleeFrom && m_fleeFrom->IsVehicle()) { + wepRangeAdjusted = 4.0f; + } else { + wepRangeAdjusted = 2.0f; + } + } else { + wepRangeAdjusted = 2.0f; + } + } + if (distWithTargetSc <= wepRangeAdjusted) { + SetMoveState(PEDMOVE_STILL); + bIsPointingGunAt = true; + if (m_nPedState != PED_AIM_GUN && !bDuckAndCover) { + m_attackTimer = CTimer::GetTimeInMilliseconds(); + SetIdle(); + } + } else { + if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS + && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { + Say(SOUND_PED_ATTACK); + SetSeek(m_pedInObjective, wepRangeAdjusted); + bIsRunning = true; + if (m_nPedType == PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops > 1) { + if (CGeneral::GetRandomNumber() & 1) + Say(SOUND_PED_GUNAIMEDAT3); + else + Say(SOUND_PED_GUNAIMEDAT2); + } + } + } + } + } + + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y); + + return ATTACK_IN_PROGRESS; +} + void PlayRandomAnimationsFromAnimBlock(CPed* ped, AssocGroupId animGroup, uint32 first, uint32 amount) { diff --git a/src/peds/Ped.h b/src/peds/Ped.h index c8621c82..b3d2f71c 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -30,6 +30,13 @@ struct PedAudioData int m_nMaxRandomDelayTime; }; +enum +{ + ATTACK_IN_PROGRESS, + CANT_ATTACK, + WATCH_UNTIL_HE_DISAPPEARS, +}; + enum eFormation { FORMATION_UNDEFINED, @@ -474,7 +481,7 @@ public: uint32 bNeverEverTargetThisPed : 1; uint32 bCrouchWhenScared : 1; uint32 bKnockedOffBike : 1; - //uint32 b158_8 + uint32 b158_8 : 1; uint32 b158_10 : 1; uint32 bBoughtIceCream : 1; uint32 b158_40 : 1; @@ -944,6 +951,8 @@ public: void ClearWaitState(void); void Undress(const char*); void Dress(void); + int32 KillCharOnFootMelee(CVector&, CVector&, CVector&); + int32 KillCharOnFootArmed(CVector&, CVector&, CVector&); bool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; } CWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; } diff --git a/src/peds/PedDebug.cpp b/src/peds/PedDebug.cpp index c3298461..0809581b 100644 --- a/src/peds/PedDebug.cpp +++ b/src/peds/PedDebug.cpp @@ -7,10 +7,11 @@ #include "Sprite.h" #include "Text.h" - +// TODO(Miami) static char ObjectiveText[][28] = { "No Obj", "Wait on Foot", + "Wait on Foot For Cop", "Flee on Foot Till Safe", "Guard Spot", "Guard Area", @@ -21,6 +22,8 @@ static char ObjectiveText[][28] = { "Flee Char on Foot Till Safe", "Flee Char on Foot Always", "GoTo Char on Foot", + "GoTo Char on Foot Walking", + "Hassle Char", "Follow Char in Formation", "Leave Car", "Enter Car as Passenger", @@ -42,10 +45,9 @@ static char ObjectiveText[][28] = { "Catch Train", "Buy IceCream", "Steal Any Car", + "Steal Any Mission Car", "Mug Char", -#ifdef VC_PED_PORTS - "Leave Car and Die" -#endif + "Leave Car and Die", }; static char StateText[][18] = { diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 98974bd3..cba01e31 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -35,7 +35,7 @@ CPlayerPed::~CPlayerPed() delete m_pWanted; } -// --MIAMI: Done except commented out things +// --MIAMI: Done CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) { m_fMoveSpeed = 0.0f; @@ -53,10 +53,8 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_nSpeedTimer = 0; m_bSpeedTimerFlag = false; - // TODO(Miami) - // if (pPointGunAt) - // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); - + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); m_pPointGunAt = nil; SetPedState(PED_IDLE); #ifndef FIX_BUGS @@ -69,13 +67,14 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; m_bHasLockOnTarget = false; - m_bDrunkVisualsWearOff = true; m_bCanBeDamaged = true; + m_bDrunkVisualsWearOff = false; m_fWalkAngle = 0.0f; m_fFPSMoveHeading = 0.0f; m_pMinigunTopAtomic = nil; m_fGunSpinSpeed = 0.0; m_fGunSpinAngle = 0.0; + m_nPadDownPressedInMilliseconds = 0; m_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1; unused1 = false; for (int i = 0; i < 6; i++) { @@ -85,17 +84,16 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) } m_nCheckPlayersIndex = 0; m_nPadUpPressedInMilliseconds = 0; - m_nPadDownPressedInMilliseconds = 0; idleAnimBlockIndex = CAnimManager::GetAnimationBlockIndex("playidles"); } -void CPlayerPed::ClearWeaponTarget() +// --MIAMI: Done +void +CPlayerPed::ClearWeaponTarget() { if (m_nPedType == PEDTYPE_PLAYER1) { - - // TODO(Miami) - // if (m_pPointGunAt) - // m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference(&m_pPointGunAt); m_pPointGunAt = nil; TheCamera.ClearPlayerWeaponMode(); @@ -1816,6 +1814,7 @@ CPlayerPed::PlayIdleAnimations(CPad *padUsed) } } +// --MIAMI: Done void CPlayerPed::RemovePedFromMeleeList(CPed *ped) { @@ -1828,6 +1827,100 @@ CPlayerPed::RemovePedFromMeleeList(CPed *ped) ped->m_attackTimer = 0; } +// --MIAMI: Done +void +CPlayerPed::GetMeleeAttackCoords(CVector& coords, int8 dir, float dist) +{ + coords = GetPosition(); + switch (dir) { + case 0: + coords.y += dist; + break; + case 1: + coords.x += Sqrt(3.f / 4.f) * dist; + coords.y += 0.5f * dist; + break; + case 2: + coords.x += Sqrt(3.f / 4.f) * dist; + coords.y -= 0.5f * dist; + break; + case 3: + coords.y -= dist; + break; + case 4: + coords.x -= Sqrt(3.f / 4.f) * dist; + coords.y -= 0.5f * dist; + break; + case 5: + coords.x -= Sqrt(3.f / 4.f) * dist; + coords.y += 0.5f * dist; + break; + default: + break; + } +} + +// --MIAMI: Done +int32 +CPlayerPed::FindMeleeAttackPoint(CPed *victim, CVector &dist, uint32 &endOfAttackOut) +{ + endOfAttackOut = 0; + bool thereIsAnEmptySlot = false; + int dirToAttack = -1; + for (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) { + CPed* pedAtThisDir = m_pMeleeList[i]; + if (pedAtThisDir) { + if (pedAtThisDir == victim) { + dirToAttack = i; + } else { + if (pedAtThisDir->m_attackTimer > endOfAttackOut) + endOfAttackOut = pedAtThisDir->m_attackTimer; + } + } else { + thereIsAnEmptySlot = true; + } + } + + // We don't have victim ped in our melee list + if (dirToAttack == -1 && thereIsAnEmptySlot) { + float angle = Atan2(-dist.x, -dist.y); + float adjustedAngle = angle + DEGTORAD(30.0f); + if (adjustedAngle < 0.f) + adjustedAngle += TWOPI; + + int wantedDir = Floor(adjustedAngle / DEGTORAD(60.0f)); + + // And we have another ped at the direction of victim ped, so store victim to next empty direction to it's real direction. (Bollocks) + if (m_pMeleeList[wantedDir]) { + int closestDirToPreferred = -99; + int preferredDir = wantedDir; + + for (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) { + if (!m_pMeleeList[i]) { + if (Abs(i - preferredDir) < Abs(closestDirToPreferred - preferredDir)) + closestDirToPreferred = i; + } + } + if (closestDirToPreferred > 0) + dirToAttack = closestDirToPreferred; + } else { + + // Luckily the direction of victim ped is already empty, good + dirToAttack = wantedDir; + } + + if (dirToAttack != -1) { + m_pMeleeList[dirToAttack] = victim; + victim->RegisterReference((CEntity**) &m_pMeleeList[dirToAttack]); + if (endOfAttackOut > CTimer::GetTimeInMilliseconds()) + victim->m_attackTimer = endOfAttackOut + CGeneral::GetRandomNumberInRange(1000, 2000); + else + victim->m_attackTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(500, 1000); + } + } + return dirToAttack; +} + #ifdef COMPATIBLE_SAVES #define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); #define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index 7ff95ff3..3b8d8fcb 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -34,7 +34,7 @@ public: bool m_bDrunkVisualsWearOff; // TODO(Miami): That may be something else CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree CPed *m_pPedAtSafePos[6]; - CPlayerPed* m_pMeleeList[6]; + CPed *m_pMeleeList[6]; // reachable peds at each direction(6) char unused1; int16 m_nCheckPlayersIndex; float m_fWalkAngle; //angle between heading and walking direction @@ -85,6 +85,8 @@ public: bool DoesPlayerWantNewWeapon(eWeaponType, bool); void PlayIdleAnimations(CPad*); void RemovePedFromMeleeList(CPed*); + void GetMeleeAttackCoords(CVector&, int8, float); + int32 FindMeleeAttackPoint(CPed*, CVector&, uint32&); static void SetupPlayerPed(int32); static void DeactivatePlayerPed(int32); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 6a3cdeaa..daafd27b 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -71,6 +71,7 @@ bool CHud::m_Wants_To_Draw_3dMarkers; wchar CHud::m_BigMessage[6][128]; int16 CHud::m_ItemToFlash; bool CHud::m_HideRadar; +int32 CHud::m_DrawClock; // These aren't really in CHud float CHud::BigMessageInUse[6]; @@ -519,7 +520,6 @@ void CHud::Draw() DrawZoneName */ if (m_pZoneName) { - float fZoneAlpha = 255.0f; if (m_pZoneName != m_pLastZoneName) { switch (m_ZoneState) { @@ -528,6 +528,8 @@ void CHud::Draw() m_ZoneToPrint = m_pZoneName; m_ZoneNameTimer = 0; m_ZoneFadeTimer = 0; + if (m_VehicleState == 1 || m_VehicleState == 2) + m_VehicleState = 3; break; case 1: case 2: @@ -542,19 +544,20 @@ void CHud::Draw() m_pLastZoneName = m_pZoneName; } + float fZoneAlpha = 255.0f; if (m_ZoneState) { switch (m_ZoneState) { case 1: + fZoneAlpha = 255.0f; m_ZoneFadeTimer = 1000; - if (m_ZoneNameTimer > 10000) { + if (m_ZoneNameTimer > 10000.0f) { m_ZoneFadeTimer = 1000; m_ZoneState = 3; } - fZoneAlpha = 255.0f; break; case 2: m_ZoneFadeTimer += CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer > 1000) { + if (m_ZoneFadeTimer > 1000.0f) { m_ZoneState = 1; m_ZoneFadeTimer = 1000; } @@ -562,7 +565,7 @@ void CHud::Draw() break; case 3: m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer < 0) { + if (m_ZoneFadeTimer < 0.0f) { m_ZoneState = 0; m_ZoneFadeTimer = 0; } @@ -570,7 +573,7 @@ void CHud::Draw() break; case 4: m_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds(); - if (m_ZoneFadeTimer < 0) { + if (m_ZoneFadeTimer < 0.0f) { m_ZoneFadeTimer = 0; m_ZoneToPrint = m_pLastZoneName; m_ZoneState = 2; @@ -582,11 +585,8 @@ void CHud::Draw() } -#ifndef HUD_ENHANCEMENTS - if (!m_Message[0]) { -#else - if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide zone name if wasted/busted text is displaying -#endif + if (!m_Message[0] && BigMessageInUse[1] == 0.0f && BigMessageInUse[2] == 0.0f) { + m_ZoneNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); @@ -606,11 +606,14 @@ void CHud::Draw() CFont::SetDropShadowPosition(2); CFont::SetDropColor(CRGBA(0, 0, 0, fZoneAlpha)); CFont::SetFontStyle(FONT_BANK); - CFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha)); - CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint); + + if (!CTheScripts::bPlayerIsInTheStatium) + CFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint); CFont::SetSlant(0.f); + } else { + m_ZoneState = 3; } } } @@ -628,6 +631,8 @@ void CHud::Draw() m_pVehicleNameToPrint = m_VehicleName; m_VehicleNameTimer = 0; m_VehicleFadeTimer = 0; + if (m_ZoneState == 1 || m_ZoneState == 2) + m_ZoneState = 3; break; case 1: case 2: @@ -723,23 +728,26 @@ void CHud::Draw() /* DrawClock */ - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetDropShadowPosition(2); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + if (m_DrawClock) { + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetPropOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); - AsciiToUnicode(sTemp, sPrint); + sprintf(sTemp, "%02d:%02d", CClock::GetHours(), CClock::GetMinutes()); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(CLOCK_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); + CFont::SetColor(CLOCK_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint); + } /* DrawOnScreenTimer @@ -1011,6 +1019,11 @@ void CHud::Draw() DrawSubtitles */ if (m_Message[0] && !m_BigMessage[2][0]) { + if (m_VehicleState != 0) + m_VehicleState = 3; + if (m_ZoneState != 0) + m_ZoneState = 3; + CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128)); @@ -1049,6 +1062,119 @@ void CHud::Draw() CFont::SetDropShadowPosition(0); } + /* + HelpMessage + */ + + if (m_HelpMessage[0]) { + if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) { + switch (m_HelpMessageState) { + case 0: + m_HelpMessageFadeTimer = 0; + m_HelpMessageState = 2; + m_HelpMessageTimer = 0; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); + m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; + + if (TheCamera.m_ScreenReductionPercentage == 0.0f) + DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); + break; + case 1: + case 2: + case 3: + case 4: + m_HelpMessageTimer = 5; + m_HelpMessageState = 4; + break; + default: + break; + } + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); + } + + float fAlpha = 225.0f; + + if (m_HelpMessageState != 0) { + switch (m_HelpMessageState) { + case 1: + fAlpha = 225.0f; + m_HelpMessageFadeTimer = 600; + if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { + m_HelpMessageFadeTimer = 600; + m_HelpMessageState = 3; + } + break; + case 2: + if (TheCamera.m_WideScreenOn) + break; + + m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer > 0) { + m_HelpMessageState = 1; + m_HelpMessageFadeTimer = 0; + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + case 3: + m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer < 0 || TheCamera.m_WideScreenOn) { + m_HelpMessageState = 0; + m_HelpMessageFadeTimer = 0; + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + case 4: + m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); + if (m_HelpMessageFadeTimer < 0) { + m_HelpMessageState = 2; + m_HelpMessageFadeTimer = 0; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); + } + fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; + break; + default: + break; + } + + if (!TheCamera.m_WideScreenOn) { + m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds(); + + CFont::SetAlphaFade(fAlpha); + CFont::SetCentreOff(); + CFont::SetPropOn(); + + if (CGame::germanGame) + CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f)); +#ifdef MORE_LANGUAGES + else if (CFont::IsJapanese()) + CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f); +#endif + else + CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); + + CFont::DrawFonts(); + // CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::SetJustifyOff(); +#ifdef MORE_LANGUAGES + if (CFont::IsJapanese()) + CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 34.0f - 4.0f)); + else +#endif + CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 34.0f - 4.0f)); + CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); + CFont::SetBackgroundOn(); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetDropShadowPosition(0); + CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); + CFont::PrintString(SCREEN_SCALE_X(34.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), CHud::m_HelpMessageToPrint); + CFont::SetAlphaFade(255.0f); + CFont::SetWrapx(SCREEN_WIDTH); + } + } + } else + m_HelpMessageState = 0; + /* DrawBigMessage */ @@ -1058,10 +1184,15 @@ void CHud::Draw() CFont::SetJustifyOff(); CFont::SetBackgroundOff(); CFont::SetBackGroundOnlyTextOff(); - CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); + if (CGame::frenchGame || CGame::germanGame) { + CFont::SetScale(SCREEN_SCALE_X(1.6f), SCREEN_SCALE_Y(1.8f)); + } else { + CFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f)); + } CFont::SetPropOn(); CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_SCALE_X(615.0f)); + CFont::SetCentreSize(SCREEN_SCALE_X(590.0f)); + CFont::SetColor(CRGBA(255, 255, 0, BigMessageAlpha[0])); // unused color CFont::SetFontStyle(FONT_HEADING); if (BigMessageX[0] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { @@ -1084,14 +1215,9 @@ void CHud::Draw() if (BigMessageAlpha[0] > 255.0f) BigMessageAlpha[0] = 255.0f; } - - CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[0])); -#ifdef FIX_BUGS - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]); -#else - CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[0]); -#endif - + CFont::DrawFonts(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[0])); CFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0])); CFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]); } @@ -1131,8 +1257,12 @@ void CHud::Draw() CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); } else { - BigMessageAlpha[2] = 0.0f; BigMessageInUse[2] = 1.0f; + BigMessageAlpha[2] = 0.0f; + if (CHud::m_VehicleState != 0) + CHud::m_VehicleState = 0; + if (CHud::m_ZoneState != 0) + CHud::m_ZoneState = 0; } } else { @@ -1143,108 +1273,13 @@ void CHud::Draw() void CHud::DrawAfterFade() { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); + RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + if (CTimer::GetIsUserPaused() || CReplay::IsPlayingBack()) return; - if (m_HelpMessage[0]) { - if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) { - switch (m_HelpMessageState) { - case 0: - m_HelpMessageFadeTimer = 0; - m_HelpMessageState = 2; - m_HelpMessageTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); - m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; - - if (TheCamera.m_ScreenReductionPercentage == 0.0f) - DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); - break; - case 1: - case 2: - case 3: - case 4: - m_HelpMessageTimer = 5; - m_HelpMessageState = 4; - break; - default: - break; - } - CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); - } - - float fAlpha = 225.0f; - - if (m_HelpMessageState != 0) { - switch (m_HelpMessageState) { - case 1: - fAlpha = 225.0f; - m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { - m_HelpMessageFadeTimer = 600; - m_HelpMessageState = 3; - } - break; - case 2: - m_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer > 0) { - m_HelpMessageState = 1; - m_HelpMessageFadeTimer = 0; - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - case 3: - m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer < 0) { - m_HelpMessageState = 0; - m_HelpMessageFadeTimer = 0; - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - case 4: - m_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds(); - if (m_HelpMessageFadeTimer < 0) { - m_HelpMessageState = 2; - m_HelpMessageFadeTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); - } - fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; - break; - default: - break; - } - - m_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds(); - - CFont::SetAlphaFade(fAlpha); - CFont::SetCentreOff(); - CFont::SetPropOn(); - - if (CGame::germanGame) - CFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f)); -#ifdef MORE_LANGUAGES - else if (CFont::IsJapanese()) - CFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f); -#endif - else - CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); - - CFont::SetColor(CRGBA(175, 175, 175, 255)); - CFont::SetJustifyOff(); -#ifdef MORE_LANGUAGES - if (CFont::IsJapanese()) - CFont::SetWrapx(SCREEN_SCALE_X(229.0f + 26.0f - 4.0f)); - else -#endif - CFont::SetWrapx(SCREEN_SCALE_X(200.0f + 26.0f - 4.0f)); - CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); - CFont::SetBackgroundOn(); - CFont::SetBackGroundOnlyTextOff(); - CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); - CFont::PrintString(SCREEN_SCALE_X(26.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), CHud::m_HelpMessageToPrint); - CFont::SetAlphaFade(255.0f); - } - } - for (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) { intro_text_line &line = CTheScripts::IntroTextLines[i]; if (line.m_Text[0] != '\0' && !line.m_bTextBeforeFade) { @@ -1315,12 +1350,10 @@ void CHud::DrawAfterFade() CFont::SetPropOn(); CFont::SetCentreSize(SCREEN_SCALE_X(600.0f)); CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString((SCREEN_WIDTH / 2) + SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[3]); - + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(ODDJOB_COLOR); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[3]); + CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f) - SCREEN_SCALE_Y(16.0f), m_BigMessage[3]); } if (!m_BigMessage[1][0] && m_BigMessage[4][0]) { @@ -1330,13 +1363,11 @@ void CHud::DrawAfterFade() CFont::SetCentreOn(); CFont::SetPropOn(); CFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); - - CFont::PrintString((SCREEN_WIDTH / 2) - SCREEN_SCALE_X(2.0f), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f) - SCREEN_SCALE_Y(2.0f), m_BigMessage[4]); - + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(ODDJOB_COLOR); - CFont::PrintString((SCREEN_WIDTH / 2), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(84.0f), m_BigMessage[4]); + CFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f), m_BigMessage[4]); } // Oddjob result @@ -1418,7 +1449,7 @@ void CHud::DrawAfterFade() CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f)); CFont::SetPropOn(); - CFont::SetRightJustifyWrap(SCREEN_SCALE_X(-500.0f)); + CFont::SetRightJustifyWrap(0.0f); CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_BANK); if (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) { @@ -1452,6 +1483,7 @@ void CHud::DrawAfterFade() BigMessageAlpha[1] = 0.0f; BigMessageX[1] = -60.0f; BigMessageInUse[1] = 1.0f; + m_ZoneState = 0; } } else { @@ -1541,6 +1573,7 @@ void CHud::Initialise() if (gpRocketSightTex == nil) gpRocketSightTex = RwTextureRead("siterocket", nil); + m_DrawClock = 1; CounterOnLastFrame = false; m_ItemToFlash = ITEM_NONE; OddJob2Timer = 0; @@ -1591,6 +1624,7 @@ void CHud::ReInitialise() { CounterOnLastFrame = false; m_ItemToFlash = ITEM_NONE; + m_DrawClock = 1; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; diff --git a/src/render/Hud.h b/src/render/Hud.h index c6aff654..9106f6fa 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -86,6 +86,7 @@ public: static wchar m_BigMessage[6][128]; static int16 m_ItemToFlash; static bool m_HideRadar; + static int32 m_DrawClock; // These aren't really in CHud static float BigMessageInUse[6]; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 329a8c9a..bd8545ee 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -922,9 +922,9 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL // prestep x1 and x2 to next integer y deltaA = CalcNewDelta(&poly[a1], &poly[a2]); - xA = deltaA * (ceilf(poly[a1].y) - poly[a1].y) + poly[a1].x; + xA = deltaA * (Ceil(poly[a1].y) - poly[a1].y) + poly[a1].x; deltaB = CalcNewDelta(&poly[b1], &poly[b2]); - xB = deltaB * (ceilf(poly[b1].y) - poly[b1].y) + poly[b1].x; + xB = deltaB * (Ceil(poly[b1].y) - poly[b1].y) + poly[b1].x; if(y != yend){ if(deltaB < 0.0f && (int)xB < xstart) @@ -969,7 +969,7 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL xstart = poly[b1].x; }while(y == (int)poly[b2].y); deltaB = CalcNewDelta(&poly[b1], &poly[b2]); - xB = deltaB * (ceilf(poly[b1].y) - poly[b1].y) + poly[b1].x; + xB = deltaB * (Ceil(poly[b1].y) - poly[b1].y) + poly[b1].x; if(deltaB < 0.0f && (int)xB < xstart) xstart = xB; } @@ -1005,7 +1005,7 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL xend = poly[a1].x; }while(y == (int)poly[a2].y); deltaA = CalcNewDelta(&poly[a1], &poly[a2]); - xA = deltaA * (ceilf(poly[a1].y) - poly[a1].y) + poly[a1].x; + xA = deltaA * (Ceil(poly[a1].y) - poly[a1].y) + poly[a1].x; if(deltaA >= 0.0f && (int)xA > xend) xend = xA; } diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index 0fd1e076..13f52334 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -1167,8 +1167,8 @@ CWaterLevel::RenderTransparentWater(void) { if (m_nRenderWaterLayers != 1 && m_nRenderWaterLayers != 6) { - float fMaskX = floorf(fCamX / 2.0f) * 2.0f; - float fMaskY = floorf(fCamY / 2.0f) * 2.0f; + float fMaskX = Floor(fCamX / 2.0f) * 2.0f; + float fMaskY = Floor(fCamY / 2.0f) * 2.0f; float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock]; float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - 400.0f; float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); @@ -1519,8 +1519,8 @@ CWaterLevel::RenderWavyMask(float fX, float fY, float fZ, return; #ifndef PC_WATER - float fUOffset = fX - (MAX_LARGE_SECTORS * (int32)floorf(fX / MAX_LARGE_SECTORS)); - float fVOffset = fY - (MAX_LARGE_SECTORS * (int32)floorf(fY / MAX_LARGE_SECTORS)); + float fUOffset = fX - (MAX_LARGE_SECTORS * (int32)Floor(fX / MAX_LARGE_SECTORS)); + float fVOffset = fY - (MAX_LARGE_SECTORS * (int32)Floor(fY / MAX_LARGE_SECTORS)); int32 nSecsX = (int32)((fX - fSectorX) / 2.0f); int32 nSecsY = (int32)((fY - fSectorY) / 2.0f); @@ -1870,8 +1870,8 @@ CWaterLevel::PreCalcWaterGeometry(void) if ( _IsColideWithBlock(BlockX, BlockY, nBlock) ) { - float fMaskX = floorf(fCamX / 2.0f) * 2.0f; - float fMaskY = floorf(fCamY / 2.0f) * 2.0f; + float fMaskX = Floor(fCamX / 2.0f) * 2.0f; + float fMaskY = Floor(fCamY / 2.0f) * 2.0f; float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET; float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); @@ -1994,8 +1994,8 @@ CWaterLevel::PreCalcWavyMask(float fX, float fY, float fZ, if ( COcclusion::IsAABoxOccluded(vecSectorPos, MAX_LARGE_SECTORS, MAX_LARGE_SECTORS, 4.0f) ) return false; - floorf(fX / MAX_LARGE_SECTORS); - floorf(fY / MAX_LARGE_SECTORS); + Floor(fX / MAX_LARGE_SECTORS); + Floor(fY / MAX_LARGE_SECTORS); RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); RpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0); @@ -2335,7 +2335,7 @@ _GetWindedWave(float fX, float fY) float y = WATER_HUGE_Y(fY); float fWindFactor (CWeather::WindClipped * 0.4f + 0.2f); - float fWave = Sin(( (x - floorf(x)) + (y - floorf(y)) ) * TWOPI + fAngle); + float fWave = Sin(( (x - Floor(x)) + (y - Floor(y)) ) * TWOPI + fAngle); return fWindFactor * fWave; } @@ -2380,8 +2380,8 @@ CWaterLevel::RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC float fVD = (PosD.y / 4) + _TEXTURE_WAKE_ADDV; #define MIN4(a, b, c, d) (Min((a), Min((b), Min((c), (d))))) - float fMinU = floorf(MIN4(fUA, fUB, fUC, fUD)); - float fMinV = floorf(MIN4(fVA, fVB, fVC, fVD)); + float fMinU = Floor(MIN4(fUA, fUB, fUC, fUD)); + float fMinV = Floor(MIN4(fVA, fVB, fVC, fVD)); #undef MIN4 float fZA = _GetWindedWave(PosA.x, PosA.y) + fWakeZ; diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index e1860179..f49f0d42 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -64,10 +64,6 @@ static psGlobalType PsGlobal; #undef MAKEPOINTS #define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l))) -#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } -#define JIF(x) if (FAILED(hr=(x))) \ - {debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;} - unsigned long _dwMemAvailPhys; RwUInt32 gGameState; @@ -830,9 +826,10 @@ void _InputInitialiseJoys() } } -void _InputInitialiseMouse() +long _InputInitialiseMouse(bool exclusive) { glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + return 0; } void psPostRWinit(void) @@ -847,7 +844,7 @@ void psPostRWinit(void) glfwSetJoystickCallback(joysChangeCB); _InputInitialiseJoys(); - _InputInitialiseMouse(); + _InputInitialiseMouse(false); if(!(vm.flags & rwVIDEOMODEEXCLUSIVE)) glfwSetWindowSize(PSGLOBAL(window), RsGlobal.maximumWidth, RsGlobal.maximumHeight); diff --git a/src/skel/platform.h b/src/skel/platform.h index cbb1be28..7f36d8b7 100644 --- a/src/skel/platform.h +++ b/src/skel/platform.h @@ -35,6 +35,7 @@ extern RwBool psInstallFileSystem(void); extern RwBool psNativeTextureSupport(void); extern void _InputTranslateShiftKeyUpDown(RsKeyCodes* rs); +extern long _InputInitialiseMouse(bool exclusive); // returns HRESULT on Windows actually extern void HandleExit(); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index ed423f30..cd75236c 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1602,7 +1602,6 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) return TRUE; } - /* ***************************************************************************** */ @@ -2003,7 +2002,7 @@ WinMain(HINSTANCE instance, if ( _InputInitialise() == S_OK ) { - _InputInitialiseMouse(); + _InputInitialiseMouse(false); _InputInitialiseJoys(); } @@ -2542,7 +2541,7 @@ HRESULT _InputInitialise() return S_OK; } -HRESULT _InputInitialiseMouse() +HRESULT _InputInitialiseMouse(bool exclusive) { HRESULT hr; @@ -2560,7 +2559,7 @@ HRESULT _InputInitialiseMouse() if( FAILED( hr = PSGLOBAL(mouse)->SetDataFormat( &c_dfDIMouse2 ) ) ) return hr; - if( FAILED( hr = PSGLOBAL(mouse)->SetCooperativeLevel( PSGLOBAL(window), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ) ) ) + if( FAILED( hr = PSGLOBAL(mouse)->SetCooperativeLevel( PSGLOBAL(window), (exclusive ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE) | DISCL_FOREGROUND ) ) ) return hr; // Acquire the newly created device @@ -2848,6 +2847,23 @@ void _InputShutdown() SAFE_RELEASE(PSGLOBAL(dinterface)); } +void _InputShutdownMouse() +{ + if (PSGLOBAL(mouse) == nil) + return; + + PSGLOBAL(mouse)->Unacquire(); + SAFE_RELEASE(PSGLOBAL(mouse)); +} + +BOOL _InputMouseNeedsExclusive(void) +{ + RwVideoMode vm; + RwEngineGetVideoModeInfo(&vm, GcurSelVM); + + return vm.flags & rwVIDEOMODEEXCLUSIVE; +} + BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) { HRESULT hr; diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 444e0760..eb32cb72 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -88,13 +88,14 @@ extern LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); HRESULT _InputInitialise(); -HRESULT _InputInitialiseMouse(); HRESULT CapturePad(RwInt32 padID); void _InputInitialiseJoys(); void _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num); HRESULT _InputAddJoys(); HRESULT _InputGetMouseState(DIMOUSESTATE2 *state); void _InputShutdown(); +void _InputShutdownMouse(); +BOOL _InputMouseNeedsExclusive(); BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key); BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index fc856de1..b0dc98ad 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -2523,7 +2523,7 @@ CAutomobile::PreRender(void) if(GetModelIndex() == MI_RCGOBLIN || GetModelIndex() == MI_RCRAIDER) radius = 3.0f; if(GetPosition().z - groundZ < radius) - HeliDustGenerate(this, radius-(GetPosition().z - groundZ), groundZ, ceilf(rnd)); + HeliDustGenerate(this, radius-(GetPosition().z - groundZ), groundZ, Ceil(rnd)); } CMatrix mat; From afc38c0d72966e7b7c421e29799655a76a2122b3 Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 22 Jul 2020 15:20:52 +0300 Subject: [PATCH 73/85] README 64-bit preparation --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3dcc9f58..71a982e9 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,6 @@ such that we have a working game at all times. ## Preparing the environment for building -Currently only building on VS2015/2017/2019 (Windows) and GCC (Linux) is tested. - - Clone the repo. - Run `git submodule init` and `git submodule update`. - Point GTA_III_RE_DIR environment variable to GTA3 root folder. @@ -30,8 +28,12 @@ Currently only building on VS2015/2017/2019 (Windows) and GCC (Linux) is tested. - On Windows: one of the `premake-vsXXXX.cmd` variants on root folder - On Linux: proceed to [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux). - There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/master/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across. +- **If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version) -> :information_source: **Rendering engine** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. + +> :information_source: **If you choose OpenAL(OAL) on Windows** You must read [Running OAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OAL-build-on-Windows). + +> :information_source: **Did you notice librw?** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. ## Contributing From 7e54a226e2e4b06d4e6e5e61a1d11ab4df8f61bb Mon Sep 17 00:00:00 2001 From: erorcun Date: Wed, 22 Jul 2020 15:21:51 +0300 Subject: [PATCH 74/85] README 64-bit preparation --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e96afb58..114c5e19 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,12 @@ Currently only building on VS2015/2017/2019 (Windows) and GCC (Linux) is tested. - On Windows: one of the `premake-vsXXXX.cmd` variants on root folder - On Linux: proceed to [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux). - There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/master/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across. +- **If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version) -> :information_source: **Rendering engine** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. + +> :information_source: **If you choose OpenAL(OAL) on Windows** You must read [Running OAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OAL-build-on-Windows). + +> :information_source: **Did you notice librw?** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. ## Contributing From 8117bcb56f00882c6cf4056431e82c9b7ef23308 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 23 Jul 2020 15:14:30 +0200 Subject: [PATCH 75/85] update librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 4883b03f..49ca300b 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 4883b03f2b8f060c04f054573e8f345878e93a11 +Subproject commit 49ca300b88c8c298e5811b41e753589ad2a4c367 From 732b7608299b1bbe40d65088498d9b37ab7d9265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 22 Jul 2020 14:56:28 +0300 Subject: [PATCH 76/85] 64-bit on Windows --- .appveyor.yml | 2 +- {libsndfile => libsndfile.32}/ChangeLog | 0 {libsndfile => libsndfile.32}/NEWS | 0 .../dist/libsndfile-1.dll | Bin .../include/sndfile.h | 0 .../include/sndfile.hh | 0 .../lib/libsndfile-1.def | 0 .../lib/libsndfile-1.lib | Bin .../lib/pkgconfig/sndfile.pc | 0 libsndfile.64/ChangeLog | 9764 +++++++++++++++++ libsndfile.64/NEWS | 199 + libsndfile.64/dist/libsndfile-1.dll | Bin 0 -> 1748992 bytes libsndfile.64/include/sndfile.h | 857 ++ libsndfile.64/include/sndfile.hh | 446 + libsndfile.64/lib/libsndfile-1.def | 47 + libsndfile.64/lib/libsndfile-1.lib | Bin 0 -> 9760 bytes libsndfile.64/lib/pkgconfig/sndfile.pc | 12 + {mpg123 => mpg123.32}/dist/libmpg123.dll | Bin {mpg123 => mpg123.32}/include/mpg123.h | 0 {mpg123 => mpg123.32}/lib/libmpg123.lib | Bin mpg123.64/dist/libmpg123.dll | Bin 0 -> 345088 bytes mpg123.64/include/fmt123.h | 159 + mpg123.64/include/mpg123.h | 1697 +++ mpg123.64/lib/libmpg123.lib | Bin 0 -> 33342 bytes premake5.lua | 62 +- src/audio/oal/aldlist.cpp | 3 +- src/audio/oal/stream.cpp | 9 +- src/control/Replay.cpp | 4 +- src/core/Camera.cpp | 6 +- src/core/Directory.cpp | 3 +- src/core/EventList.cpp | 6 +- src/core/EventList.h | 2 +- src/core/FileMgr.cpp | 16 +- src/core/FileMgr.h | 6 +- src/core/Frontend.cpp | 2 +- src/core/Game.cpp | 2 +- src/core/Pad.cpp | 2 +- src/core/Streaming.cpp | 19 +- src/core/Streaming.h | 10 +- src/core/common.h | 4 + src/peds/Ped.cpp | 2 +- src/peds/PedAttractor.cpp | 10 +- src/peds/PedAttractor.h | 4 +- src/peds/PedStats.cpp | 2 +- src/peds/PedType.cpp | 2 +- src/render/Fluff.cpp | 2 +- src/rw/NodeName.cpp | 2 +- src/rw/VisibilityPlugins.cpp | 4 +- src/rw/VisibilityPlugins.h | 6 +- src/skel/crossplatform.h | 2 +- src/skel/glfw/glfw.cpp | 2 +- src/skel/win/win.cpp | 47 +- src/skel/win/win.h | 8 +- src/text/Text.cpp | 26 +- src/text/Text.h | 14 +- src/weapons/WeaponInfo.cpp | 2 +- 56 files changed, 13368 insertions(+), 106 deletions(-) rename {libsndfile => libsndfile.32}/ChangeLog (100%) rename {libsndfile => libsndfile.32}/NEWS (100%) rename {libsndfile => libsndfile.32}/dist/libsndfile-1.dll (100%) rename {libsndfile => libsndfile.32}/include/sndfile.h (100%) rename {libsndfile => libsndfile.32}/include/sndfile.hh (100%) rename {libsndfile => libsndfile.32}/lib/libsndfile-1.def (100%) rename {libsndfile => libsndfile.32}/lib/libsndfile-1.lib (100%) rename {libsndfile => libsndfile.32}/lib/pkgconfig/sndfile.pc (100%) create mode 100644 libsndfile.64/ChangeLog create mode 100644 libsndfile.64/NEWS create mode 100644 libsndfile.64/dist/libsndfile-1.dll create mode 100644 libsndfile.64/include/sndfile.h create mode 100644 libsndfile.64/include/sndfile.hh create mode 100644 libsndfile.64/lib/libsndfile-1.def create mode 100644 libsndfile.64/lib/libsndfile-1.lib create mode 100644 libsndfile.64/lib/pkgconfig/sndfile.pc rename {mpg123 => mpg123.32}/dist/libmpg123.dll (100%) rename {mpg123 => mpg123.32}/include/mpg123.h (100%) rename {mpg123 => mpg123.32}/lib/libmpg123.lib (100%) create mode 100644 mpg123.64/dist/libmpg123.dll create mode 100644 mpg123.64/include/fmt123.h create mode 100644 mpg123.64/include/mpg123.h create mode 100644 mpg123.64/lib/libmpg123.lib diff --git a/.appveyor.yml b/.appveyor.yml index f4b28dd4..9e54f5ab 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,7 +24,7 @@ install: - cmd: >- git submodule update --init --recursive - premake5 vs2019 --with-librw --glewdir=%APPVEYOR_BUILD_FOLDER%/%GLEW_BASE% --glfwdir=%APPVEYOR_BUILD_FOLDER%/%GLFW_BASE% + premake5 vs2019 --with-librw --glewdir=%APPVEYOR_BUILD_FOLDER%/%GLEW_BASE% --glfwdir32=%APPVEYOR_BUILD_FOLDER%/%GLFW_BASE% build: project: build/reVC.sln diff --git a/libsndfile/ChangeLog b/libsndfile.32/ChangeLog similarity index 100% rename from libsndfile/ChangeLog rename to libsndfile.32/ChangeLog diff --git a/libsndfile/NEWS b/libsndfile.32/NEWS similarity index 100% rename from libsndfile/NEWS rename to libsndfile.32/NEWS diff --git a/libsndfile/dist/libsndfile-1.dll b/libsndfile.32/dist/libsndfile-1.dll similarity index 100% rename from libsndfile/dist/libsndfile-1.dll rename to libsndfile.32/dist/libsndfile-1.dll diff --git a/libsndfile/include/sndfile.h b/libsndfile.32/include/sndfile.h similarity index 100% rename from libsndfile/include/sndfile.h rename to libsndfile.32/include/sndfile.h diff --git a/libsndfile/include/sndfile.hh b/libsndfile.32/include/sndfile.hh similarity index 100% rename from libsndfile/include/sndfile.hh rename to libsndfile.32/include/sndfile.hh diff --git a/libsndfile/lib/libsndfile-1.def b/libsndfile.32/lib/libsndfile-1.def similarity index 100% rename from libsndfile/lib/libsndfile-1.def rename to libsndfile.32/lib/libsndfile-1.def diff --git a/libsndfile/lib/libsndfile-1.lib b/libsndfile.32/lib/libsndfile-1.lib similarity index 100% rename from libsndfile/lib/libsndfile-1.lib rename to libsndfile.32/lib/libsndfile-1.lib diff --git a/libsndfile/lib/pkgconfig/sndfile.pc b/libsndfile.32/lib/pkgconfig/sndfile.pc similarity index 100% rename from libsndfile/lib/pkgconfig/sndfile.pc rename to libsndfile.32/lib/pkgconfig/sndfile.pc diff --git a/libsndfile.64/ChangeLog b/libsndfile.64/ChangeLog new file mode 100644 index 00000000..62576177 --- /dev/null +++ b/libsndfile.64/ChangeLog @@ -0,0 +1,9764 @@ +2013-04-05 Erik de Castro Lopo + + * Makefile.am + Make sure checkprograms are built as part of 'make test-tarball'. + Closes: https://github.com/erikd/libsndfile/issues/37 + +2013-03-29 Erik de Castro Lopo + + * tests/dft_cmp.c + Fix a buffer overflow detected using GCC 4.8's -fsantiize=address runtime + error checking functionality. This was a buffer overflow in libsndfile's + test suite, not in the actual library code. + +2013-03-09 Erik de Castro Lopo + + * M4/gcc_version.m4 + Fix to work with OpenBSD's sed. + +2013-03-07 Erik de Castro Lopo + + * src/ALAC/alac_encoder.c + Patch from Michael Pruett (author of libaudiofile) to add correct byte + swapping for the mChannelLayoutTag field. + +2013-03-02 Erik de Castro Lopo + + * doc/bugs.html + Bugs should bt reported on the github issue tracker. + +2013-02-22 Erik de Castro Lopo + + * configure.ac + Improve sanitization of FLAC_CFLAGS value. + +2013-02-21 Erik de Castro Lopo + + * src/Makefile.am + Call python interpreter instead of using '#!' in script. Thanks to Jan + Stary for reporting this. + + * doc/index.html doc/FAQ.html + Make internal links relative. Patch from Jan Stary. + +2013-02-13 Erik de Castro Lopo + + * src/test_endswap.def src/test_endswap.tpl + Add tests for psf_put_be32() and psf_put_be64(). + + * src/sfendian.h src/test_endswap.(def|tpl) + Add functions psf_get_be(16|32|64) with tests. + These are needed for platforms where un-aligned accesses cause bus faults. + + * src/ALAC/ag_enc.c src/ALAC/alac_decoder.c + Replace all un-aligned accesses with safe alternatives. + Closes: https://github.com/erikd/libsndfile/issues/19 + +2013-02-12 Erik de Castro Lopo + + * src/sfendian.h + Add big endian versions of H2BE_16 and H2BE_32. + +2013-02-11 Erik de Castro Lopo + + * src/ALAC/ + Replace Apple endswap routines with ones from libsndfile. + + * merge from libsndfile-cart repo + Add ability to set and get a cart chunk with WAV and RF64. + Orignal patch by Chris Roberts required a number of + tweaks. + +2013-02-10 Erik de Castro Lopo + + * src/common.h + Bump SF_HEADER_LEN from 8192 to 12292, the value it was in the 1.0.25 + release. + +2013-02-09 Erik de Castro Lopo + + * src/alac.c + Fix segfault when encoding 8 channel files. + Closes: https://github.com/erikd/libsndfile/issues/30 + +2013-02-07 Erik de Castro Lopo + + * src/ALAC/EndianPortable.c + Fall back to compiler's __BYTE_ORDER__ for endian-ness detection. + +2013-02-06 Erik de Castro Lopo + + * configure.ac src/common.h src/ima_adpcm.c src/ms_adpcm.c src/paf.c + Drop tests for and #ifdef hackery for C99 struct flexible array feature. + libsndfile assumes the compiler supports most of the ISO C99 standard. + + * src/alac.c + Fix valgrind invalid realloc. Reported by nu774. + Closes: https://github.com/erikd/libsndfile/issues/31 + +2013-02-05 Erik de Castro Lopo + + * src/alac.c + The 'pakt' chunk header should now be written correctly. + Closes: https://github.com/erikd/libsndfile/issues/24 + + * configure.ac Makefile.am + Use PKG_INSTALLDIR when it exists. Suggestion from Christoph Thompson. + Closes: https://github.com/erikd/libsndfile/pull/28 + +2013-02-03 Erik de Castro Lopo + + * src/common.h src/caf.c + Read the ALAC 'pakt' header and stash the values. + + * src/sfendian.h + Add functions psf_put_be64() and psf_put_be32(). + + * src/alac.c + Start work on filling on the 'pakt' chunk header. + +2013-02-02 Erik de Castro Lopo + + * doc/FAQ.html + Add missing opening

tag. + + * src/alac.c + Increase ALAC_BYTE_BUFFER_SIZE to 82000. + +2013-01-27 Erik de Castro Lopo + + * doc/FAQ.html + Improve question #8. + +2013-01-02 Erik de Castro Lopo + + * src/ogg_opus.c + Add skeleton implementation so someone else can run with it. + +2012-12-12 Erik de Castro Lopo + + * src/common.h src/dwd.c src/rx2.c src/txw.c + Fix for compiling when configured with --enable-experimental. Thanks to + Eric Wong for reporting this. + +2012-12-01 Erik de Castro Lopo + + * configure.ac programs/sndfile-play.c + OS X 10.8 uses a different audio API to previous versions. + Fix compile failure on by disabling sndfile-play on this version. + Someone needs to supply code for the new API. + +2012-11-30 Erik de Castro Lopo + + * Octave/Makefile.am Octave/octave_test.sh + Fix 'make distcheck'. + +2012-10-13 Erik de Castro Lopo + + * M4/octave.m4 + Relax constraints on Octave version. + +2012-10-11 Erik de Castro Lopo + + * tests/utils.tpl + Improve compare_*_or_die() functions. + + * src/command.c + Fix bug reported by Keiler Florian. When reading short or int data from a + file containing float data, and setting SFC_SET_SCALE_FLOAT_INT_READ to + SF_TRUE would fail 3, 5, 7 and other channels counts. Problem was that + psf_calc_signal_max() was not calculating the signal max correctly. + Calculation of the signal max was failing because it was trying to read + a sample count that was not an integer multiple of the channel count. + + * tests/channel_test.c tests/Makefile.am tests/test_wrapper.sh.in + Add test for the above. + +2012-09-25 Erik de Castro Lopo + + * src/sndfile.hh + Added a constructor to allow the use of SF_VIRTUAL_IO. Patch from + DannyDaemonic : https://github.com/erikd/libsndfile/pull/20 + +2012-08-23 Erik de Castro Lopo + + * doc/octave.html + Fix link to octave.sourceforge.net. Thanks to IOhannes m zmoelnig. + + * src/mat5.c + Allow reading of mat5 files without a specified sample rate (default to + 44.1kHz). Thanks to IOhannes m zmoelnig. + +2012-08-19 Erik de Castro Lopo + + * src/paf.c + Error out if channel count is zero. Bug report from William ELla via + launchpad: + https://bugs.launchpad.net/ubuntu/+source/libsndfile/+bug/1036831 + +2012-08-04 Erik de Castro Lopo + + * configure.ac programs/sndfile-play.c + Patch from Ricci Adams to use OSX's AudioQueues on OSX 10.7 and greater. + +2012-07-09 Erik de Castro Lopo + + * programs/common.c + Accept "ogg" as a file extention for Ogg/Vorbis files. + +2012-06-22 Erik de Castro Lopo + + * src/flac.c + Make sure any previously allocated FLAC stream encoder and stream decoder + objects are deleted before a new one is allocated. + +2012-06-20 Erik de Castro Lopo + + * tests/utils.tpl + Rename gen_lowpass_noise_float() to gen_lowpass_signal_float() and add a + sine wave component so that different FLAC compression levels can be + tested. + + * src/sndfile.h.in doc/command.html + Add SFC_SET_COMPRESSION_LEVEL and document it. + + * src/sndfile.c + Catch SFC_SET_VBR_ENCODING_QUALITY command and implement it as the inverse + of SFC_SET_COMPRESSION_LEVEL. + + * src/ogg_vorbis.c src/flac.c + Implement SFC_SET_COMPRESSION_LEVEL command. + + * tests/test_wrapper.sh.in tests/compression_size_test.c + Use the compression_size_test on FLAC as well. + +2012-06-19 Erik de Castro Lopo + + * tests/ + Rename vorbis_test.c -> compression_size_test.c so it can be extended to + test FLAC as well. + +2012-06-18 Erik de Castro Lopo + + * src/broadcast.c + Fix a bug where a file with a 'bext' chunk with a zero length coding + history field would get corrupted when the file was closed. + Reported by Paul Davis of the Ardour project. + + * src/test_broadcast_var.c + Add a test for the above. + +2012-05-19 Erik de Castro Lopo + + * src/sndfile.c + sf_format_check: For SF_FORMAT_AIFF, reject endian-ness setttings for + non-PCM formats. + +2012-04-12 Erik de Castro Lopo + + * src/aiff.c + Fix regression in handling of odd length SSND chunks. + Thanks Olivier Tristan for the example file. + + * src/aiff.c src/wav.c + Exit parser loop when marker == 0. + +2012-04-04 Erik de Castro Lopo + + * doc/FAQ.html + Fix text. Thanks to Richard Collins. + +2012-03-24 Erik de Castro Lopo + + * src/caf.c + Exit parse loop if the marker is zero. Pass jump offsets as size_t instead + of int. + +2012-03-20 Erik de Castro Lopo + + * src/alac.c + Fix segfault when decoding CAF/ALAC file with more than 4 channels. + Fixes github issue #8 reported by Charles Van Winkle. + +2012-03-20 Erik de Castro Lopo + + * src/common.h + Change 'typedef SF_CHUNK_ITERATOR { ... } SF_CHUNK_ITERATOR' into 'struct + SF_CHUNK_ITERATOR { ... }' to prevent older compilers from complaining of + re-typedef-ing of SF_CHUNK_ITERATOR. + + * configure.ac + Fix if test for empty $prefix. + +2012-03-18 Erik de Castro Lopo + + * src/*.c tests/chunk_test.c + Reworking of custom chunk handling code. + - Memory for the iterator is now attached to the SF_PRIVATE struct and + freed one sf_close(). + - Rename sf_create_chunk_iterator() -> sf_get_chunk_iterator(). + - Each SNDFILE handle never has more than one SF_CHUNK_ITERATOR handle. + + * tests/string_test.c + Fix un-initialised char buffer. + +2012-03-17 Erik de Castro Lopo + + * src/*.c tests/chunk_test.c + Add improved handling of custom chunk getting and settings. Set of patches + from IOhannes m zmoelnig submitted via github pull request #6. + + * src/alac.c + Fix calculated frame count for files with zero block length. + +2012-03-13 Erik de Castro Lopo + + * src/avr.c + Remove double assignment to psf->endian. Thanks Kao Dome. + + * src/gsm610.c + Fix clearing of buffers. Thanks Kao Dome. + + * src/paf.c + Remove duplicate code. Thanks Kao Dome. + + * src/test_strncpy_crlf.c + Fix minor error in test. Thanks Kao Dome. + + * src/common.h src/*.c + Fix a bunch of valgrind errors. + +2012-03-13 Erik de Castro Lopo + + * src/sndfile.c + Fix typo in error string 'Uknown' -> 'Unknown'. + + * tests/fix_this.c + Fix potential int overflow. + +2012-03-10 Erik de Castro Lopo + + * src/alac.c + Fix decoding of last block so that the decode length is not a multiple of + the block length. Fixes github issue #4 reported by Charles Van Winkle. + + * src/sfconfig.h src/sfendian.h + Fix for MinGW cross compiling. Use '#if (defined __*66__)' instead of + '#if __*86__' because the MinGW header use '#ifdef __x86_64__'. + +2012-03-10 Erik de Castro Lopo + + * src/ALAC/ src/alac.c + Unify the interface between libsndfile and Apple ALAC codec. Regardless of + file bit width samples are now passed between the two as int32_t that are + justified towards the most significant bit. Without this modification, 16 + conversion functions would have been needed between the libsndfile (short, + int, float, double) types and the ALAC types (16, 20, 24 and 32 bit). With + this mod, only 4 are needed. + + * tests/floating_point_test.tpl tests/write_read_test.(def|tpl) + Add tests for 20 and 24 bit ALAC/CAF files. + + * src/command.c + Add ALAC/CAF to the SFC_GET_FORMAT_* commands. Fixes github issue #5. + + * configure.ac + Only use automake AM_SLIENT_RULES where supported. Thanks Dave Yeo. + + * tests/pipe_test.tpl + Disable tests on OS/2. Thanks Dave Yeo. + +2012-03-09 Erik de Castro Lopo + + * configure.ac src/sfconfig.h src/sfendian.h + For GCC, use inline assembler for endian swapping. This should work with + older versions of GCC like the one currently used in OS/2. + +2012-03-06 Erik de Castro Lopo + + * src/alac.c + Make sure temp file gets opened in binary mode. + + * src/alac.c src/common.c src/common.h + Fix function alac_write16_d(). + + * tests/floating_point_test.tpl + Add tests for 16 bit ALAC/CAF. + + * src/alac.c src/common.c src/common.h + Add support for 32 bit ALAC/CAF files. + + * tests/floating_point_test.tpl tests/write_read_test.tpl + Add tests for 32 bit ALAC/CAF files. + +2012-03-05 Erik de Castro Lopo + + * src/ + Refactor chunk storage so it work on big as well as little endian CPUs. + + * tests/chunk_test.c + Clean up error messages. + + * src/sfendian.h src/*.c + Rename endian swapping macros and add ENDSWAP_64 and BE2H_64. + + * configure.ac + Detect presence of header file. + + * src/sfendian.h + Use intrinsics (ie for MinGW) when is not + present. + Make ENDSWAP_64() work with i686-w64-mingw32 compiler. + + * src/ALAC/EndianPortable.c + Add support for __powerpc__. + + * src/sfconfig.h + Make sure HAVE_X86INTRIN_H is either 1 or 0. + +2012-03-03 Erik de Castro Lopo + + * src/ALAC/* + Big dump of code for Apple's ALAC file format. The copyyright to this code + is owned by Apple who have released it under an Apache style license. A few + small modifications were made to allow this to be integrated into libsndfile + but unfortunately the history of those changes were lost because they were + developed in a Bzr tree and during that time libsndfile moved to Git. + + * src/alac.c src/caf.c src/common.[ch] src/Makefile.am src/sndfile.h.in + src/sndfile.c + Hook new ALAC codec in. + + * programs/sndfile-convert.c + Add support for alac codec. + + * tests/write_read_test.tpl + Expand tests to cover ALAC. + +2012-03-02 Erik de Castro Lopo + + * src/aiff.c src/wav.c + Fix a couple of regressions from version 1.0.25. + +2012-03-01 Erik de Castro Lopo + + * src/strings.c + Minor refactoring. Make sure that the memory allocation size if always > 0 + to avoid undefined behaviour. + +2012-02-29 Erik de Castro Lopo + + * src/chunk.c + Fix buffer overrun introduced in recently added chunk logging. This chunk + logging has not yet made it to a libsndfile release version. Thanks to + Olivier Tristan for providing an example file. + + * src/wav.c + Fix handling of odd sized chunks which was causing the parser to lose some + chunks. Thanks to Olivier Tristan for providing an example file. + +2012-02-26 Erik de Castro Lopo + + * tests/util.tpl + Used gnu_printf format checking with mingw-w64 compiler. + + * tests/header_test.tpl + Printf format fixes. + +2012-02-25 Erik de Castro Lopo + + * M4/extra_pkg.m4 + Update PKG_CHECK_MOD_VERSION macro to add an AC_TRY_LINK step. This fix + allows the configure process to catch attempts to link incompatible + libraries. For example, linking 32 bit version of eg libFLAC to a 64 bit + version of libsndfile will now fail. Similarly, when cross compiling + libsndfile from Linux to Windows linking the Linux versions of a library + to the Windows version of libsndfile will now also fail. + + * src/sndfile.h.in src/sndfile.c src/common.h src/create_symbols_file.py + Add API function sf_current_byterate(). + + * src/dwvw.c src/flac.c src/ogg_vorbis.c src/sds.c + Add codec specific handlers for current byterate. + + * tests/floating_point_test.tpl + Add initial test for sf_current_byterate(). + +2012-02-24 Erik de Castro Lopo + + * src/common.[ch] + Add function psf_decode_frame_count(). + + * src/dwvw.c + Fix a termnation bug that caused the decoder to go into an infinite loop. + +2012-02-24 Erik de Castro Lopo + + * src/wav.c + Fix a regression in the WAV header parser. Thanks to Olivier Tristan for + bug report and the example file. + +2012-02-21 Erik de Castro Lopo + + * src/sndfile.c + Return error when SF_BROADCAST_INFO struct has bad coding_history_size. + Thanks to Alex Weiss for the report. + +2012-02-20 Erik de Castro Lopo + + * src/au.c src/flac.c src/g72x.c src/ogg_vorbis.c src/wav_w64.c + Don't fake psf->bytewidth values. + +2012-02-19 Erik de Castro Lopo + + * tests/string_test.c + Fix valgrind warnings. + + * src/common.h src/sndfile.c src/strings.c + Make string storage dynamically allocated. + + * src/sndfile.c + Add extra validation for custom chunk handling. + +2012-02-18 Erik de Castro Lopo + + * src/wav.c + Improve handlling unknown chunk types. Thanks to Olivier Tristan for sending + example files. + + * src/utils.tpl + Add GCC specific testing for format string parameters for exit_if_true(). + + * tests/*.c tests/*.tpl + Fix all printf format warnings. + + * programs/sndfile-play.c + Remove un-needed OSX include . Thanks jamesfmilne for github + issue #3. + + * tests/chunk_test.c + Extend custom chunk test. + +2012-02-12 Erik de Castro Lopo + + * src/wav.c + Jump over some more chunk types while parsing. + +2012-02-04 Erik de Castro Lopo + + * src/common.h src/strings.c + Change way strings are stored in SF_PRIVATE in preparation for dynamically + allocating the storage. + +2012-02-02 Erik de Castro Lopo + + * src/common.h src*.c + Improve encapsulation of string data in SF_PRIVATE. + +2012-02-01 Erik de Castro Lopo + + * src/common.h src*.c + Remove the buffer union from SF_PRIVATE. Most uses of this have been + replaced with a BUF_UNION that is allocated on the stack. + +2012-01-31 Erik de Castro Lopo + + * src/common.h src*.c + Rename logbuffer field of SF_PRIVATE to parselog and reduce its size. + Put the parselog buffer and the index inside a struct within SF_PRIVATE. + +2012-01-26 Erik de Castro Lopo + + * configure.ac + Fix typo, FLAC_CLFAGS -> FLAC_CFLAGS. Thanks to Jeremy Friesner. + +2012-01-21 Erik de Castro Lopo + + * src/sndfile.c src/ogg.c + Fix misleading error message when trying to create an SF_FORMAT_OGG file + with anything other than SF_FORMAT_FILE. Thanks to Charles Van Winkle for + the bug report. Github issue #1. + +2012-01-20 Erik de Castro Lopo + + * src/sndfile.c src/wav.c + Allow files opened in RDWR mode with string data in the tailer to be + extended. Thanks to Bodo for the patch. + + * tests/string_test.c + Add tests for the above changes (patch from Bodo). + +2012-01-09 Erik de Castro Lopo + + * src/aiff.c + Refactor reading of chunk size and use of psf_store_read_chunk(). + + * src/(caf|wav).c + Correct storing of chunk offset. + +2012-01-05 Erik de Castro Lopo + + * src/aiff.c src/wav.c src/common.h + Refactor common code into src/common.h. + + * src/caf.c + Make custom chunks work for CAF files. + + * tests/chunk_test.c tests/test_wrapper.sh.in + Test CAF files with custom chunks. + + * src/sndfile.c + Prevent psf->codec_close() being called more than once. + +2012-01-04 Erik de Castro Lopo + + * programs/sndfile-cmp.c + Catch the case where the second file has more frames than the first. + +2012-01-02 Erik de Castro Lopo + + * src/create_symbols_file.py + Add sf_set_chunk/sf_get_chunk_size/sf_get_chunk_data. + +2011-12-31 Erik de Castro Lopo + + * tests/chunk_test.c tests/Makefile.am + New test for custom chunks. + + * src/aiff.c src/chunk.c src/common.h src/sndfile.c + Make custom chunks work on AIFF files. + + * src/wav.c + Make custom chunks work on WAV files (includes refactoring). + +2011-11-12 Erik de Castro Lopo + + * src/sndfile.h.in src/common.h src/sndfile.c + Start working on setting/getting chunks. + +2011-11-24 Erik de Castro Lopo + + * src/binheader_writef_check.py src/create_symbols_file.py + Make it work for Python 2 and 3. Thanks Michael. + +2011-11-19 Erik de Castro Lopo + + * libsndfile.spec.in + Change field name 'URL' to 'Url'. + + * src/sndfile.h.in + Add SF_SEEK_SET/CUR/END. + +2011-11-05 Erik de Castro Lopo + + * src/id3.c + Fix a stack overflow that can occur when parsing a file with multiple + ID3 headers which would cause libsndfile to go into an infinite recursion + until it blew the stack. Thanks to Anders Svensson for supplying an example + file. + +2011-10-30 Erik de Castro Lopo + + * src/double64.c src/float32.c src/common.h + Make (float32|double_64)_(be|le)_read() functions const correct. + +2011-10-28 Erik de Castro Lopo + + * src/sfendian.h + Minor tweaking of types. Cast to ptr to correct final type rather void*. + + * programs/sndfile-play.c tests/utils.tpl + Fix compiler warnings with latest MinGW cross compiler. + +2011-10-13 Erik de Castro Lopo + + * src/file_io.c + Use the non-deprecated resource fork name on OSX. Thanks to Olivier Tristan. + +2011-10-12 Erik de Castro Lopo + + * src/wav.c + Jump over the 'olym' chunks when parsing. + +2011-10-06 Erik de Castro Lopo + + * tests/write_read_test.tpl + Remove windows only truncate() implementation. + +2011-09-04 Erik de Castro Lopo + + * src/sd2.c src/sndfile.c + Make sure 23 bit PCM SD2 files are readable/writeable. + + * tests/write_read_test.tpl + Add tests for 32 bit PCM SD2 files. + +2011-08-23 Erik de Castro Lopo + + * configure.ac + Use AC_SYS_LARGEFILE instead of AC_SYS_EXTRA_LARGEFILE as suggested by + Jan Willies. + +2011-08-07 Erik de Castro Lopo + + * configure.ac Makefile.am + Move ACLOCAL_AMFLAGS setup to Makefile.am. + +2011-07-15 Erik de Castro Lopo + + * doc/command.html + Merge two separate blocks of SFC_SET_VBR_ENCODING_QUALITY documentation. + + * src/paf.c + Replace ppaf24->samplesperblock with a compile time constant. + +2011-07-13 Erik de Castro Lopo + + * src/ogg_vorbis.c + Fix return value of SFC_SET_VBR_ENCODING_QUALITY command. + + * doc/command.html + Document SFC_SET_VBR_ENCODING_QUALITY, SFC_GET/SET_LOOP_INFO and + SFC_GET_INSTRUMENT. + + * NEWS README configure.ac doc/*.html + Updates for 1.0.25. + +2011-07-07 Erik de Castro Lopo + + * src/sfconfig.h + Add handling for HAVE_SYS_WAIT_H. + + * Makefile.am src/Makefile.am tests/Makefile.am + Add 'checkprograms' target. + +2011-07-05 Erik de Castro Lopo + + * src/common.h src/sndfile.c + Purge SF_ASSERT macro. Use standard C assert instead. + + * src/paf.c src/common.h src/sndfile.c + Fix for Secunia Advisory SA45125, heap overflow (heap gets overwritten with + byte value of 0) due to integer overflow if PAF file handler. + + * src/ima_adpcm.c src/ms_adpcm.c src/paf.c + Use calloc instead of malloc followed by memset. + + * tests/utils.tpl + Clean up use of memset. + +2011-07-05 Erik de Castro Lopo + + * src/ogg.c + Fix log message. + + * tests/format_check_test.c + Fix compiler warnings. + +2011-07-04 Erik de Castro Lopo + + * src/sndfile.c + Fix error message for erro code SFE_ZERO_MINOR_FORMAT. + + * tests/format_check_test.c + Add a test to for SF_FINFO format field validation. + + * src/ogg.c src/ogg_vorbis.c src/ogg.h src/ogg_pcm.c src/ogg_speex.c + src/common.h src/Makefile.am + Move vorbis specific code to ogg_vorbis.c, add new files for handling PCM + and Speex codecs in an Ogg container. The later two are only enabled with + ENABLE_EXPERIMENTAL_CODE config variable. + +2011-06-28 Erik de Castro Lopo + + * src/strings.c + Clean up and refactor storage of SF_STR_SOFTWARE. + +2011-06-23 Erik de Castro Lopo + + * src/sndfile.h.in doc/api.html + Fix definition of SF_STR_LAST and update SF_STR_* related docs. Thanks to + Tim van der Molen for the patch. + +2011-06-21 Erik de Castro Lopo + + * programs/sndfile-interleave.c + Fix handling of argc. Thanks to Marius Hennecke. + + * src/wav_w64.c + Accept broken WAV files with blockalign == 0. Thanks to Olivier Tristan for + providing example files. + + * src/wav.c + Jump over 'FLLR' chunks. + +2011-06-14 Erik de Castro Lopo + + * src/sndfile.h.in + Fix -Wundef warning due to ENABLE_SNDFILE_WINDOWS_PROTOTYPES. + + * configure.ac + Add -Wundef to CFLAGS. + + * src/ogg.c + Fix -Wunder warning. + +2011-05-18 Erik de Castro Lopo + + * configure.ac + Use int64_t instead of off_t when they are the same size. + + * src/Makefile.am tests/Makefile.am + Use check_PROGRAMS instead of noinst_PROGRAMS where appropriate. + +2011-05-08 Erik de Castro Lopo + + * src/wav.c + Don't allow unknown and/or un-editable chunks to prevent the file from being + opened in SFM_RDWR mode. + +2011-04-25 Erik de Castro Lopo + + * tests/format_check_test.c + Fix segfault in test program. + +2011-04-25 Erik de Castro Lopo + + * tests/format_check_test.c + New test program to check to make sure that sf_open() and sf_check_format() + agree as to what is a valid program. + + * tests/Makefile.am tests/test_wrapper.sh.in + Hook into build and test runner. + + * src/sndfile.c + Fix some sf_format_check() problems. Thanks to Charles Van Winkle for the + notification. + +2011-04-06 Erik de Castro Lopo + + * src/caf.c + Add validation to size of 'data' chunk and fix size of written 'data' + chunk. Thanks to Michael Pruett for reporting this. + +2011-03-28 Erik de Castro Lopo + + * src/* tests/* programs/* + Fix a bunch of compiler warnings with gcc-4.6. + +2011-03-25 Erik de Castro Lopo + + * tests/util.tpl + Add NOT macro to util.h. + + * src/strings.c + Fix handling of SF_STR_SOFTWARE that resulted in a segfault due to calling + strlen() on an unterminated string. Thanks to Francois Thibaud for reporting + this problem. + + * tests/string_test.c + Add test for SF_STR_SOFTWARE segfault bug. + + * configure.ac + Sanitize FLAC_CFLAGS value supplied by pkg-config which returns a value of + '-I${includedir}/FLAC'. However FLAC also provides an include file + which clashes with the Standard C header of the same name. The + solution is strip the 'FLAC' part off the end and include all FLAC headers + as . + + * configure.ac src/Makefile.am + Use non-recursive make in src/ directory. + +2011-03-23 Erik de Castro Lopo + + * NEWS README docs/*.html + Updates for 1.0.24 release. + +2011-03-22 Erik de Castro Lopo + + * configure.ac + Fix up usage of sed (should not assume GNU sed). + + * M4/add_(c|cxx)flags.m4 + Test flags in isolation. + + * tests/cpp_test.cc + Fix a broken test (test segfaults). Report by Dave Flogeras. + +2011-03-21 Erik de Castro Lopo + + * programs/common.[ch] + Add function program_name() which returns the program name minus the path + from argv [0]. + + * programs/*.c programs/Makefile.am + Use program_name() where appropriate. Fix build. + +2011-03-20 Erik de Castro Lopo + + * src/wav.c + For u-law and A-law files, write an 18 byte 'fmt ' chunk instead of a 16 + byte one. Win98 accepts files with a 16 but not 18 byte 'fmt' chunk. Later + version accept 18 byte but not 16 byte. + +2011-03-15 Erik de Castro Lopo + + * doc/FAQ.html + Add examples for question 12. + + * doc/libsndfile.css.in + Add tweaks for h4 element. + + * doc/api.html + Add documentation for virtual I/O functionality. Thanks to Uli Franke. + + * tests/util.tpl + Add static inline functions sf_info_clear() and sf_info_setup(). + + * tests/(alaw|dwvw|ulaw)_test.c + Use functions sf_info_clear() and sf_info_setup(). + +2011-03-08 Erik de Castro Lopo + + * configure.ac + Fail more gracefully if pkg-config is missing. Suggestion from Brian + Willoughby. + +2011-02-27 Erik de Castro Lopo + + * src/common.c + Use size_t instead of int for size params with varargs. + +2011-02-09 Erik de Castro Lopo + + * doc/index.html + Update supported platforms with more Debian platforms and Android. + +2011-01-27 Erik de Castro Lopo + + * src/sndfile.hh + Add an LPCWSTR version of the SndfileHandle constructor to the SndfileHandle + class definition. Thanks to Eric Eizenman for pointing out this was missing. + + * tests/cpp_test.cc + Add test for LPCWSTR version of the SndfileHandle constructor. + +2011-01-19 Erik de Castro Lopo + + * programs/sndfile-play.c + Remove cruft. + +2010-12-01 Erik de Castro Lopo + + * src/sndfile.hh + Add methods rawHandle() and takeOwnership(). Thanks to Tim Blechmann for + the patch. + + * tests/cpp_test.cc + Add tests for above two methods. Also supplied by Tim Blechmann. + +2010-11-11 Erik de Castro Lopo + + * doc/api.html + Add mention of use of sf_strerror() when sf_open() fails. + +2010-11-01 Erik de Castro Lopo + + * configure.ac + Make TYPEOF_SF_COUNT_T int64_t where possible. This may fix problems where + people are compiling on a 64 bit system with the GCC -m32 flag. + + * src/sndfile.h.in + Fix comments on sf_count_t. + +2010-10-26 Erik de Castro Lopo + + * src/aiff.c + Handle non-zero offset field in SSND chunk. Thanks to Michael Chinen. + +2010-10-20 Erik de Castro Lopo + + * configure.ac + Sed fix for FreeBSD. Thanks Tony Theodore. + +2010-10-14 Erik de Castro Lopo + + * shave.in M4/shave.m4 + Fix shave invocation of windres compiler. Thanks Damien Lespiau (upstream + shave author). + + * configure.ac M4/shave.m4 shave-libtool.in shave.in + Switch from shave to automake-1.11's AM_SILENT_RULES. + +2010-10-13 Erik de Castro Lopo + + * shave-libtool.in shave.in + Sync to upstream version. + + * src/rf64.c + More work to make the parser more robust and accepting of mal-formed files. + +2010-10-12 Erik de Castro Lopo + + * src/common.h + Add functions psf_strlcpy() and psf_strlcat(). + + * src/broadcast.c src/sndfile.c src/strings.c src/test_main.c + src/test_main.h src/test_strncpy_crlf.c + Use functions psf_strlcpy() and psf_strlcat() as appropriate. + + * tests/string_test.c + Add tests for SF_STR_GENRE and SF_STR_TRACKNUMBER. + + * src/rf64.c + Fix size of 'ds64' chunk when writing RF64. + +2010-10-10 Erik de Castro Lopo + + * programs/*.c + Add the libsndfile version to the usage message of all programs. + +2010-10-10 Erik de Castro Lopo + + * configure.ac src/version-metadata.rc.in src/Makefile.am + Add version string resources to the windows DLL. + + * doc/api.html + Update to add missing SF_FORMAT_* values. Closed Debian bug #545257. + + * NEWS README configure.ac doc/*.html + Updates for 1.0.23 release. + +2010-10-09 Erik de Castro Lopo + + * tests/pedantic-header-test.sh.in + Handle unusual values of CC environment variable. + + * src/rf64.c + Minor tweaks and additional sanity checking. + + * src/Makefile.am src/binheader_writef_check.py + Use python 2.6. + +2010-10-08 Erik de Castro Lopo + + * src/sndfile.hh + Add a missing 'inline' before a constructor defintion. + +2010-10-06 Erik de Castro Lopo + + * src/common.h + Add macro NOT. + + * src/rf64.c + Minor tweaks. + + * Makefile.am */Makefile.am + Add *~ to CLEANFILES. + +2010-10-05 Erik de Castro Lopo + + * src/sndfile.c + Fix a typo in the error string for SFE_OPEN_PIPE_RDWR. Thanks to Charles + Van Winkle for the report. + +2010-10-04 Erik de Castro Lopo + + * src/flac.c src/ogg.c src/sndfile.h.in src/strings.c src/wav.c + Add ability to read/write tracknumber and genre to flac/ogg/wav files. + Thanks to Matti Nykyri for the patch. + + * src/common.h src/broadcast.c src/strings.c + Add function psf_safe_strncpy() and use where appropriate. + +2010-10-04 Erik de Castro Lopo + + * NEWS README configure.ac doc/*.html + Updates for 1.0.22 release. + +2010-10-03 Erik de Castro Lopo + + * src/common.h src/broadcast.c src/rf64.c src/sndfile.c src/wav.c + Rewrite of SF_BROADCAST_INFO handling. + + * src/test_broadcast_var.c tests/command_test.c + Tweak SF_BROADCAST_INFO tests. + + * src/test_broadcast_var.c + Fix OSX stack check error. + +2010-09-30 Erik de Castro Lopo + + * src/sds.c + Set sustain_loop_end to 0 as suggested by Brian Lewis. + +2010-09-29 Erik de Castro Lopo + + * src/sds.c + Make sure the correct frame count gets written into the header. + + * tests/write_read_test.tpl + Don't allow SDS files to have a long frame count. + +2010-09-17 Erik de Castro Lopo + + * src/sds.c + Apply a pair of patches from Brian Lewis to fix the packet number location + and the checksum. + +2010-09-10 Erik de Castro Lopo + + * src/aiff.c src/file_io.c src/ogg.c src/rf64.c src/sndfile.c + src/strings.c src/test_audio_detect.c src/test_strncpy_crlf.c + src/wav.c tests/pcm_test.tpl + Fix a bunch of minor issues found using static analysis. + +2010-08-23 Erik de Castro Lopo + + * src/test_broadcast_var.c + New file containing tests for broadcast_set_var(). + + * src/Makefile.am src/test_main.[ch] + Hook test_broadcast_var.c into tests. + +2010-08-22 Erik de Castro Lopo + + * src/broadcast.c src/common.(c|h) + Move function strncpy_crlf() to src/common.c so the function can be tested + in isolation. + + * src/test_strncpy_crlf.c + New file. + + * src/Makefile.am src/test_main.[ch] + Hook test_strncpy_crlf.c into tests. + +2010-08-18 Erik de Castro Lopo + + * src/common.h + Move code around to make comments make sense. + + * src/broadcast.c + Add debugging code that is disabled by default. + +2010-08-02 Erik de Castro Lopo + + * src/flac.c + When the file meta data says the file has zero frames set psf->sf.frames + to SF_COUNT_MAX. Fixes Debian bug #590752. + + * programs/sndfile-info.c + Print 'unknown' if frame count == SF_COUNT_MAX. + +2010-06-27 Erik de Castro Lopo + + * src/sndfile.c + Only support writing mono SVX files. Multichannel SVX files are not + interleaved and there is no support infrastructure to cache and write + multiple channels to create a non-interleaved file. + + * src/file_io.c + Don't call close() on a file descriptor of -1. Thanks to Jeremy Friesner + for the bug report. + +2010-06-09 Erik de Castro Lopo + + * src/common.h + Add macro SF_ASSERT. + + * src/sndfile.c + Use SF_ASSERT to ensure sizeof (sf_count_t) == 8. + + * src/svx.c + Add support for reading and writing stereo SVX files. + +2010-05-07 Erik de Castro Lopo + + * configure.ac + When compiling with x86_64-w64-mingw32-gcc link with -static-libgcc flags. + + * programs/common.c programs/sndfile-metadata-set.c + Update metadata after the audio data is copied. Other minor fixes. Patch + from Marius Hennecke. + +2010-05-04 Erik de Castro Lopo + + * src/nist.c + Fix a regression reported by Hugh Secker-Walker. + + * src/api.html + Add comment about sf_open_fd() not working on Windows if the application + and the libsndfile DLL are linked to different versions of the Microsoft + C runtime DLL. + +2010-04-23 Erik de Castro Lopo + + * tests/pedantic-header-test.sh.in + Fix 'make distcheck'. + +2010-04-21 Erik de Castro Lopo + + * tests/pedantic-header-test.sh.in + New file to test whether sndfile.h can be compiled with gcc's -pedantic + flag. + + * configure.ac tests/test_wrapper.sh.in + Hook pedantic-header-test into test suite. + + * src/sndfile.h.in + Fix -pedantic warning. + +2010-04-19 Erik de Castro Lopo + + * programs/sndfile-salvage.c programs/Makefile.am + New program to salvage the audio data from WAV/WAVEX/AIFF files which are + greater than 4Gig in size. + +2010-04-09 Erik de Castro Lopo + + * programs/sndfile-convert.c + Fix valgrind warning. + +2010-04-06 Erik de Castro Lopo + + * programs/sndfile-cmp.c + When files differ in the PCM data, also print the difference offset. + Minor cleanup. + +2010-03-19 Erik de Castro Lopo + + * src/aiff.c + Don't use the 'twos' marker for 24 and 32 bit PCM, use 'in24' and 'in32' + instead. Thanks to Paul Davis (Ardour) for this suggestion. + +2010-02-28 Erik de Castro Lopo + + * configure.ac + Clean up configure report. + + * tests/utils.tpl + Add functions test_read_raw_or_die and test_write_raw_or_die. + + * tests/rdwr_test.(def|tpl) tests/Makefile.am + Add new test program and hook into build. + + * src/sndfile.c + Fix minor issues with sf_read/write_raw(). Bug reported by Milan Křápek. + + * tests/test_wrapper.sh.in + Add rdwr_test to the test wrapper script. + +2010-02-22 Erik de Castro Lopo + + * configure.ac + Remove -fpascal-strings from OSX's OS_SPECIFIC_CFLAGS. + + * programs/common.[ch] programs/sndfile-metadata-set.c + Apply a patch from Robin Gareus allowing the setting of the time reference + field of the BEXT chunk. + +2010-02-06 Erik de Castro Lopo + + * src/ima_adpcm.c + Add a fix from Jonatan Liljedahl to handle predictor overflow when decoding + IMA4. + +2010-01-26 Erik de Castro Lopo + + * src/sndfile.hh + Add a constructor which takes an existing file descriptor and then calls + sf_open_fd(). Patch from Sakari Bergen. + +2010-01-10 Erik de Castro Lopo + + * programs/sndfile-deinterleave.c programs/sndfile-interleave.c + Improve usage messages. + +2010-01-09 Erik de Castro Lopo + + * src/id3.c src/Makefile.am + Add new file src/id3.c and hook into build. + + * src/sndfile.c src/common.h + Detect and skip and ID3 header at the start of the file. + +2010-01-07 Erik de Castro Lopo + + * programs/common.c + Fix update_strings() copyright, comment, album and license are correctly + written. Thanks to Todd Allen for reporting this. + + * man/Makefile.am + Change GNU makeism to something more widely supported. Thanks to Christian + Weisgerber for reporting this. + + * configure.ac programs/Makefile.am programs/sndfile-play.c + Apply patch from Christian Weisgerber and Jacob Meuserto add support for + OpenBSD's sndio. + +2010-01-05 Erik de Castro Lopo + + * doc/api.html + Discourage the use of sf_read/write_raw(). + +2009-12-28 Erik de Castro Lopo + + * configure.ac + Test for Unix pipe() and waitpid() functions. + + * src/sfconfig.h tests/pipe_test.tpl + Disable pipe_test if pipe() and waitpid() aren't available. + +2009-12-16 Erik de Castro Lopo + + * configure.ac src/Makefile.am src/create_symbols_file.py + src/make-static-lib-hidden-privates.sh + Change name of generated file src/Symbols.linux to Symbols.gnu-binutils and + and use the same symbols file for other systems which use GNU binutils like + Debian's kfreebsd. + + * M4/shave.m4 shave.in + Update shave files from upstream. + +2009-12-15 Erik de Castro Lopo + + * man/sndfile-metadata-get.1 + Fix typo. + + * man/sndfile-interleave.1 man/Makefile.am + New man page. + +2009-12-13 Erik de Castro Lopo + + * src/ogg.c + When decoding to short or int, clip the decoded signal to [-1.0, 1.0] if + its too hot. Thanks to Dmitry Baikov for suggesting this. + + * NEWS README doc/*.html + Updates for 1.0.21. + +2009-12-09 Erik de Castro Lopo + + * programs/sndfile-jackplay.c man/sndfile-jackplay.1 + Remove these which will now be in found in the sndfile-tools package. + + * programs/Makefile.am man/Makefile.am + Remove build rules for sndfile-jackplay. + + * configure.ac + Remove detection of JACK Audio Connect Kit. + + * programs/sndfile-concat.c man/sndfile-concat.1 + Add new program with man page. + + * man/Makefile.am programs/Makefile.am + Hook sndfile-concat into build system. + +2009-12-08 Erik de Castro Lopo + + * tests/error_test.c + Don't terminate when sf_close() returns zero in error_close_test(). + It seems that Windows 7 behaves differently from earlier versions of + Windows. + +2009-12-03 Erik de Castro Lopo + + * configure.ac M4/*.m4 + Rename all custom macros from AC_* to MN_*. + + * programs/sndfile-interleave.c + Make it actually work. + +2009-12-02 Erik de Castro Lopo + + * doc/*.html configure.ac + Corrections and clarifications courtesy of Robin Forder. + + * programs/sndfile-convert.c programs/common.[ch] + Move some code from convert to common for reuse. + + * programs/sndfile-interleave.c programs/sndfile-interleave.c + Add new programs sndfile-interleave and sndfile-deinterleave. + + * programs/Makefile.am + Hook new programs into build. + +2009-12-01 Erik de Castro Lopo + + * src/create_symbols_file.py tests/stdio_test.c tests/win32_test.c + Minor OS/2 tweaks as suggested by David Yeo. + + * tests/multi_file_test.c + Fix file creation flags on windows. Thanks to Bruce Sharpe. + + * src/sf_unistd.h + Set all group and other file create permssions to zero. + + * tests/win32_test.c + Add a new test. + +2009-11-30 Erik de Castro Lopo + + * doc/print.css doc/*.html + Add a print stylesheet and update all HTML documents to reference it. + Thanks to Aditya Bhargava for suggesting this. + + * doc/index.html + Minor corrections. + +2009-11-29 Erik de Castro Lopo + + * sndfile.pc.in + Add a Libs.private entry to assist with static linking. + +2009-11-28 Erik de Castro Lopo + + * src/make-static-lib-hidden-privates.sh src/Makefile.am + Add a script to hide all non-public symbols in the libsndfile.a static + library. + +2009-11-22 Erik de Castro Lopo + + * tests/locale_test.c + Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES. + +2009-11-20 Erik de Castro Lopo + + * src/windows.c + Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES. + +2009-11-16 Erik de Castro Lopo + + * programs/sndfile-convert.c + Allow the program to read from stdin by specifying '-' on the command line + as the input file. + + * src/sndfile.h.in + Hash define ENABLE_SNDFILE_WINDOWS_PROTOTYPES to 1 for greater safety. + + * tests/virtual_io_test.c + Add a PAF/PCM_24 test and verify the file length is not negative + immediately after openning the file for write. + +2009-10-18 Erik de Castro Lopo + + * src/wav.c + When writing loop lengths, adjust the end position by one to make up for + Microsoft's screwed up spec. Thanks to Olivier Tristan for the patch. + +2009-10-14 Erik de Castro Lopo + + * src/flac.c + Apply patch from Uli Franke allowing FLAC files to be encoded at any sample + rate. + +2009-10-09 Erik de Castro Lopo + + * src/nist.c + Fix parsing of odd ulaw encoded file provided by Jan Silovsky. + + * configure.ac + Insist on libvorbis >= 1.2.3. Earlier verions have bugs that cause the + libsndfile test suite to fail on MIPS, PowerPC and others. + See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549899 + +2009-10-06 Erik de Castro Lopo + + * man/sndfile-convert.1 + Fix warning from Debian's lintian checks. + + * man/sndfile-cmp.1 man/sndfile-jackplay.1 man/sndfile-metadata-get.1 + man/Makefile.am + Add three new minimal manpages and hook into build. + +2009-10-05 Erik de Castro Lopo + + * tests/test_wrapper.sh.in + Don't run cpp_test on x86_64-w64-mingw32. + +2009-09-28 Erik de Castro Lopo + + * tests/utils.tpl + On windows, make sure the open() function doesn't get called with a third + parameter of 0 which fails for no good reason. Also make sure this third + parameter doesn't get called with S_IRGRP when compiling for windows because + Wine complains. + + * src/sndfile.hh + Add a SndfileHandle constructor for windows that takes a 'const wchar_t *' + string. + + * doc/FAQ.html + Add Q/A : I'm cross compiling libsndfile for another platform. How can I + run the test suite? + + * src/create_symbols_file.py src/Makefile.am + Add Symbols.static target, a list of symbols, one per line. + +2009-09-27 Erik de Castro Lopo + + * tests/test_wrapper.sh.in + Update to allow all tests to be gathered up into a testsuite tarball and + then be run using this script. + + * build-test-tarball.mk.in + Add a Make script to build a tarball of all the test binaries and the test + wrapper script. This is useful for cross compiling; you can build the + binaries, build test test tarball and transfer the test tarball to the + target machine for testing. + +2009-09-26 Erik de Castro Lopo + + * src/common.h src/*.c + Modify SF_FILE struct to allow it to carry either 8-bit or 16-bit strings + for the file path, directory and name. Fixes for this change throughout. + + * src/windows.c src/Makefile.am + New file defining new windows only public function sf_wchar_open() which + takes a 'const wchar_t *' string (LPCWSTR) for the file name parameter. + + * src/sndfile.h.in + Add SF_CHANNEL_MAP_ABISONIC_* entries. + Add windows only defintion for sf_wchar_open(). + + * src/create_symbols_file.py + Add sf_wchar_open() to the list of public symbols (windows only). + + * tests/locale_test.c + Add a wchar_test() to test sf_wchar_open(). + +2009-09-25 Erik de Castro Lopo + + * src/common.h src/*.c + Split file stuff into PSF_FILE struct within the SF_PRIVATE struct. + +2009-09-23 Erik de Castro Lopo + + * src/aiff.c src/voc.c + When a byte is needed, use unsigned char. + + * src/ima_oki_adpcm.c src/broadcast.c src/test_ima_oki_adpcm.c + Include sfconfig.h to prevent compile errors with MinGW compilers. + + * configure.ac + Remove AM_CONFIG_HEADER due to warnings from autoconf 2.64. + + * tests/locale_test.c + Update to work with xx_XX.UTF-8 style locales. Refactoring. + +2009-09-22 Erik de Castro Lopo + + * configure.ac + Set __USE_MINGW_ANSI_STDIO to 1 when compiling using MinGW compilers. + Remove unneeded AC_SUBST. + Report Host CPU/OS/vendor. + +2009-09-19 Erik de Castro Lopo + + * src/sndfile.c + Fix error message string. + + * src/flac.c + Add 88200 to the list of supported sample rates. + + * src/ogg.c + Fix compiler warning when using gcc-4.5.0. + + * programs/sndfile-info.c tests/utils.tpl + Remove WIN32 snprintf #define. + + * src/ima_adpcm.c + Fix minor bug in aiff_ima_encode_block. Thanks to Denis Fileev for finding + this. + +2009-09-16 Erik de Castro Lopo + + * src/caf.c + Use the correct C99 format specifier for int64_t. + + * M4/endian.m4 + Fix detection of CPU endian-ness when cross compiling. Thanks to Pierre + Ossman for the bug report. + + * src/caf.c src/sndfile.c + Fix reading and writing of PEAK chunks in CAF files. + + * tests/peak_chunk_test.c tests/test_wrapper.sh.in + Run peak_chunk_test on CAF files. + +2009-09-15 Erik de Castro Lopo + + * src/aiff.c src/wav.c + Use the correct C99 format specifier for int64_t. + +2009-08-30 Erik de Castro Lopo + + * src/rf64.c src/sndfile.c src/wav.c src/wav_w64.h + Apply a patch (massaged slightly) from Uli Franke adding handling of the + BEXT chunk in RF64 files. + + * tests/command_test.c + Update channel_map_test() function so WAV test passes. + + * src/rf64.c + Add channel mapping and ambisonic support. + + * src/sndfile.h + Add comments showing correspondance between libsndfile channel map + defintiions and those used by Apple and MS. + + Add handling of reading/writing channel map info. + + * tests/command_test.c tests/test_wrapper.sh.in + Update channel map tests. + +2009-07-29 Erik de Castro Lopo + + * src/common.h + Add function psf_isprint() a replacement for the standard C isprint() + function which ignores any locale settings and treats all input as ASCII. + + * src/(aiff|common|rf64|sd2|strings|svx|wav).c + Use psf_isprint() instead of isprint(). + +2009-07-13 Erik de Castro Lopo + + * src/command.c + Add string descriptions for SF_FORMAT_RF64 and SF_FORMAT_MPC2K. + +2009-06-30 Erik de Castro Lopo + + * programs/sndfile-play.c + Allow use of Open Sound System audio output under FreeBSD. + +2009-06-24 Erik de Castro Lopo + + * configure.ac + Add patch from Conrad Parker to add --disable-jack. + +2009-05-28 Erik de Castro Lopo + + * src/alaw.c src/float32.c src/htk.c src/pcm.c src/sds.c src/ulaw.c + Fix bugs where invalid files can cause a divide by zero error (SIGFPE). + Thanks to Sami Liedes for reporting this a Debian bug #530831. + +2009-05-26 Erik de Castro Lopo + + * src/chanmap.[ch] + New files for channel map decoding/encoding. + +2009-05-25 Erik de Castro Lopo + + * configure.ac src/sndfile.h.in + Fix MSVC definition of sf_count_t. + +2009-05-24 Erik de Castro Lopo + + * src/wav_w64.[ch] + Add wavex_channelmask to WAV_PRIVATE struct and add a function to convert + an array of SF_CHANNEL_MASK_* values into a bit mask for use in WAV files. + + * src/wav.c + Add ability to write the channel mask. + +2009-05-23 Erik de Castro Lopo + + * programs/sndfile-info.c + Add -c command line option to dump the channel map information. + + * src/wav_w64.c + Don't bail from parser if channel map bitmask is faulty. + + * src/common.h src/sndfile.c + Remove error code SFE_W64_BAD_CHANNEL_MAP which is not needed any more. + + * src/sndfile.c + On SFC_SET_CHANNEL_MAP_INFO pass the channel map command down to container's + command handler. + +2009-05-22 Erik de Castro Lopo + + * src/sndfile.h.in src/common.h src/sndfile.c src/wav_w64.c + Apply a patch from Lennart Poettering (PulseAudio) to allow reading of + channel data in WAV and W64 files. + Add a test for the above. + +2009-05-20 Erik de Castro Lopo + + * src/FAQ.html + Update the section about pre-compiled binaries for Win64. + +2009-05-14 Erik de Castro Lopo + + * src/common.h src/test_conversions.c + Be more careful when including so compiling on pre-C99 platforms + (hello Slowlaris) might actually work. + + * NEWS README doc/*.html + Updates for 1.0.20. + +2009-04-21 Erik de Castro Lopo + + * src/voc.c + Fix a bug whereby opening a specially crafted VOC file could result in a + heap overflow. Thanks to Tobias Klein (http://www.trapkit.de) for reporting + this issue. + + * src/aiff.c + Fix potential (heap) buffer overflow when parsing 'MARK' chunk. + +2009-04-12 Erik de Castro Lopo + + * tests/stdin_test.c + Check psf->error after opening file. + + * src/file_io.c + Fix obscure seeking bug reported by Hugh Secker-Walker. + + * tests/utils.tpl + Add check of sf_error to test_open_file_or_die(). + + * src/sndfile.c + Clear error if opening resource fork fails. + +2009-04-11 Erik de Castro Lopo + + * tests/alaw_test.c tests/locale_test.c tests/ulaw_test.c + Cleanup output. + +2009-03-25 Erik de Castro Lopo + + * src/float32.c + Fix f2s_clip_array. + +2009-03-24 Erik de Castro Lopo + + * src/float32.c + In host_read_f2s call convert instead of f2s_array. + + * src/ima_adpcm.c + Remove dead code. + + * src/test_ima_oki_adpcm.c examples/generate.c tests/dither_test.c + tests/dwvw_test.c tests/fix_this.c tests/generate.c + tests/multi_file_test.c + Minor fixes. + +2009-03-23 Erik de Castro Lopo + + * M4/shave.m4 shave.in + Pulled update from upstream. + +2009-03-19 Erik de Castro Lopo + + * doc/api.html + Add pointers to example programs in source code tarball. + +2009-03-17 Erik de Castro Lopo + + * src/common.h + Define SF_PLATFORM_S64 for non-gcc compilers with 'long long' type. + + * configure.ac + Add documentation for --disable-external-libs and improve error handling + for that option. + + * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py + Add public function sf_version_string. + + * tests/sfversion.c + Test function sf_version_string. + + * M4/shave.m4 shave-libtool.in shave.in + Add new files from 'git clone git://git.lespiau.name/shave'. + + * configure.ac + Enable shave. + + * src/Makefile.am src/binheader_writef_check.py Octave/* + Shave related tweaks. + +2009-03-15 Erik de Castro Lopo + + * src/common.h src/caf.c src/sndfile.c + Add SF_MAX_CHANNELS (set to 256) and use it. + + * src/sndfile.h.in + Check for either _MSCVER or _MSC_VER being defined. + +2009-03-04 Erik de Castro Lopo + + * tests/vorbis_test.c + Relax test slighly to allow test to pass on more CPUs etc. + +2009-03-03 Erik de Castro Lopo + + * configure.ac + Detect vorbis_version_string() correctly. + +2009-03-02 Erik de Castro Lopo + + * doc/index.html + Add a 'See Also' section with a link to sndfile-tools. + + * NEWS README doc/*.html + Updates for 1.0.19 release. + + * configure.ac + Fix --enable-external-libs logic. + +2009-03-01 Erik de Castro Lopo + + * src/aiff.c + Fix resource leak and potential read beyond end of buffer. + + * src/nist.c + Fix reading of header value sample_n_bytes. + + * src/sd2.c src/wav.c + Fix potential read beyond end of buffer. + + * src/sndfile.c src/svx.c + Check return values of file_io functions. + + * tests/win32_test.c + Fix resource leak. + + * configure.ac + Detect the presence/absence of vorbis_version_string() in libvorbis. + + * src/ogg.c + Only call vorbis_version_string() from libvorbis if present. + +2009-02-24 Erik de Castro Lopo + + * tests/win32_test.c + Don't use sprintf, even on windows. + + * src/aiff.c src/rf64.c src/wav.c + Eliminate dead code, more validation of data read from file. + +2009-02-22 Erik de Castro Lopo + + * src/ima_adpcm.c + Clamp values to a valid range before indexing ima_step_size array. + + * src/GSM610/*.c tests/*c programs/*.c src/audio_detect.c + Don't include un-needed headers. + + * programs/sndfile-info.c + Remove dead code. + + * tests/test_wrapper.sh.in + Add 'set -e' so the script exits on error. + + * src/test_ima_oki_adpcm.c + Fix read beyond end of array. + + * tests/win32_test.c + Add missing close on file descriptor. + + * src/nist.c programs/sndfile-metadata-set.c + Fix 'unused variable' warnings. + + * src/aiff.c + Fix potential memory leak in handling of 'MARK' chunk. + Remove un-needed test (unsigned > 0). + + * src/sd2.c + Improve handling of heap allocated buffer. + + * src/sndfile.c + Remove un-needed test (always true). + + * src/wav.c src/rf64.c + Ifdef out dead code that will be resurected some time in the future. + + * src/wav.c src/w64.c src/xi.c + Handle error return values from psf_ftell. + + * src/wav_w64.c + Fix handling and error checking of MSADPCM coefficient arrays. + + * regtest/*.c + Bunch of fixes. + + * src/test_file_io.c + Use snprintf instead of strncpy in test program. + +2009-02-21 Erik de Castro Lopo + + * src/sd2.c + Validate data before using. + + * src/caf.c + Validate channels per frame value before using, fixing a possible integer + overflow bug, leading to a possible heap overflow. Found by Alin Rad Pop of + Secunia Research (CVE-2009-0186). + +2009-02-20 Erik de Castro Lopo + + * Octave/octave_test.sh + Unset TERM environment variable and export LD_LIBRARY_PATH. + +2009-02-16 Erik de Castro Lopo + + * src/file_io.c + In windows code, cast LPVOID to 'char*' in printf. + +2009-02-15 Erik de Castro Lopo + + * M4/octave.m4 + Clear the TERM environment before evaluating anything in Octave. This works + around problems that might occur if a users TERM settings are incorrect. + Thanks to Rob Til Freedmen for helping to debug this. + + * src/wav.c + Handle four zero bytes as a marker within a LIST or INFO chunk. + Thanks to Rogério Brito for supplying an example file. + +2009-02-14 Erik de Castro Lopo + + * src/common.h src/*.c + Use C99 snprintf everywhere. + +2009-02-11 Erik de Castro Lopo + + * tests/test_wrapper.sh.in + New file to act as the template for the test wrapper script. + + * configure.ac + Generate tests/test_wrapper.sh from the template. + + * tests/Makefile.am + Replace all tests with a single invocation of the test wrapper script. + +2009-02-09 Erik de Castro Lopo + + * src/ogg.c + Record vorbis library version string. + + * configure.ac + Require libvorbis >= 1.2.2. + + * M4/endian.m4 + Fix bracketing of function for autoconf 2.63. Thanks to Richard Ash. + + * M4/octave.m4 M4/mkoctfile_version.m4 + Clean up AC_WITH_ARG usage using AC_HELP_STRING. + +2009-02-08 Erik de Castro Lopo + + * Octave/Makefile.am + Use $(top_buildir) instead of $(builddir) which may not be defined. + + * M4/octave.m4 + Improve logic and status reporting. + +2009-02-07 Erik de Castro Lopo + + * configure.ac AUTHORS NEWS README doc/*.html + Final tweaks for 1.0.18 release. + +2009-02-03 Erik de Castro Lopo + + * programs/sndfile-convert.c + Add 'htk' to the list of convert formats. + + * programs/sndfile-info.c + Simplify get_signal_max using SFC_CALC_SIGNAL_MAX command. + Increase size of files for which signal max will be calculated. + +2009-01-14 Erik de Castro Lopo + + * doc/index.html + Fix links for SoX and WavPlay. Thanks to Daniel Griscom. + +2009-01-11 Erik de Castro Lopo + + * programs/sndfile-metadata-get.c + Make valgrind clean. + Clean up temp string array usage. + Error out if trying to update coding history in RDWR mode. + +2009-01-10 Erik de Castro Lopo + + * doc/index.html + Fix links to versions of the LGPL. + +2008-12-14 Erik de Castro Lopo + + * tests/string_test.c + Add test for RDWR mode where the file ends up shorter than when it was + opened. + + * src/wav.c + Truncate the file on close for RDWR mode where the file ends up shorter + than when it was opened. + +2008-11-30 Erik de Castro Lopo + + * M4/add_cflags.m4 + Fix problem with quoting of '#include'. + + * M4/add_cxxflags.m4 configure.ac + Add new file M4/add_cxxflags.m4 and use it in configure.ac. + +2008-11-19 Erik de Castro Lopo + + * programs/sndfile-info.c + Apply patch from Conrad Parker to calculate and display total duration when + more than one file is dumped. + +2008-11-10 Erik de Castro Lopo + + * configure.ac src/Makefile.am + Tweaks to generation of Symbols files. + + * tests/win32_ordinal_test.c + Update tests for above changes. + +2008-11-06 Erik de Castro Lopo + + * programs/common.c + When merging broadcast info, make sure to clear the destination field + before copying in the new data. + + * programs/test-sndfile-metadata-set.py + Add test for the above. + + * src/broadcast.c + Fix checking of required coding_history_size. + +2008-10-28 Erik de Castro Lopo + + * tests/command_test.c + Add test to detect if coding history is truncated. + + * src/broadcast.c + Fix truncation of coding history. + +2008-10-27 Erik de Castro Lopo + + * tests/command_test.c + Add broadcast_coding_history_size test. + + * programs/*.[ch] + Use SF_BROADCAST_INFO_VAR to manipulate larger 'bext' chunks. + + * src/rf64.c + Add code to prevent infinite loop on malformed file. + + * src/common.h src/sndfile.c src/w64.c src/wav_w64.c + Rationalize and improve error handling when parsing 'fmt ' chunk. + + * M4/octave.m4 + Simplify and remove cruft. + Check for correct Octave version. + + * Octave/* + Reduce 3 C++ files to one, fix build for octave 3.0, fix build. + + * Octave/sndfile.cc Octave/PKG_ADD + Add Octave function sfversion which returns the libsndfile version that the + module is linked against. + + * Octave/Makefile.am + Bunch of build and 'make distcheck' fixes. + +2008-10-26 Erik de Castro Lopo + + * programs/common.c + Return 1 if SFC_SET_BROADCAST_INFO fails. + + * programs/test-sndfile-metadata-set.py + Update for new programs directory, exit on any error. + + * tests/error_test.c + Fix failure behaviour in error_number_test. + + * src/common.h src/sndfile.c + Add error number SFE_BAD_BROADCAST_INFO_SIZE. + + * src/* + Reimplement handling of broadcast extentioon chunk in WAV/WAVEX files. + + * src/broadcast.c + Fix generation of added coding history. + +2008-10-25 Erik de Castro Lopo + + * programs/sndfile-metadata-get.c programs/sndfile-info.c + Exit with non-zero on errors. + +2008-10-21 Erik de Castro Lopo + + * examples/sndfile-to-text.c examples/Makefile.am + Add a new example program and hook it into the build. + + * examples/ programs/ + Add a new directory programs and move sndfile-info, sndfile-play and other + real programs to the new directory, leaving example programs where they + were. + +2008-10-20 Erik de Castro Lopo + + * tests/Makefile.am + Automake 1.10 MinGW cross compiling fixes. + +2008-10-19 Erik de Castro Lopo + + * examples/sndfile-play.c + Remove call to deprecated function snd_pcm_sw_params_get_xfer_align. + Fix gcc-4.3 compiler warnings. + + * tests/command_test.c + Fix a valgrind warning. + + * tests/error_test.c tests/multi_file_test.c tests/peak_chunk_test.c + tests/pipe_test.tpl tests/stdio_test.c tests/win32_test.c + Fix gcc-4.3 compiler warnings. + +2008-10-17 Erik de Castro Lopo + + * src/broadcast.c + Fix termination of desitination string in strncpy_crlf. + When copying BROADCAST_INFO chunk, make sure destination gets correct line + endings. + + * examples/common.c + Fix copying of BROADCAST_INFO coding_history field. + +2008-10-13 Erik de Castro Lopo + + * tests/command_test.c + Add test function instrument_rw_test, but don't hook it into the testing + yet. + + * src/common.h src/command.c src/sndfile.c src/flac.c + Error code rationalization. + + * src/common.h src/sndfile.c + Set psf->error to SFE_CMD_HAS_DATA when adding metadata via sf_command() + fails due to psf->have_written being true. + + * doc/command.html + Document the SFC_GET/SET_BROADCAST_INFO comamnds. + +2008-10-10 Erik de Castro Lopo + + * tests/command_test.c + Improve error reporting when '\0' is found in coding history. + Fix false failure. + +2008-10-09 Erik de Castro Lopo + + * src/broadcast.c + Convert all coding history line endings to \r\n. + + * tests/command_test.c + Add test to make sure all line endings are converted to \r\n. + +2008-10-08 Erik de Castro Lopo + + * src/broadcast.c + Changed the order of coding history fields. + + * tests/command_test.c + Update bextch test to cope with previous change. + + * examples/common.c + Add extra length check when copying broadcast info data. + +2008-10-05 Erik de Castro Lopo + + * tests/utils.tpl tests/pcm_test.tpl + Update check_file_hash_or_die to use 64 bit hash. + + * tests/checksum_test.c tests/Makefile.am + Add new checksum_test specifically for lossy compression of headerless + files. + +2008-10-04 Erik de Castro Lopo + + * src/gsm610.c + Seek to psf->dataoffset before decoding first block. + + * src/sndfile.c + Fix detection of mpc2k files on big endian systems. + +2008-10-03 Erik de Castro Lopo + + * src/broadcast.c + Use '\r\n' newlines in Coding History as required by spec. + +2008-10-02 Erik de Castro Lopo + + * src/test_conversions.c + Use int64_t instead of 'long long'. + +2008-10-01 Erik de Castro Lopo + + * examples/sndfile-metadata-set.c + Remove --bext-coding-history-append command line option because it didn't + really make sense. + + * examples/sndfile-metadata-(get|set).c + Add usage messages. + + * examples/test-sndfile-metadata-set.py + Start work on test coding history. + +2008-09-30 Erik de Castro Lopo + + * README doc/win32.html + Bring these up to date. + + * src/aiff.c + Fix parsing of REX files. + +2008-09-29 Erik de Castro Lopo + + * src/file_io.c + Use intptr_t instead of long for return value of _get_osfhandle. + + * src/test_conversions.c src/test_endswap.tpl + Fix printing of int64_t values. + + * examples/sndfile-play.c + Fix win64 issues. + + * tests/win32_ordinal_test.c + Fix calling of GetProcAddress with ordinal under win64. + + * tests/utils.tpl + Fix win64 issues. + +2008-09-25 Erik de Castro Lopo + + * examples/* + Rename copy_data.[ch] to common.[ch]. Fix build. + Move code from sndfile-metadata-set.c to common.c. + + * examples/Makefile.am tests/Makefile.am regtest/Makefile.am + Clean paths. + +2008-09-19 Erik de Castro Lopo + + * doc/tutorial.html doc/Makefile.am + Add file doc/tutorial.html and hook into build/dist system. + +2008-09-14 Erik de Castro Lopo + + * examples/sndfile-metadata-set.c + Clean up handling of bext command line params. + +2008-09-13 Erik de Castro Lopo + + * src/w64.c + Add handling/skipping of a couple of new chunk types. + +2008-09-09 Erik de Castro Lopo + + * configure.ac + Add -funsigned-char to CFLAGS if the compiler supports it. + + * examples/sndfile-metadata-(get|set).c + Add handling for more metadata types. + +2008-09-04 Erik de Castro Lopo + + * src/common.h + Add macros SF_CONTAINER, SF_CODEC and SF_ENDIAN useful for splitting format + field of SF_INFO into component parts. + + * src/*.c + Use new macros everywhere it is appropriate. + +2008-09-02 Erik de Castro Lopo + + * examples/sndfile-bwf-set.c + Massive reworking. + +2008-08-24 Erik de Castro Lopo + + * examples/sndfile-bwf-set.c + Add --info-auto-create-date command line option. + + * examples/sndfile-metadata-set.c examples/sndfile-metadata-get.c + examples/Makefile.am examples/test-sndfile-bwf-set.py + Rename sndfile-bwf-(set|get).c to sndfile-metadata-(set|get).c. + Change command line args. + +2008-08-23 Erik de Castro Lopo + + * src/wav.c + Allow 'PAD ' chunk to be modified in RDWR mode. + + * src/sndfile.h.in src/sndfile.c + Add handling (incomplete) for SFC_SET_ADD_HEADER_PAD_CHUNK. + + * tests/Makefile.am tests/write_read_test.tpl tests/header_test.tpl + tests/misc_test.c + Add tests for RF64. + + * src/rf64.c + Fixes to make sure all tests pass. + + * tests/Makefile.am tests/string_test.c + Add string tests (not yet passing). + +2008-08-22 Erik de Castro Lopo + + * src/rf64.c + First pass at writing RF64 now working. + +2008-08-21 Erik de Castro Lopo + + * examples/sndfile-convert.c + Add SF_FORMAT_RF64 to format_map. + + * src/common.h src/sndfile.c + More RF64 support code. + + * examples/sndfile-bwf-set.c + Fix the month number in autogenerated date string and use hypen in date + instead of slash. + + * examples/test-sndfile-bwf-set.py + Update tests. + + * examples/sndfile-info.c + When called with -i or -b option, operate on all files on command line, not + just the first. + +2008-08-19 Erik de Castro Lopo + + * src/rf64.c + New file to handle RF64 (WAV like format supportting > 4Gig files). + + * src/sndfile.h.in src/common.h src/sndfile.c src/Makefile.am + Hook the above into build so hacking can begin. + + * src/pcm.c + Improve log message when pcm_init fails. + + * src/sndfile-info.c + Only calculate and print 'Signal Max' if file is less than 10 megabytes in + length. + +2008-08-18 Erik de Castro Lopo + + * tests/string_test.c + Polish string_multi_set_test. + + * src/wav.c + In RDWR mode, pad the header if necessary (ie LIST chunk has moved or + length has changed). + Minor fixes in wav_write_strings. + Write PAD chunk with default endian-ness, not a specific endian-ness. + + * examples/test-sndfile-bwf-set.py + Add Python script to test sndfile-bwf-set/get. + + * examples/sndfile-bwf-set.c + Clean up and fixes. + + * src/wav.c + Merge function wavex_write_header into wav_write_header, deleting about 70 + lines of code. + + * src/common.h + Double value of SF_MAX_STRINGS. + + * tests/string_test.c + Add string tests for WAVEX and RIFX files. + + * tests/command_test.c + Add broadcast test for WAVEX files. + +2008-08-17 Erik de Castro Lopo + + * tests/string_test.c + Add a new string_rdwr_test (currently failing for WAV). + Add a new string_multi_set_test (currently failing). + + * tests/command_test.c + Add new broadcast_rdwr_test (currently failing). + + * src/wav.c + Fix to WAV parser to allow 'bext' chunk to be updated in place. + In wav_write_tailer, seek to psf->dataend if its greater than zero. + + * src/sndfile.c + Make sure psf->have_written gets set correctly in mode SFM_RDWR. + + * configure.ac + Test for and gettimeofday. + + * src/common.c + Use gettimeofday() to initialize psf_rand_int32. + + * src/common.h src/sndfile.c + Add unique_id field to SF_PRIVATE struct. + + * src/common.h src/sndfile.c src/wav.c src/wav_w64.[ch] + Move wavex_ambisonic field from SF_PRIVATE struct to WAV_PRIVATE struct. + + * src/common.h src/strings.c + Add function psf_location_string_count. + +2008-08-16 Erik de Castro Lopo + + * configure.ac + Test for localtime and localtime_r. + + * examples/sndfile-convert.c + In function copy_metadata(), copy broadcast info if present. + + * examples/copy_data.[ch] examples/Makefile.am + Break some functionality out of sndfile-convert.c so it can be used in + examples/sndfile-bwf-set.c. + + * tests/utils.tpl + Add new function create_short_sndfile(). + + * examples/sndfile-bwf-set.c examples/sndfile-bwf-get.c + examples/Makefile.am + Add new files and hook into build. + +2008-08-11 Erik de Castro Lopo + + * src/sndfile.h.in + Fix comments. Patch from Mark Glines. + +2008-07-30 Erik de Castro Lopo + + * tests/misc_test.c + Use zero_data_test on Ogg/Vorbis files. + + * src/ogg.c + Fix segfault when closing an Ogg/Vorbis file that has been opened for write + but had no actual data written to it. Bug reported by Chinoy Gupta. + + * tests/Makefile.am + Make sure to run mist_test on Ogg/Vorbis files. + +2008-07-19 Erik de Castro Lopo + + * regtest/Makefile.am + Use SQLITE3_CFLAGS to locate sqlite headers. + +2008-07-10 Erik de Castro Lopo + + * doc/index.html doc/FAQ.html + Add notes about which versions of windows libsndfile works on. + +2008-07-03 Erik de Castro Lopo + + * tests/misc_test.c + Add a test for correct handling of Ambisonic files. Thanks to Fons + Adriaensen for the test. + + * src/wav.c src/wav_w64.c + Fix handling of Ambisonic files. Thanks to Fons Adriaensen for the patch. + +2008-06-29 Erik de Castro Lopo + + * configure.ac + Fix detection/enabling of external libs. + + * M4/extra_pkg.m4 M4/Makefile.am + Add m4 macro PKG_CHECK_MOD_VERSION which is a hacked version + PKG_CHECK_MODULES. The new macro prints the version number of the package + it is searching for. + +2008-06-14 Erik de Castro Lopo + + * src/aiff.c + Apply a fix from Axel Röbel where if the second loop in the instrument + chunk is none, the loop mode is written into the first loop. + +2008-05-31 Erik de Castro Lopo + + * src/test_float.c src/test_main.(c|h) src/Makefile.am + Add new file to test functions float32_(le|be)_(read|write) and + double64_(le|be)_(read|write). Hook into build and testsuite. + + * src/double64.c src/float32.c + Fix bugs in functions found by test added above. Thanks to Nicolas Castagne + for reporting this bug. + + * src/sndfile.h.in + Change time_reference_(low|high) entries of SF_BROADCAST_INFO struct to + unsigned. + + * examples/sndfile-info.c + Print out the BEXT time reference in a sensible format. + +2008-05-21 Erik de Castro Lopo + + * src/*.c + Fuzz fixes. + + * src/ogg.c + Add call to ogg_stream_clear to fix valgrind warning. + + * src/aiff.c + Fix x86_64 compile issue. + + * configure.ac src/Makefile.am src/flac.c src/ogg.c + Link to external versions of FLAC, Ogg and Vorbis. + + * tests/lossy_comp_test.c tests/ogg_test.c tests/string_test.c + tests/vorbis_test.c tests/write_read_test.tpl + Fix tests when configured with --disable-external-libs. + + * tests/external_libs_test.c tests/Makefile.am + Add new test and hook into build and test suite. + + * src/command.c + Use HAVE_EXTERNAL_LIBS to ensure that the SFC_GET_FORMAT_* commands return + the right data when external libs are disabled. + +2008-05-11 Erik de Castro Lopo + + * tests/write_read_test.tpl + Add a test for extending a file during write by seeking past the current + end of file. + + * src/sndfile.c + Allow seeking past end of file during write. + +2008-05-10 Erik de Castro Lopo + + * doc/api.html doc/command.html + Move all information about the sf_command function to command.html and add + a link from documentation of the sf_read/write_raw function to the + SFC_RAW_NEEDS_ENDSWAP command. + + * doc/index.html doc/FAQ.html doc/libsndfile.css + Minor documentation tweaks. + +2008-05-09 Erik de Castro Lopo + + * configure.ac + Add AM_PROG_CC_C_O. + +2008-04-27 Erik de Castro Lopo + + * tests/error_test.c + Add a test to make sure if file opened with sf_open_fd, and then the file + descriptor is closed, then sf_close will return an error code. Thanks to + Dave Flogeras for the bug report. + + * src/sndfile.c + Make sf_close return an error is the file descriptor is already closed. + +2008-04-19 Erik de Castro Lopo + + * configure.ac + Set object format to aout for OS/2. Thanks to David Yeo. + + * src/mpc2k.c src/sndfile.c src/sndfile.h.in src/common.h src/Makefile.am + Add ability to read MPC 2000 file. + + * tests/write_read_test.tpl tests/misc_test.c tests/header_test.tpl + tests/Makefile.am + Add tests for MPC 2000 file format. + + * examples/sndfile-convert.c + Allow conversion to MPC 2000 file format. + +2008-04-17 Erik de Castro Lopo + + * src/VORBIS/lib/codebook.c + Sync from upstream SVN. + + * autogen.sh configure.ac + Minor tweaks. + +2008-04-13 Erik de Castro Lopo + + * src/ogg.c + Add a patch that fixes finding the length in samples of an Ogg/Vorbis file. + The patch as supplied segfaulted and required many hours of debugging. + + * src/OGG/bitwise.c + Sync from upstream SVN. + +2008-04-09 Erik de Castro Lopo + + * src/aiff.c + Fix up handling of 'APPL' chunk. Thanks to Axel Röbel for bringing up + this issue. + +2008-04-06 Erik de Castro Lopo + + * tests/*.c + Add calls to sf_close() where needed. + + * tests/utils.tpl tests/multi_file_test.c + Always pass 0 as the third argument to open when OS_IS_WIN32. + +2008-04-03 Erik de Castro Lopo + + * src/test_* + Add files test_main.[ch]. + Collapse all tests into a single executable. + +2008-03-30 Erik de Castro Lopo + + * src/FLAC + Sync to upstream CVS. + +2008-03-25 Erik de Castro Lopo + + * src/common.h + Make SF_MIN and SF_MAX macros MinGW friendly. + + * examples/sndfile-(info|play).c + Use Sleep function from instead of _sleep. + + * tests/locale_test.c + Disable some tests when OS_IS_WIN32. + + * src/FLAC/src/share/replaygain_anal/replaygain_analysis.c + src/FLAC/src/share/utf8/utf8.c + MinGW fixes. + +2008-03-11 Erik de Castro Lopo + + * doc/FAQ.html + Tweaks to pcm16 <-> float conversion answer. + +2008-02-10 Erik de Castro Lopo + + * src/OGG + Sync to SVN upstream. + + * Makefile.am + Add 'DISTCHECK_CONFIGURE_FLAGS = --enable-gcc-werror'. + +2008-02-05 Erik de Castro Lopo + + * examples/sndfile-jackplay.c + Minor tweaks to warning message printed when compiled without libjack. + +2008-01-27 Erik de Castro Lopo + + * tests/peak_chunk_test.c + Improve read_write_peak_test to find more errors. Inspired by example + provided by Nicolas Castagne. + + * src/aiff.c + Another SFM_RDWR fix shown up by above test. + +2008-01-24 Erik de Castro Lopo + + * src/aiff.c + Fix reading of COMM encoding string. + + * src/chunk.c src/common.h src/Makefile.am + New file for storing and retrieving info about header chunks. Hook into + build. + + * src/aiff.c + Use new chunk logging to fix problem with AIFF in RDWR mode. + +2008-01-22 Erik de Castro Lopo + + * src/command.c + Add WVE to the list of major formats. + + * tests/aiff_rw_test.c + Fix error reporting. + +2008-01-21 Erik de Castro Lopo + + * src/common.[ch] + Add internal functions str_of_major_format, str_of_minor_format, + str_of_open_mode and str_of_endianness. + + * tests/write_read_test.tpl + Fix reporting of errors in new_rdwr_XXXX_test. + +2008-01-20 Erik de Castro Lopo + + * examples/sndfile-play.c + Apply patch from Yair K. to fix compiles with OSS v4. + + * src/common.h src/float32.c src/double64.c + Rename psf->float_enswap to psf->data_endswap. + + * src/sndfile.h.in src/sndfile.c src/pcm.c + Add command SFC_RAW_NEEDS_ENDSWAP. + + * tests/command.c + Add test for SFC_RAW_NEEDS_ENDSWAP. + + * doc/command.html + Document SFC_RAW_NEEDS_ENDSWAP. + + * tests/peak_chunk_test.c + Add test function read_write_peak_test. Thanks to Nicolas Castagne for the + bug report. + +2008-01-09 Erik de Castro Lopo + + * examples/sndfile-cmp.c + Add new example program contributed by Conrad Parker. + + * examples/Makefile.am + Hook into build. + + * doc/development.html + Change use or reconfigure.mk to autogen.sh. + +2008-01-08 Erik de Castro Lopo + + * tests/win32_test.c + Add another win32 test. + + * tests/util.tpl + Add function file_length_fd which wraps fstat. + + * tests/Makefile.am + Run the multi_file_test on AU files. + + * tests/multi_file_test.c + Use function file_length_fd() instead of file_length() to overcome stupid + win32 bug. Fscking hell Microsoft sucks so much. + +2008-01-05 Erik de Castro Lopo + + * src/sd2.c + Fix a rsrc parsing bug. Example file supplied by Uli Franke. + +2007-12-28 Erik de Castro Lopo + + * doc/index.html + Allow use of either LGPL v2.1 or LGPL v3. + + * tests/header_test.tpl + Add header_shrink_test from Axel Röbel. + + * src/wav.c + Add fix from Axel Röbel for writing files with float data but no peak + chunk (ie peak chunk gets removed after the file is opened). + + * src/aiff.c tests/header_test.tpl + Apply similar fix to above for AIFF files. + + * src/wav.c tests/header_test.tpl + Apply similar fix to above for WAVEX files. + + * src/command.c + Add Ogg/Vorbis to 'get format' commands. + +2007-12-16 Erik de Castro Lopo + + * src/ogg.c + Fix seeking on multichannel Ogg Vorbis files. Reported by Bodo. + Set the default encoding quality to 0.4 instead of 4.0 (Bodo again). + + * tests/ogg_test.c + Add stereo seek tests. + +2007-12-14 Erik de Castro Lopo + + * tests/ogg_test.c + Add a test (currently failing) for stereo seeking on Ogg Vorbis files. Test + case supplied by Bodo. + + * tests/utils.(def|tpl) + Add compare_XXX_or_die functions. + +2007-12-05 Erik de Castro Lopo + + * src/aiff.c + Fix a bug where ignoring ssnd_fmt.offset and ssnd_fmt.blocksize caused + misaligned reading of 24 bit data. Thanks to Uli Franke for reporting this. + +2007-12-03 Erik de Castro Lopo + + * src/vox_adpcm.c src/ima_oki_adpcm.[ch] src/Makefile.am + Merge in code from the vox-patch branch. Thanks to Robs for the patch + which fixes a long standing bug in the VOX codec. + +2007-12-01 Erik de Castro Lopo + + * examples/sndfile-convert.c + Fix handling of -override-sample-rate=X option. + +2007-11-25 Erik de Castro Lopo + + * src/ogg.c src/VORBIS + Merge in Ogg Vorbis support from John ffitch of the Csound project. + +2007-11-24 Erik de Castro Lopo + + * src/sndfile.c + Recognise files with 'vox6' extension as 6kHz OKI VOX ADPCM files. Also + recognise 'vox8' as and 'vox' as 8kHz files. + + * configure.ac + Detect libjack (JACK Audio Connect Kit). + + * examples/sndfile-jackplay.c examples/Makefile.am + Add new example program to play sound files using the JACK audio server. + Thanks to Jonatan Liljedahl for allowing this to be included. + +2007-11-21 Erik de Castro Lopo + + * doc/index.html + Update support table with SD2 and FLAC. + +2007-11-17 Erik de Castro Lopo + + * src/sndfile.c + Fix calculation of internal value psf->read_current when attempting to read + past end of audio data. + Remove redundant code. + + * tests/lossy_comp_test.c + Add read_raw_test to check that raw reads do not go past the end of the + audio data section. + Clean up error output messages. + + * src/sndfile.c + Add code to prevent sf_read_raw from reading past the end of the audio data. + + * tests/Makefile.am + Add the wav_pcm lossy_comp_test. + +2007-11-16 Erik de Castro Lopo + + * configure.ac src/Makefile.am src/create_symbols_file.py + More OS/2 fixes from David Yeo. + +2007-11-12 Erik de Castro Lopo + + * src/file_io.c tests/utils.tpl tests/benchmark.tpl + Improve handling of requirements for O_BINARY as suggested by Ed Schouten. + +2007-11-11 Erik de Castro Lopo + + * src/common.h + Fix symbol class when SF_MIN is nested inside SF_MAX or vice versa. + + * src/create_symbols_file.py + Add support for OS/2 contributed by David Yeo. + +2007-11-05 Erik de Castro Lopo + + * M4/gcc_version.m4 + Add macro AC_GCC_VERSION to detect GCC_MAJOR_VERSION and GCC_MINOR_VERSION. + + * configure.ac + Use AC_GCC_VERSION to work around gcc-4.2 inline warning stupidity. + See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33995 + Use -fgnu-inline to prevent stupid warnings. + +2007-11-03 Erik de Castro Lopo + + * tests/util.tpl + Increase the printing width for print_test_name(). + + * tests/command_test.c tests/Makefile.am + Add tests for correct updating of broadcast WAV coding history. + + * examples/sndfilehandle.cc examples/Makefile.am + Add example program using the C++ SndfileHandle class. + +2007-10-29 Erik de Castro Lopo + + * src/common.h src/sndfile.c + Add error codes SFE_ZERO_MAJOR_FORMAT and SFE_ZERO_MINOR_FORMAT. + +2007-10-26 Erik de Castro Lopo + + * src/sd2.c + Identify sample-rate/sample-size/channels by resource id. + +2007-10-25 Erik de Castro Lopo + + * src/broadcast.c src/common.h src/sndfile.c + Improvements to handling of broadcast info in WAV files. Thanks to Frederic + Cornu and other for their input. + +2007-10-24 Erik de Castro Lopo + + * src/FLAC/include/share/alloc.h + Mingw fix for SIZE_T_MAX from Uli Franke. + +2007-10-23 Erik de Castro Lopo + + * tests/open_fail_test.c tests/error_test.c tests/Makefile.am + Move tests from open_fail_test.c to error_test.c and remove the former. + +2007-10-22 Erik de Castro Lopo + + * tests/scale_clip_test.(def|tpl) + Add tests for SFC_SET_INT_FLOAT_WRITE command. + + * doc/command.html + Add docs for SFC_SET_INT_FLOAT_WRITE command. + + * examples/sndfile-play.c tests/dft_cmp.c + Fix gcc-4.2 warning messages. + +2007-10-21 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c + Add command SFC_GET_CURRENT_SF_INFO. + + * src/sndfile.h.in src/sndfile.c src/create_symbols_file.py + Remove function sf_get_info (only ever in pre-release code). + + * tests/command_test.c + Add test for SFC_GET_CURRENT_SF_INFO. + +2007-10-15 Erik de Castro Lopo + + * src/wav.c + Add parsing of 'exif' chunks. Originally coded by Trent Apted. + + * configure.ac + Put config stuff in Cfg directory. + Remove check for inttypes.h. + +2007-10-10 Erik de Castro Lopo + + * src/w64.c + Fix writing of 'riff' chunk length and check for correct value in parser. + +2007-09-20 Erik de Castro Lopo + + * doc/index.html + Link to MP3 FAQ entry. + +2007-09-18 Erik de Castro Lopo + + * src/flac.c + Move the blocksize check to an earlier stage of flac_buffer_copy. + +2007-09-12 Erik de Castro Lopo + + * src/FLAC + Huge merge from FLAC upstream. + +2007-09-10 Erik de Castro Lopo + + * examples/*.c + Change license to all example programs to BSD. + +2007-09-08 Erik de Castro Lopo + + * src/FLAC/include/FLAC/metadata.h + Include to prevent compile error on OSX. + + * Octave/octave_test.sh + Disable test on OSX. Can't get it to work. + + * src/flac.c + Check the blocksize returned from the FLAC decoder to prevent buffer + overruns. Reported by Jeremy Friesner. Thanks. + +2007-09-07 Erik de Castro Lopo + + * Makefile.am M4/octave.m4 + Fix build when Octave headers are not present. + +2007-08-27 Erik de Castro Lopo + + * doc/development.html + Add note about bzr repository directory looking empty. + +2007-08-26 Erik de Castro Lopo + + * configure.ac Octave/* M4/octave_* + Bunch of changes to add ability to build GNU Octave modules to read/write + sound files using libsndfile from Octave. + +2007-08-23 Erik de Castro Lopo + + * acinclude.m4 configure.ac ... + Get rid of acinclude.m4 and replace it with an M4 directory. + +2007-08-21 Erik de Castro Lopo + + * src/sndfile.h.in + Remove crufty Metrowerks compiler support. Allow header file to be compiled + on windows with both GCC and microsoft compiler. + +2007-08-19 Erik de Castro Lopo + + * tests/dft_cmp.[ch] tests/floating_point_test.tpl + Clean up floating point tests. + +2007-08-14 Erik de Castro Lopo + + * src/aiff.c + Fix segfault when COMM chunk length is byte swapped. + +2007-08-09 Erik de Castro Lopo + + * src/common.h src/mat4.c src/mat5.c src/sndfile.c + Add a generic SFE_CHANNEL_COUNT_ZERO error, remove format specific errors. + + * src/au.c + Fix crash on AU files with zero channel count. Reported by Ben Alison. + +2007-08-08 Erik de Castro Lopo + + * src/voc.c + Fix bug in handling file supplied by Matt Olenik. + +2007-07-31 Erik de Castro Lopo + + * src/OGG + Merge from OGG upstream sources. + +2007-07-25 Erik de Castro Lopo + + * src/FLAC + Merge from FLAC upstream sources. + +2007-07-15 Erik de Castro Lopo + + * src/flac.c + Fix memory leak; set copy parameter to FALSE in call to + FLAC__metadata_object_vorbiscomment_append_comment. + + * src/common.[ch] + Add function psf_rand_int32(). + +2007-07-14 Erik de Castro Lopo + + * src/FLAC + Merge from FLAC upstream sources. + + * src/strings.c tests/string_test.c tests/Makefile.am + Make sure string tests for SF_STR_LICENSE actually works. + +2007-07-13 Erik de Castro Lopo + + * tests/string_test.c + Add ability to test strings stored in metadata secion of FLAC files. + + * src/string.c + Fix logic for testing if audio data has been written and string is added. + Make sure SF_STR_ALBUM actually works. + + * src/flac.c + Finalize reading/writing string metadata. Tests pass. + + * src/sndfile.h.in tests/string_test.c src/flac.c + Add string type SF_STR_LICENSE, update test and use for FLAC files. + + * src/sndfile.h.in + Add definition for SFC_SET_SCALE_FLOAT_INT_WRITE command. + + * src/common.h src/double64.c src/float32.c src/sndfile.c + Add support for SFC_SET_SCALE_FLOAT_INT_WRITE (still needs testing). + +2007-07-12 Erik de Castro Lopo + + * src/flac.c + Apply patch from Ed Schouten to read artist and title metadata from FLAC + files. + Improve reporting of FLAC metadata. + + * src/sndfile.h.in tests/string_test.c src/flac.c + Add string type SF_STR_ALBUM, update test and use for FLAC files. + +2007-06-28 Erik de Castro Lopo + + * src/FLAC/* + Merge from upstream CVS. + +2007-06-16 Erik de Castro Lopo + + * src/FLAC/* + Update from upstream CVS. + +2007-06-14 Erik de Castro Lopo + + * tests/cpp_test.cc + Add extra tests for when the SndfileHandle constructor fails. + + * src/sndfile.hh + Make sure failure to open the file in the constructor does not allow later + calls to other methods to fail. + +2007-06-10 Erik de Castro Lopo + + * tests/util.tpl + Add function write_mono_file. + + * tests/generate.[ch] tests/Makefile.am + Add files generate.[ch] and hook into build. + + * tests/write_read_test.tpl + Add multi_seek_test. + + * src/flac.c + Fix buffer overflow bug. Test provided by Jeremy Friesner and fix provided + by David Viens. + +2007-06-07 Erik de Castro Lopo + + * doc/FAQ.html + Minor update. + + * configure.ac src/FLAC/src/libFLAC/ia32/Makefile.am src/Makefile.am + Apply patch from Trent Apted make it compile on Intel MacOSX. Thanks Trent. + +2007-05-28 Erik de Castro Lopo + + * src/wav.c + Fix writing of MSGUID subtypes. Thanks to Bruce Sharpe. + +2007-05-22 Erik de Castro Lopo + + * src/wav.c + Fix array indexing bug raised by Bruce Sharpe. + +2007-05-12 Erik de Castro Lopo + + * src/FLAC/src/share/getopt/getopt.c + Fix Mac OSX / PowerPC compile warnings. + + * configure.ac + Make sure WORDS_BIGENDIAN gets correctly defined for FLAC code. + +2007-05-04 Erik de Castro Lopo + + * doc/FAQ.html + Add Q/A about MP3 support. + +2007-05-03 Erik de Castro Lopo + + * doc/new_file_type.HOWTO + Minor updates. + +2007-05-02 Erik de Castro Lopo + + * src/wve.c + Fix a couple bad parameters with psf_log_printf. + + * src/pcm.c + Improve error reporting. + + * src/common.h src/common.c + Constify psf_hexdump. + +2007-04-30 Erik de Castro Lopo + + * src/FLAC + Ditch and re-import required FLAC code. + + * configure.ac + Force FLAC__HAS_OGG variable to 1. + + * src/FLAC/src/libFLAC/stream_encoder.c + Fix compiler warnings. + +2007-04-23 Erik de Castro Lopo + + * configure.ac tests/win32_ordinal_test.c + Detect if win32 DLL is beging generated and only run win32_ordinal_test if + true. + + * src/G72x/Makefile.am src/Makefile.am + Use $(EXEEXT) where possible. + +2007-04-18 Erik de Castro Lopo + + * src/wve.c src/common.h src/sndfile.c + Complete definition of SfE_WVE_NO_WVE error message. + + * src/wve.c + Fix error in files generated on big endian systems. Robustify parsing. + +2007-04-16 Erik de Castro Lopo + + * src/double64.c + Fix clipping of double to short conversions on 64 bit systems. + + * src/flac.c regtest/database.c tests/cpp_test.cc + Fix compile warnings for 64 bit systems. + +2007-04-15 Erik de Castro Lopo + + * src/wav.c src/wav_w64.c + Use audio detect function when 'fmt ' chunk data is suspicious. + + * configure.ac + Add ugly hack to remove -Werror from some Makefiles. + +2007-04-14 Erik de Castro Lopo + + * src/GSM610/long_term.c src/macbinary3.c tests/cpp_test.cc + Add patch from André Pang to clean up compiles on OSX. + + * src/wve.c src/common.h src/sndfile.c src/sndfile.h.in + examples/sndfile-convert.c + Merge changes from Reuben Thomas to improve WVE support. + + * tests/lossy_comp_test.c tests/Makefile.am + Add tests for WVE files. + +2007-04-11 Erik de Castro Lopo + + * src/sndfile.hh + Add a static SndfileHandle::formatCheck method as suggested by Jorge + Jiménez. + +2007-04-09 Erik de Castro Lopo + + * src/sndfile.c + Fixed a bug in sf_error() where the function itself was being compared + against zero. Add a check for a NULL return from peak_info_calloc. Fix a + possible NULL dereference. + +2007-04-07 Erik de Castro Lopo + + * src/flac.c + Turn off seekable flag when writing, return SFE_BAD_RDWR_FORMAT when + opening file for RDWR. + + * src/sndfile.c + Improve error message for SFE_BAD_RDWR_FORMAT. + + * src/mat4.c + Fix array indexing issue. Thanks to Ben Allison (Nullsoft) for alerting me. + +2007-03-05 Erik de Castro Lopo + + * doc/FAQ.html + Add Q/A 19 on project files. + +2007-03-01 Erik de Castro Lopo + + * src/sndfile.c + Guard agains MacOSX universal binary compiles. + + * doc/FAQ.html + Add Q/A 18 and clean up Q3. + +2007-02-22 Erik de Castro Lopo + + * src/aiff.c + Add support for 'in24' files. + +2007-02-13 Erik de Castro Lopo + + * src/wav.c src/wav_w64.c src/wav_w64.h + Start work towards detecting ausio codec type from the actual audio data. + + * src/audio_detect.c src/test_audio_detect.c + Add new file and its unit test. + +2007-02-07 Erik de Castro Lopo + + * examples/cooledit-fixer.c examples/Makefile.am + Remove old broken example program. + +2007-02-06 Erik de Castro Lopo + + * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py + Add function sf_get_info. + +2007-01-25 Erik de Castro Lopo + + * examples/sndfile-play.c + For ALSA, use the 'default' device instead of 'plughw:0'. + +2007-01-22 Erik de Castro Lopo + + * src/sndfile.c + Allow writing of WAV/WAVEX 'BEXT' chunks in SFM_RDWR mode. + +2007-01-21 Erik de Castro Lopo + + * doc/development.html doc/embedded_files.html man/sndfile-play.1 + Minor documentation fixes. Thanks Reuben Thomas. + +2006-12-16 Erik de Castro Lopo + + * examples/sndfile-convert.c + Add -override-sample-rate command line option. + +2006-11-19 Erik de Castro Lopo + + * tests/misc_test.c + Force errno to zero at start of some tests. + + * src/sndfile.c + Minor clean up of error handling. + + * configure.ac + Remove an assembler test which was failing on OSX. + +2006-11-15 Erik de Castro Lopo + + * src/common.h + Fix the definition of SF_PLATFORM_S64 for MinGW. + + * src/FLAC/Makefile.am src/FLAC/share/grabbag/Makefile.am + Fix path problems for MinGW. + +2006-11-13 Erik de Castro Lopo + + * src/sfendian.h + Add include guard. + + * src/Makefile.am src/flac.c + Clean up include paths. + + * src/test_conversions.c + New file to test psf_binheader_readf/writef functions. + + * src/Makefile.am src/test_file_io.c src/test_log_printf.c src/common.c + Clean up unit testing. + + * src/common.c + Fix a bug reading/writing 64 bit header fields. Thanks to Jonathan Woithe + for reporting this. + + * src/test_conversions.c + Complete unit test for above fix. + +2006-11-11 Erik de Castro Lopo + + * src/sndfile.c + More refactoring to clean up psf_open_file() and vairous sf_open() + functions. + +2006-11-09 Erik de Castro Lopo + + * src/wav.c + Apply a patch from Jonathan Woithe to allow opening of (malformed) WAV + files of over 4 gigabytes. + +2006-11-05 Erik de Castro Lopo + + * src/sndfile.c + Refactor function psf_open_file() to provide a single return point. + + * tests/misc_test.c + Fix permission_test to ensure that read only file can be created. + +2006-11-03 Erik de Castro Lopo + + * src/common.h + Add SF_PLATFORM_S64 macro as a platform independant way of doing signed 64 + bit integers. + + * src/aiff.c src/svx.c src/wav.c + Add warning in log if files are larger than 4 gigabytes in size. + +2006-11-01 Erik de Castro Lopo + + * src/FLAC src/OGG confgure.ac src/Makefile.am + Pull in all required FLAC and OGG code so external libraries are not + needed. This makes compiling on stupid fscking Windoze easier. + +2006-10-27 Erik de Castro Lopo + + * src/sd2.c + Add workaround for switched sample rate and sample size. + + * src/wav.c + Add workaround for excessively long coding history in the 'bext' chunk. + +2006-10-23 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c src/wav.c doc/command.html + Use SF_AMBISONIC_* instead of SF_TRUE/SF_FALSE. + +2006-10-22 Erik de Castro Lopo + + * src/sndfile.h.in src/wav.c src/wav_w64.c src/common.h doc/command.html + Apply a patch from Fons Adriaensen to allow writing on WAVEX Ambisonic + files. Still needs a little tweaking before its ready for release. + + * src/*.c + Use the UNUSED macro to prevent compiler warnings. + +2006-10-19 Erik de Castro Lopo + + * src/aiff.c + Fix a bug in parsing AIFF files with a slightly unusual 'basc' chunk. Thanks + to David Viens for providing two example files. + + * src/common.(c|h) src/aiff.c + Add a function psf_sanitize_string and use it in aiff.c. + +2006-10-18 Erik de Castro Lopo + + * src/wav_w64.c + Apply a patch from Fons Adriaensen which fixes a minor WAVEX GUID issue. + +2006-10-17 Erik de Castro Lopo + + * src/Makefile.am + Fix problem related to recent test coverage changes. + +2006-10-15 Erik de Castro Lopo + + * configure.ac tests/Makefile.am + Add --enable-test-coverage configure option. + +2006-10-05 Erik de Castro Lopo + + * src/sndfile.hh + Add an std::string SndfileHandle constructor. + + * tests/scale_clip_test.tpl + Fix the 'make distcheck' target. + +2006-10-03 Erik de Castro Lopo + + * src/double64.c src/float32.c + Add optional clipping on float file data to int read data conversions. + + * tests/tests/scale_clip_test.(def|tpl) + Add test for above new code. + +2006-09-06 Erik de Castro Lopo + + * tests/aiff_rw_test.c + Add 'MARK' chunks to make sure they are parsed correctly. + +2006-09-05 Erik de Castro Lopo + + * src/aiff.c + Fix parsing of MARK chunks. Many thanks to Sciss for generating files to + help debug the problem. + +2006-09-02 Erik de Castro Lopo + + * src/common.h + Make the SF_MIN and SF_MAX macros at least partially type safe. + + * tests/lossy_comp_test.c + Fix overflow problems when ensuring that signalis not zero. + +2006-08-31 Erik de Castro Lopo + + * configure.ac docs/*.html + Changes for release 1.0.17. + +2006-08-08 Erik de Castro Lopo + + * src/flac.c + Remove inline from functions called by pointer. Thanks to Sampo Savolainen + for notifying me of this. + +2006-07-31 Erik de Castro Lopo + + * src/sndfile.hh + Add writeSync method. + Add copy constructor and assignment operator (thanks Daniel Schmitt). + Add methods readRaw and writeRaw. + Make read/write/readf/writef simple overlaods instead of templates (thanks + to Trent Apted for suggesting this). + + * tests/cpp_test.cc + Cleanup. Add tests. + +2006-07-30 Erik de Castro Lopo + + * src/sndfile.hh + Templatize the read/write/readf/writef methods as suggested by Lars Luthman. + Prevent the potential leak of SNDFILE* pointers in the openRead/openWrite/ + openReadWrite methods. + Add const to SF_INFO pointer in Sndfile constructor. + Make the destrictor call the close() method. + + * tests/cpp_test.cc + Add more tests. + +2006-07-29 Erik de Castro Lopo + + * tests/cpp_test.cc + Remove the generated file so "make distcheck" passes. + + * src/Makefile.am + Add sndfile.hh to distributed header files. + + * src/sndfile.hh + Change the license for the C++ wrapper to modified BSD. + +2006-07-28 Erik de Castro Lopo + + * src/sndfile.hh + Complete it. + + * tests/cpp_test.cc + Add more tests. + +2006-07-27 Erik de Castro Lopo + + * tests/utils.tpl + Add extern C to generated header file. + + * src/sndfile.hh + Work towards completing this. + + * tests/cpp_test.cc tests/Makefile.am + Add a C++ test and hook into build. + + * configure.ac + Add appropriate CXXFLAGS. + +2006-07-26 Erik de Castro Lopo + + * configure.ac + Test if compiler supports -Wpointer-arith. + + * src/common.c + Fix a warning resulting from -Wpointer-arith. + +2006-07-15 Erik de Castro Lopo + + * examples/sndfile-play.c + Explicitly set endian-ness as well as setting 16 bit output. + + * examples/sndfile-info.c + Make sure to parse info if file fails to open. + + * src/sndfile.c + Handle parse error a little better. + + * src/wav_w64.[ch] + Minor clean up, add detection of IPP ITU G723.1. + +2006-06-23 Erik de Castro Lopo + + * src/sndfile.c + Make sure psf->dataoffset gets reset to zero when openning headersless + files based on the file name extension. + +2006-06-21 Erik de Castro Lopo + + * tests/(command|lossy_comp|pcm|scale_clip)_test.c tests/fix_this.c + tests/write_read_test.(tpl|def) + Fix gcc-4.1 compiler warnings about "dereferencing type-punned pointer will + break strict-aliasing rules". + + * examples/cooledit-fixer.c + More fixes like above. + +2006-06-20 Erik de Castro Lopo + + * src/file_io.c + Fix a windows bug where the syserr string of SF_PRIVATE was not being set + correctly. + + * src/sndfile.c + Fixed a logic bug in sf_seek(). Thanks to Paul Davis for finding this. + +2006-06-04 Erik de Castro Lopo + + * configure.ac + Fixed detection of S_IRGRP. + +2006-05-30 Erik de Castro Lopo + + * sndfile-convert.c + Add conversion SF_INSTRUMENT data when present. + +2006-05-22 Erik de Castro Lopo + + * doc/development.html + Removed references to tla on windows. + + * src/common.h src/sndfile.c + Add separate void pointers for file containter and file codec data to + SF_PRIVATE struct. Still need to move all existing fdata pointers. + + * tests/write_read_test.tpl + Change the order of some tests. + + * src/aiff.c + When writing 'AIFC' files, make sure get an 'FVER' gets added. + + * src/common.h src/(dwvw|flac|g72x|gsm610|ima_adpcm|ms_adpcm|paf|sds).c + src/(sndfile|voc|vox_adpcm|xi).c + Remove fdata field from SF_PRIVATE struct and replace it with codec_data. + +2006-05-10 Erik de Castro Lopo + + * Win32/testprog.c Win32/Makefile.am + Add a minimal win32 test program. + + * Win32/README-precompiled-dll.txt Mingw-make-dist.sh + Update readme and Mingw build script. + +2006-05-09 Erik de Castro Lopo + + * configure.ac acinclude.m4 + Minor fixes for Solaris. + +2006-05-05 Erik de Castro Lopo + + * src/test_endswap.(def|tpl) + Fix printf formatting for int64_t on 64 bit machines. + +2006-05-04 Erik de Castro Lopo + + * src/binhead_check.py + New file to check for bad parameters passed to psf_binheader_writef(). + + * src/Makefile.am + Hook into test suite. + + * src/voc.c src/caf.c src/wav.c src/mat5.c src/mat4.c + Fix bugs found by new test program. + + * src/double64.c + Clean up double64_get_capability(). + +2006-05-03 Erik de Castro Lopo + + * src/wav_w64.c + Fix a bug on x86_64 where an int was being passed via stdargs and being + read using size_t which is 64 bits. Thenks to John ffitch for giving me a + login on his box. + +2006-05-02 Erik de Castro Lopo + + * src/caf.c src/double64.c examples/sndfile-info.c tests/virtual_io_test.c + tests/utils.tpl + Fix a couple of signed/unsigned problems. + +2006-05-01 Erik de Castro Lopo + + * tests/command_test.c + Add channel map tests. + + * src/common.h src/sndfile.c + Add a pointer to the SF_PRIVATE struct and make sure it gets freed in + sf_close(). + +2006-04-30 Erik de Castro Lopo + + * configure.ac doc/(command|index|api).html NEWS README + Updates for 1.0.16 release. + + * src/sndfile.h.in + Define enums for channel mapping. + + * examples/sndfile-info.c + Clean up usage of SF_INFO struct. + +2006-04-29 Erik de Castro Lopo + + * tests/util.tpl + Add function testing function exit_if_true(). + + * tests/floating_point_test.tpl + Fix a problem where the test program was not exiting when the test failed. + +2006-04-15 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c src/common.h src/command.c + Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS. + + * doc/commands.html + Document new commands. Other minor updates. + + * tests/peak_chunk_test.c + Update tests for new commands. + +2006-04-02 Erik de Castro Lopo + + * tests/peak_chunk_test.c + Add test for RIFX and WAVEX files. + Try and confuse the PEAK chunk writing by enabling and disabling it. + + * src/sndfile.c + Fix a bug where enabling and disabling PEAK chunk was screwing up. + +2006-03-31 Erik de Castro Lopo + + * src/sndfile.h.in + Add the block of 190 reserved bytes into this struct to allow for + future expansion. + + * src/wav.c src/sndfile.c src/broadcast.c + Significant cleanup of broadcast wave stuff. + + * examples/sndfile-info.c + Fix print message. + + * tests/command_test.c tests/Makefile.am + Complete bext tests, hook test in test suite. + +2006-03-30 Erik de Castro Lopo + + * src/sndfile.h.in + Make coding_history field of SF_BROADCAST_INFO struct a char array instead + of a char pointer. + + * src/sndfile.c src/common.h src/wav.c + Clean up knock on effects of above chnage. + + * examples/sndfile-info.c + Add -b command line option to usage message. + Clean up output of broadcast wave info. + + * src/wav.c + Ignore and skip the 'levl' chunk. + +2006-03-26 Erik de Castro Lopo + + * configure.ac + Fix handling of --enable and --disable configure args. Thanks to Diego + 'Flameeyes' Pettenò who sent the patch. + +2006-03-22 Erik de Castro Lopo + + * doc/win32.html + Make it really clear that although the MSVC++ cannot compile libsndfile, + the precompiled DLL can be used in C++ programs compiled with MSVC++. + +2006-03-18 Erik de Castro Lopo + + * src/aiff.c + Fix bug in writing of INST chunk in AIFF files. + Fix potential bug in writing MARK chunks. + + * src/sndfile.c + Make sure the instrument chunk can only be written at the start of the file. + + * tests/command_test.c + Add check of log buffer. + + * tests/utils.tpl + Add usage of space character to psf_binheader_writef. + +2006-03-17 Erik de Castro Lopo + + * src/Makefile.am tests/Makefile.am + Remove --source-time argument from autogen command lines. + + * src/broadcast.c + New file for EBU Broadcast chunk in WAV files. + + * src/sndfile.c src/sndfile.h.in src/wav.c src/common.h + Add patch from Paul Davis implementing read/write of the BEXT chunk. + +2006-03-16 Erik de Castro Lopo + + * Win32/README-precompiled-dll.txt + New file descibing how to use the precompiled DLL. + + * Win32/Makefile.am + Add Win32/README-precompiled-dll.txt to EXTRA_DIST files. + + * configure.ac + Bump version to 1.0.15. + +2006-03-11 Erik de Castro Lopo + + * src/wav.c + On read, only add the endian flag if the file is big endian. + + * src/ms_adpcm.c + Fixed writing of APDCM coeffs in RIFX files. + + * tests/write_read_test.tpl tests/lossy_comp_test.c + Add tests for RIFX files. + +2006-03-10 Erik de Castro Lopo + + * Mingw-make-dist.sh + Bunch of improvements. + + * doc/win32.html + Update MinGW program versions. + +2006-03-09 Erik de Castro Lopo + + * src/create_symbols_file.py + Fix the library name in created win32 DEF file. Add correct DLL name for + Cygwin DLL. + + * Win32/Makefile.am tests/Makefile.am + Remove redundant files, add win32_ordinal_test to test suite. + + * tests/win32_ordinal_test.c + Update to do test in cygsndfile-1.dll as well. + + * doc/win32.html + Fix typo, mention that -mno-cygwin with the Cygwin compiler does not work. + + * src/wav.c src/wav_w64.c src/sndfile.c src/sndfile.h.in + Apply large patch from Jesse Chappell which adds support for RIFX files. + +2006-03-08 Erik de Castro Lopo + + * Makefile.am + Add Mingw-make-dist.sh to the extra dist files. + + * configure.ac + Fix setting SHLIB_VERSION_ARG for MinGW. + + * tests/win32_ordinal_test.c + New test program to test that the win32 DLL ordinals agree with the DEF + file. + +2006-03-04 Erik de Castro Lopo + + * src/common.h + Add a static inline function to convert an int to a size_t. This will be + a compile to nothing on 32 bit CPUs and a sign extension on 64 bit CPUs. + + * src/aiff.c src/avr.c src/common.c src/xi.c src/gsm610.c + Fix an ia64 problem where a varargs function was being passed an int in + some places and a size_t in other places. + + * src/sd2.c + Add a workaround for situations where OSX seems to add an extra 0x52 bytes + to the start of the resource fork. + +2006-02-19 Erik de Castro Lopo + + * Mingw-make-dist.sh + Add a shell script to build the windows binary/source ZIP file. + + * doc/index.html + Add download link for windows binary/source ZIP file. Add links for GPG + signatures. + + * doc/win32.html + Remove info about building using microsoft compiler. + + * configure.ac + Bump version to 1.0.14. + +2006-02-11 Erik de Castro Lopo + + * src/sd2.c + Improve logging of errors in resource fork parser. + +2006-01-31 Erik de Castro Lopo + + * Win32/Makefile.msvc + Replace au_g72x.* with g72x.*. Thanks to ussell Borogove. + +2006-01-29 Erik de Castro Lopo + + * src/common.c + Make sure return values are initialised header buffer is full. + + * src/wav.c + Add workarounds for messed up WAV files. + +2006-01-21 Erik de Castro Lopo + + * Win32/config.h + Undef HAVE_INTTYPES_H for win32. + + * tests/command_test.c + Don't exit on error in instrument test for XI files. + + * configure.ac + Bump version to 1.0.13. + + * doc/*.html NEWS README + Update version numbers. + +2006-01-19 Erik de Castro Lopo + + * src/xi.c + Start work on add read/write of instrument chunks. + + * src/command_test.c + Add tests for XI instrument chunk. + + * tests/largefile_test.c tests/Makefile.am + Add new test and hook it into the build system. This test will not be run + automatically because it requires 3 Gig of disk space and takes 3 minutes + to run. + +2006-01-10 Erik de Castro Lopo + + * examples/sndfile-play.c + Fix calculation of samples remaining in win32 code. Thanks Axel Röbel. + + * src/common.h + Make sure length of header buffer can hold header plus strings. Thanks Axel + Röbel. + +2006-01-09 Erik de Castro Lopo + + * src/sndfile.h.in src/aiff.c src/wav.c + Apply a patch from John ffitch (Csound project). + Add detune field to SF_INSTRUMENT struct. + Add reading/writing instrument chunks to WAV files. + + * tests/command_test.c + Update SF_INSTRUMENT tests. + + * tests/Makefile.am + Hook instrument tests into test suite. + +2006-01-05 Erik de Castro Lopo + + * configure.ac + Check for because some broken systems (like Solaris) don't have + which is the 1999 ISO C standard file containing int64_t. + + * src/sfendian.h src/common.h + Use if is not available. + +2005-12-30 Erik de Castro Lopo + + * tests/peak_chunk_test.c + Extend and clean up tests. + + * src/sndfile.c + Fix a bug that prevented the turning off of PEAK chunks. + +2005-12-29 Erik de Castro Lopo + + * tests/error_test.c + Make the test distclean correct. + + * src/file_io.c + Fix an SD2 MacOSX bug (reported by vince schwarzinger). + +2005-12-28 Erik de Castro Lopo + + * src/aiff.c tests/command_test.c + Apply a big patch from John ffitch (Csound project) to add reading and + writing of instrument chunks to AIFF files. Also update the test. + +2005-12-10 Erik de Castro Lopo + + * tests/aiff_rw_test.c tests/virtual_io_test.c tests/utils.tpl + Move test function dump_data_to_file() to utils.tpl. + + * tests/error_test.c tests/Makefile.am + Updates, including a new test to test that sf_error() returns a valid error + number. + +2005-12-07 Erik de Castro Lopo + + * examples/list_formats.c + Make sure the SF_INFO struct is memset to all zero before being used. + Thanks to Stephen F. Booth. + + * src/sndfile.c + Make the return value of sf_error() match the API documentation. + +2005-11-19 Erik de Castro Lopo + + * examples/sndfile-convert.c + Allow conversion to raw gsm610. + + * src/common.h src/sndfile.c src/au.c + Remove au_nh_open() and all references to it (wasn't working anyway). + + * tests/headerless_test.c + Add new test for file extension based detection. + + * src/sndfile.c + Rejig file extension based file type detection. + +2005-11-16 Erik de Castro Lopo + + * src/sndfile.c + Add "gsm" as a recognised file extension when no magic number can be found. + + * tests/lossy_comp_test.c tests/Makefile.am + Test headerless GSM610. + +2005-11-13 Erik de Castro Lopo + + * doc/api.html + Fix a minor typo and a minor error. Thanks Christoph Kobe and John Pavel. + +2005-10-30 Erik de Castro Lopo + + * src/wav_w64.c + Add more reporting of 'fmt ' chunk for G721 encoded files. + + * src/wav.c + Gernerate a more correct 20 byte 'fmt ' chunk rather than a 16 byte one. + +2005-10-29 Erik de Castro Lopo + + * src/G72x/g72x.[ch] + Minor cleanup of interface. + +2005-10-28 Erik de Castro Lopo + + * src/ogg.c + Removed the horribly broken and non-functional OGG implementation when + --enable-experimental was enabled. When OGG does finally work it will be + merged. + + * src/caf.c + Fix a memory leak. + +2005-10-27 Erik de Castro Lopo + + * src/g72x.c src/G72x/*.(c|h) src/common.h src/sndfile.c src/wav.c src/au.c + Add support for G721 encoded WAV files. + + * doc/index.html + Update support matrix. + + * tests/lossy_comp_test.c + For file formats that support it, add string data after the audio data and + make sure it isn't treated as audio data on read. + + * src/gsm610.c + Add code to ensure that the container close function (ie for WAV files) gets + called after the codec's close function. This allows GSM610 encoded WAV files + to have string data following the audio data. + Add an AIFF specific check on psf->datalength. + + * src/wav.c + Simplify wav_close function. + + * src/aiff.c + Make sure the tailer data gets written at an even file offset. Pad if + necessary. + + * src/common.h + Replace the close function pointer in SF_PRIVATE with separate functions + codec_close and container_close. The former is always called first. + + * src/*.c + Fix knock on effects of above. + +2005-10-26 Erik de Castro Lopo + + * examples/sndfile-info.c + Complete dumping SF_INSTRUMENT data. + + * src/dwvw.c src/ima_adpcm.c src/gsm610.c src/ms_adpcm.c + Add extra checks in *_init function. + + * tests/lossy_comp_test.c + Add a string comment to the end of the files to make sure that the decoder + doesn't decode beyond the end of the audio data section. + +2005-10-25 Erik de Castro Lopo + + * examples/sndfile-info.c + Minor code cleanup. + Start work on dumping SF_INSTRUMENT data. + +2005-10-23 Erik de Castro Lopo + + * src/sndfile.h.in src/common.h src/common.c + Update definition of SF_INSTRUMENT struct and create a function to allocate + and initialize the struct (input from David Viens). + Clean up definition of SF_INSTRUMENT struct. + + * src/wav.c src/wav_w64.c + Add support for Ambisoncs B WAVEX files (David Viens). + + * src/aiff.c src/wav.c src/wav_w64.c + Start work on reading/writing the SF_INSTRUMENT data. + + * src/sndfile.c + Add code to get and set SF_INSTRUMENT data. + + * tests/command_test.* tests/Makefile.am + Add test for set and getof SF_INSTRUMENT data. + The file command_test.c is no longer autogen generated. + +2005-10-15 Erik de Castro Lopo + + * src/gsm610.c + Minor cleanup. + +2005-10-14 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Minor cleanup. + +2005-10-13 Erik de Castro Lopo + + * src/*.c + Ensure sfconfig.h is included before any other header file. + + * src/file_io.c + Add comments documenting the three sections of the file. + + * src/gsm610.c + Make sure SF_FORMAT_WAVEX are handled correctly. + +2005-10-07 Erik de Castro Lopo + + * configure.ac + Add options to allow disabling of FLAC and ALSA. Suggested by Ben Greear. + +2005-09-30 Erik de Castro Lopo + + * tests/locale_test.c + Modify the way the unicode strings were encoded so that older compilers + do not complain. Thanks Axel Röbel. + + * configure.ac + Bump the version to 1.0.12 for release. + + * NEWS README Win32/config.h doc/(FAQ|index.html|command|api).html + Update version numbers. + +2005-09-26 Erik de Castro Lopo + + * src/flac.c + Fix valgrind error and minor cleanup. + +2005-09-25 Erik de Castro Lopo + + * src/(au|paf|aiff|w64|wav|svx).c + Make sure structs are initialised. + +2005-09-24 Erik de Castro Lopo + + * configure.ac + Make -Wdeclaration-after-statement work with --enable-gcc-werror configure + option. + Add -std=gnu99 (C99 plus posix style stuff like gmtime_r) to CFLAGS if the + compiler supports it. + +2005-09-23 Erik de Castro Lopo + + * configure.ac acinclude.m4 + Add -Wdeclaration-after-statement to CFLAGS if the compilers supports it. + +2005-09-22 Erik de Castro Lopo + + * tests/util.(tpl|def) + Make the test_write_*_or_die() functions const safe. + +2005-09-21 Erik de Castro Lopo + + * src/nist.c + Make sure the data offset is read from the file header. Thanks to + David A. van Leeuwen for a patch. + +2005-09-20 Erik de Castro Lopo + + * configure.ac src/sfconfig.h + Check for and the function setlocale(). + Set config variables to zero if not found. + + * tests/locale_test.c tests/Makefile.am + Add new test program and hook into build/test system. + +2005-09-18 Erik de Castro Lopo + + * src/common.h src/file_io.c + On windows, use windows specific types for file handles. + Add functions psf_init_files() and psf_use_rsrc(). + + * src/sd2.c + Make resource fork handling independant of file desciptor/handles. + + * src/sndfile.c src/test_file_io.c + Fix knock on effects. + +2005-09-06 Erik de Castro Lopo + + * src/float_cast.h + The lrint and lrintf implementations in Cygwin are both buggy and slow. + Add replacements which were pulled from the Public Domain MinGW math.h + header file. + +2005-09-05 Erik de Castro Lopo + + * tests/(lossy_comp_test|virtual_io_test).c + More Valgrind fixups. + + * configure.ac + Simplify and correct configuring for Cygwin. + + * Win32/config.h Win32/sndfile.h Win32/Makefile.msvc + Update build for MSVC. + +2005-09-04 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Make sure to close SNDFILE when exiting test when file format is not seekable. + + * tests/(aiff_rw_test|virtual_io_test).c + Do a few valgrind fix ups. + +2005-09-03 Erik de Castro Lopo + + * src/float32.c src/double64.c + Replace floating point equality comparisons with greater/less comparisons. + Found by John Pavel using the Intel compiler. + + * src/sfconfig.h + New file to clean up issues surrounding autoconf generated preprocessor + symbols. + + * src/*.(c|h) tests/*.(c|tpl) examples/*.c + Fixed a bunch of other stuff found by John Pavel using the Intel compiler. + + * src/file_io.c + Remove Mac OS9 Metrowerks compiler specific hacks. + +2005-08-31 Erik de Castro Lopo + + * src/w64.c + Cast integer literal to sf_count_t in call to psf_binheader_writef() to + prevent Valgrind error. + +2005-08-30 Erik de Castro Lopo + + * doc/command.html + Improve documentation of SF_GET_FORMAT_SUBTYPE. + +2005-08-26 Erik de Castro Lopo + + * examples/sndfile-convert.c + Allow files to be converted to SD2 format. + + * src/sd2.c + Fix a bug in reading and writing of SD2 files on little endian CPUs. + Thanks to Matthew Willis for finding this. + +2005-08-25 Erik de Castro Lopo + + * doc/api.html + Update Note2 to point to SFC_SET_SCALE_FLOAT_INT_READ. + +2005-08-16 Erik de Castro Lopo + + * configure.ac + Use $host_os instead of $target_os (thanks to Mo De Jong). + +2005-08-15 Erik de Castro Lopo + + * src/Makefile.am + Apply a patch from Mo DeJong to allow building outside of the source dir. + + * src/file_io.c + Fix psf_fsync() for win32. + + * src/wav.c src/wav_w64.(c|h) + Move some code from wav.c to wav_w64.c to improve the log output of files of + type WAVE_FORMAT_EXTENSIBLE. + +2005-08-10 Erik de Castro Lopo + + * src/create_symbols_file.py + Make sure sf_write_fsync is an exported symbol. + + * examples/sndfile-convert.c + Add support for writing VOX adpcm files. + +2005-07-31 Erik de Castro Lopo + + * doc/api.html + Document the new function sf_write_sync(). + + * doc/FAQ.html + Do you plan to support XYZ codec. + +2005-07-28 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c + Add function sf_write_sync() to the API. + + * src/common.h src/file_io.c + Low level implementation (win32 not done yet). + + * tests/write_read_test.tpl + Use the new function in the tests. + +2005-07-24 Erik de Castro Lopo + + * src/common.h src/double64.c src/float32.c src/sndfile.c + Change the way PEAK chunk info is stored. Peaks now stored as an sf_count_t + for position and a double as the value. + + * src/aiff.c src/caf.c src/wav.c + Fix knock on effects of above changes. + + * src/caf.c + Implement 'peak' chunk for file wuth data in SF_FORMAT_FLOAT or + SF_FORMAT_DOUBLE format. + +2005-07-23 Erik de Castro Lopo + + * src/nist.c + Fix a bug where a variable was being used without being initialized. + + * src/flac.c + Add extra debug in sf_flac_meta_callback. + Make a bunch of private functions static. + + * src/aiff.c src/wav.c + Fix allocation for PEAK_CHUNK (bug found using valgrind). + +2005-07-21 Erik de Castro Lopo + + * src/common.h + Move the peak_loc field of SF_PRIVATE to the PEAK_CHUNK struct. + Remove had_peak field of SF_PRIVATE, use pchunk != NULL instead. + Rename PEAK_CHUNK and PEAK_POS to PEAK_CHUNK_32 and PEAK_POS_32. + + * src/aiff.c src/caf.c src/wav.c src/float32.c src/double64.c + Fix knock on effects from above. + +2005-07-19 Erik de Castro Lopo + + * src/wav.c + Prevent files with unknown chunks from being opened read/write. + +2005-07-14 Erik de Castro Lopo + + * src/flac.c + Do not use psf->end_of_file because it never gets set to anything. + + * src/common.h + Remove unused SF_PRIVATE field end_of_file. + +2005-07-12 Erik de Castro Lopo + + * src/common.c + Change the 'S' format specifier of psf_binheader_writef() to write AIFF + style strings (no terminating character). + + * src/aiff.c + Move to new (correct) AIFF string style. Thanks to Axel Röbel for being + so persistent on this issue. + +2005-07-11 Erik de Castro Lopo + + * src/sndfile.c + Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open(). + + * doc/api.html doc/command.html + Documentation updates (thanks to Kyroz for promoting these updates). + + * src/mat5.c + Modify the way the header is written. + +2005-07-10 Erik de Castro Lopo + + * src/caf.c + Add a 'free' chunk to the written file so that the audio data starts at + an offset of 0x1000. + + * src/sndfile.c + Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open(). + +2005-07-09 Erik de Castro Lopo + + * src/caf.c src/sndfile.c + Add support for signed 8 bit integers. + + * tests/write_read_test.tpl + Add test for signed 8 bit integers in CAF files. + + * doc/index.html + Update matrix for signed 8 bit integers in CAF files. + +2005-07-08 Erik de Castro Lopo + + * src/sndfile.c + Update sf_check_format() to support CAF. + + * examples/sndfile-convert.c + Add support for ".caf" file extension. + + * doc/index.html + Add Apple CAF to the support matrix. + + * src/caf.c + Add file write support. + + * src/common.c + Fix printing of Frames. + + * tests/Makefile.am tests/write_read_test.tpl tests/lossy_comp_test.c + tests/header_test.tpl misc_test.c + Add tests for CAF files. + +2005-07-07 Erik de Castro Lopo + + * doc/FAQ.html + Fix Q/A about reading/writing memory buffers. + + * src/caf.c + Bunch of work to support reading of CAF files. + +2005-07-04 Erik de Castro Lopo + + * src/(aiff|ima_adpcm|mat4|mat5|ms_adpcm).c examples/sndfile-play.c + Fix sign conversion errors reported by gcc-4.0. + + * src/caf.c + New file for Apple's Core Audio File format. + + * src/sndfile.c src/common.h src/sndfile.h.in src/Makefile.am + Hook new file into build system. + +2005-06-21 Erik de Castro Lopo + + * src_wav_w64.c + Fix handling of stupidly large 'fmt ' chunks. Thanks to Vadim Berezniker + for supplying an example file. + + * src/common.h src/sndfile.c + Remove redundant error code SFE_WAV_FMT_TOO_BIG. + +2005-06-20 Erik de Castro Lopo + + * src/sndfile.h.in src/common.h src/sndfile.c + Add public error value SF_ERR_MALFORMED_FILE. + + * src/sndfile.c + When parsing a file header fails and we don't have a system error, then set + the error number to SF_ERR_MALFORMED_FILE (suggested by Kyroz). + + * configure.ac + Allow sqlite support to be disabled in configure script. + + * regtest/database.c regtest/sndfile-regtest.c + Fix compiling when sqlite is missing. + +2005-06-11 Erik de Castro Lopo + + * src/file_io.c + Fix psf_is_pipe() and return value of psf_fread() when using virtual i/o. + + * src/sndfile.c + Fix VALIDATE_AND_ASSIGN_PSF macro for virtual i/o. + + * tests/virtual_io_test.c + Fill in skeleton test program. + + * tests/Makefile.am + Move virtual i/o tests to end of tests with stdio/pipe tests. + + * src/(sndfile.h.in|file_io.c|common.h|sndfile.c) tests/virtual_io_test.c + Rename some of the virtual i/o functions and data types. + +2005-06-10 Erik de Castro Lopo + + * src/sndfile.c + Fix the return values of sf_commands : SFC_SET_NORM_DOUBLE, + SFC_SET_NORM_FLOAT, SFC_GET_LIB_VERSION and SFC_GET_LOG_INFO. Thanks to + Kyroz for pointing out these errors. + + * doc/command.html + Correct documented return values for SFC_SET_NORM_DOUBLE and + SFC_SET_NORM_FLOAT. Thanks to Kyroz again. + +2005-05-17 Erik de Castro Lopo + + * regtest/* + Add new files for sndfile-regtest program. + + * configure.ac Makefile.am + Hook regetest into build. + + * src/wav.c src/common.c + Fix a regression where long ICMT chunks were causing the WAV parser + to exit. + +2005-05-15 Erik de Castro Lopo + + * libsndfile.spec.in + Add html docs to the files section as suggested by Karsten Jeppesen. + + * src/aiff.c + Fix parsing of odd length ANNO chunks. + +2005-05-13 Erik de Castro Lopo + + * src/common.h + Change the include guard to prevent clashes with other code. + +2005-05-12 Erik de Castro Lopo + + * examples/sndfile-play.c + Improve error handling in code for playback under Linux/ALSA. + +2005-05-10 Erik de Castro Lopo + + * src/ircam.c + Fix writing of IRCAM files on big endian systems (thanks to Axel Röbel). + + * src/wav.c + Add workaround for files created by the Peak audio editor on Mac which can + produce files with very short LIST chunks (thanks to Jonathan Segel who + supplied the file). + +2005-04-30 Erik de Castro Lopo + + * src/aiff.c + Apply a patch From David Viens to make the parsing of basc chunks more + robust. + + * src/wav.c + Another patch from David Viens to write correct wavex channel masks for + the most common channel configurations. + +2005-04-08 Erik de Castro Lopo + + * src/command.c + Only allow FLAC in the format arrays if FLAC is enabled. Thanks to + Leigh Smith. + +2005-03-09 Erik de Castro Lopo + + * src/common.h + Add a directory field for storing the file directory to the SF_PRIVATE + struct. + + * src/sndfile.c + Grab the directory name when copying the file path. + + * src/file_io.c + Cleanup psf_open_rsrc() and also check for resource fork in + .AppleDouble/filename. + +2005-03-01 Erik de Castro Lopo + + * src/svx.c + Fix a bug in the printing of the channel count. Bug reported by Michael + Schwendt. Thanks. + +2005-01-26 Erik de Castro Lopo + + * src/paf.c + Fix a seek bug for 24 bit PAF files. + + * tests/write_read_test.tpl + Update write_read_test to trigger the previously hidden PAF seek bug. + +2005-01-25 Erik de Castro Lopo + + * src/aiff.c src/w64.c src/wav.c + Do not return a header parse error when the log buffer overflows. + Continuing parsing works even on files where the log buffer does overflow. + This avoids a bug on some weirdo WAV (and other) files. + + * src/common.h src/sndfile.c + Remove SFE_LOG_OVERRIN error and its associated error message. + + * src/file_io.c + Fix a rsrc fork problem on MacOSX. + +2004-12-31 Erik de Castro Lopo + + * src/sndfile-play.c + In the ALSA output code, added call to snd_pcm_drain() just before + snd_pcm_close() as suggested by Thomas Kaeding. + In the OSS output code, added two ioctls (SNDCTL_DSP_POST and + SNDCTL_DSP_SYNC) just before the close of the audio device. + + * tests/virtual_io_test.c tests/Makefile.am + Add a new test program (currently empty) and add it to the build. + +2004-12-29 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.h src/common.h src/file_io.c + src/create_symbols_file.py + Apply patch from Steve Baker which is the beginnings of a virtual + I/O interface. + +2004-12-23 Erik de Castro Lopo + + * src/*.c src/sndfile.h.in + Const-ify the write path throughout the library. + +2004-12-14 Erik de Castro Lopo + + * doc/development.html + Minor improvements. + +2004-11-29 Erik de Castro Lopo + + * doc/bugs.html + Minor improvements. + +2004-11-18 Erik de Castro Lopo + + * src/aiff.c + Add workaround for Logic Platinum AIFF files with broken COMT chunks. + +2004-11-16 Erik de Castro Lopo + + * doc/FAQ.html + Remove some ambiguities in the SD2 FAQ answer. + +2004-11-15 Erik de Castro Lopo + + * Win32/sndfile.h Win32/config.h MacOS9/sndfile.h MacOS9/config.h + Updates from autoconfig versions. + +2004-11-13 Erik de Castro Lopo + + * src/aiff.c + Fix parsing of COMT chunks. Store SF_STR_COMMENT data in ANNO chunks + instead of COMT chunk. + +2004-11-07 Erik de Castro Lopo + + * src/file_io.c src/common.h + Change the ptr argument to psf_write() from "void*" to a "const void*". + Thanks to Tobias Gehrig for suggesting this. + +2004-10-31 Erik de Castro Lopo + + * src/file_io.c src/common.h + Add functions psf_close_rsrc() and read length of resourse fork into + rsrclength field of SF_PRIVATE. + + * src/sd2.c + Make sure resource fork gets closed. + + * tests/util.tpl + Add functions to check for file descriptor leakage. + + * src/write_read_test.tpl + Use the file descriptor leak checks. + + * src/sndfile.h.in + Add SFC_GET_LOOP_INFO and SF_LOOP_INFO struct. + + * src/common.h + Add SF_LOOP_INFO pointer to SF_PRIVATE. + + * src/wav.c src/aiff.c + Improve and add parsing of 'ACID' and 'basc' chunks, filling in + SF_LOOP_INFO data in SF_PRIVATE. + +2004-10-30 Erik de Castro Lopo + + * src/sd2.c + Further cleanup: remove printfs, change snprintf to LSF_SNPRINTF. + + * Win32/config.h Win32/sndfile.h + Updates. + + * tests/util.tpl + Add win32 macro for snprintf. + +2004-10-29 Erik de Castro Lopo + + * src/sfendian.h + Add macros : H2BE_SHORT, H2BE_INT, H2LE_SHORT and H2LE_INT. + + * src/sd2.c + Use macros to make sure writing SD2 files on little endian machines works + correctly. + + * tests/util.tpl + Add a delete_file() function which also deletes the resource fork of SD2 + files. + + * tests/write_read_test.tpl + Use delete_file() so that "make distcheck" works. + +2004-10-28 Erik de Castro Lopo + + * src/sndfile.c src/file_io.c + Move resource filename construction and testing to psf_open_rsrc(). + + * src/common.h src/sndfile.c + Add error SFE_SD2_FD_DISALLOWED. + + * tests/util.tpl tests/*.(c|tpl) + Add and allow_fd parameter to test_open_file_or_die() so that use of + sf_open_fd() can be avoided when opening SD2 files. + +2004-10-27 Erik de Castro Lopo + + * src/wav.c + Update ACID chunk parsing. + + * src/sd2.c + More fixes for files with large resource forks. + +2004-10-23 Erik de Castro Lopo + + * src/common.h src/sndfile.c + Add error numbers and messages for sd2 files. + + * src/sd2.c + Reading of sd2 (resource fork version) now seems to be working. + +2004-10-17 Erik de Castro Lopo + + * src/file_io.h + Update file_io.c to include win32 psf_rsrc_open(). + + * tests/floating_point_test.tpl + Remove use of __func__ in test programs (MSVC++ doesn't grok this). + + * Win32/(config|sndfile).h MacOS9/(config|sndfile).h + Updates. + +2004-10-13 Erik de Castro Lopo + + * src/sfendian.h + Fix endswap_int64_t_(array|copy). + + * src/test_endswap.(tpl|def) + Add tests for above and inprove all tests. + +2004-10-12 Erik de Castro Lopo + + * src/sfendian.h + Improve type safety, add endswap_double_array(). + + * src/double64.c + Use endswap_double_array() instead of endswap_long_array(). + + * src/test_endswap.(tpl|def) src/Makefile.am + Add preliminary endswap tests and hook into build system. + +2004-10-06 Erik de Castro Lopo + + * src/configure.ac src/makefile.am + Finally fix the bulding of DLLs on Win32/MinGW. + + * tests/makefile.am + Fix running of tests on Win32/MinGW. + +2004-10-01 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c tests/floating_point_test.tpl + Rename SFC_SET_FLOAT_INT_MULTIPLIER to SFC_SET_SCALE_FLOAT_INT_READ. + + * doc/command.html + Document SFC_SET_SCALE_FLOAT_INT_READ. + +2004-09-30 Erik de Castro Lopo + + * tests/floating_point_test.(tpl|def) + Derived from floating_point_test.c. + Add (float|double)_(short|int)_test functions. + + * tests/util.(tpl|def) + Make separate float and double versions of gen_windowed_sine(). + + * tests/write_read_test.tpl + Fix after changes to gen_windowed_sine(). + + * src/(float32|double64).c + Implement SFC_SET_FLOAT_INT_MULTIPPLIER. + +2004-09-29 Erik de Castro Lopo + + * acinclude.m4 + Fix warnings from automake 1.8 and later. + + * examples/sndfile-info.c + Add a "fflush (stdout)" after printing Win32 message. + +2004-09-28 Erik de Castro Lopo + + * Win32/Makefile.mingw.in + Add a "make install" target. + +2004-09-24 Erik de Castro Lopo + + * src/sndfile.h.in src/common.h src/sndfile.c src/command.c + Start work on adding command SFC_SET_FLOAT_INT_MULTIPLIER. + +2004-09-22 Erik de Castro Lopo + + * examples/sndfile-convert.c + Fix a bug converting stereo integer PCM files to float. + +2004-09-22 Erik de Castro Lopo + + * examples/sndfile-play.c + Appy patch from Conrad Parker to make Mac OSX error messages more + consistent and informative. + + * doc/api.html + Fix a HTML HREF which was wrong. + + * doc/win32.html + Add information about when nmake fails. + +2004-09-05 Erik de Castro Lopo + + * examples/sndfile-play.c + Another patch from Denis Cote to prevent race conditions. + +2004-09-02 Erik de Castro Lopo + + * src/common.h src/ms_adpcm.c src/ima_adpcm.c + Fix alternative to ISO standard flexible struct array feature for broken + compilers. + +2004-08-31 Erik de Castro Lopo + + * src/common.h src/string.c src/sndfile.c + Make sf_set_string() return an error if trying to set a string when in + read mode. + +2004-08-29 Erik de Castro Lopo + + * src/common.h + Change the unnamed union into a named union so gcc-2.95 will compile it. + + * src/*.c + Fixes to allow for the above change. + +2004-08-20 Erik de Castro Lopo + + * examples/sndfile-play.c + Fixes for Win32. Thanks to Denis Cote. + + * Win32/Win32/Makefile.(msvc|mingw.in) + Fix build system after removal of sfendian.h. + Build sndfile-convert. + + * src/Makefile.am + Remove sfendian.c from dependancies. + +2004-08-10 Erik de Castro Lopo + + * src/sndfile.h.in + Fix typo in comments (thanks Tommi Sakari Uimonen). + +2004-07-31 Erik de Castro Lopo + + * tests/(a|u)law_test.c + Minor cleanup. + +2004-07-29 Erik de Castro Lopo + + * src/(pcm|float|double64|ulaw|alaw|xi).c + Optimise read/write loops by removing a redundant variable. + +2004-07-24 Erik de Castro Lopo + + * src/file_io.c + Remove call to fsync() in psf_close(). + +2004-07-19 Erik de Castro Lopo + + * src/pcm.c + Inline x2y_array() functions where possible. + + * configure.ac + Detect presence of type int64_t. + + * src/sfendian.c src/sfendian.h + Move functions in the first file to the sfendian.h as static inline + functions. + Improve endswap_long_*() where possible. + +2004-07-17 Erik de Castro Lopo + + * src/pcm.c + When converting from unsigned char to float or double, subtract 128 before + converting to float/double rather than after to save a floating point + operation as suggested by Stefan Briesenick. + + * src/(pcm|sfendian|alaw|ulaw|double64|float32).c + Optimize inner loops by changing the loop counting slightly as suggested + by Stefan Briesenick. + + * configure.ac + Detect presence of . + + * src/sfendian.h + Use if present as suggested by Stefan Briesenick. + + * src/pcm.c + Update bytewapping. + +2004-07-02 Erik de Castro Lopo + + * src/common.h src/*.c + Change the psf->buffer field of SF_PRIVATE into a more type safe union with + double, float, int etc elements. + +2004-06-28 Erik de Castro Lopo + + * examples/sndfile-play.c + Merge slightly modifed patch from Stanko Juzbasic which allows playback of + mono files on MacOSX. + +2004-06-25 Erik de Castro Lopo + + * examples/sndfile-convert.c + Move copy_metadata() after the second sf_open(). + +2004-06-21 Erik de Castro Lopo + + * examples/sndfile-convert.c + Fix a bug which caused the program to go into an infinite loop if the source + file has no meta-data. Thanks to Ron Parker for reporting this. + + * src/sndfile.h.in + Add SF_STR_FIRST and SF_STR_LAST to allow enumeration of string types. + + * Win32/sndfile.h MacOS9/sndfile.h + Update these as per the above file. + +2004-06-17 Erik de Castro Lopo + + * configure.ac src/common.h src/ogg.c src/sndfile.c src/sndfile.h.in + src/Makefile.am + Apply large patch from Conrad Parker implementing Ogg Vorbis, Ogg Speex and + Annodex support via liboggz and libfishsound. Thanks Conrad. + +2004-06-15 Erik de Castro Lopo + + * src/avr.c src/ircam.c src/nist.c src/paf.c src/xi.c + Add cast to size_t for some parameters passed to psf_binheader_writef. This + is Debian bug number 253490. Thanks to Anand Kumria and Andreas Jochens. + + * src/w64.c + Found and fixed a bug resulting from use of size_t when writing W64 'fmt ' + chunk. + +2004-06-14 Erik de Castro Lopo + + * configure.ac + Bump version to 1.0.10 ready for release. + + * Makefile.am + Remove redundant files (check_libsndfile.py libsndfile_version_convert.py) + from distribution tarball. + + * tests/header_test.tpl + Fix uninitialised variable. + + * src/GSM610/short_term.c + Fix compiler warning on MSVC++. + +2004-05-23 Erik de Castro Lopo + + * src/wav.c + Improve record keeping of chunks seen and return an error if a file with + unusual chunks is opened in mode SFM_RDWR. + + * src/mmreg.h + This file not needed so remove it. + +2004-05-22 Erik de Castro Lopo + + * tests/header_test.tpl + Add extra_header_test(). + + * src/common.h src/sndfile.c + Add SFE_RDWR_BAD_HEADER error number and string. + +2004-05-21 Erik de Castro Lopo + + * tests/utils.tpl tests/*.c tests/*.tpl + Add a line number argument to check_log_buffer_or_die() and update all + files that use that function. + + * tests/header_test.tpl + Modify/update tests for files opened SFM_RDWR and SFC_UPDATE_HEADER_AUTO. + + * src/aiff.c src/wav.c + Fix another bug in AIFF and WAV files opened in SFM_RDWR and using + SFC_UPDATE_HEADER_AUTO. + + * src/test_file_io.c + Add a test for psf_ftruncate() function. + +2004-05-19 Erik de Castro Lopo + + * src/sndfile.c + Fix another weird corner case bug found by Martin Rumori. Thanks. + + * tests/header_test.(tpl|def) + Two new files to test for the absence of the above bug and include tests + moved from tests/misc_test.c. + + * tests/Makefile.am + Hook new tests into build/test system. + + * tests/misc_test.c + Remove update_header_test() which has been moved to the new files above. + +2004-05-16 Erik de Castro Lopo + + * src/aiff.c + Fixed a bug reported by Martin Rumori on the LAD list. If a file created + with a format of SF_FORMAT_FLOAT and then closed before any data is written + to it, the header can get screwed up (PEAK chunk gets overwritten). + + * tests/write_read_test.tpl + Add a test (empty_file_test) for the above bug. + +2004-05-13 Erik de Castro Lopo + + * Win32/Makefile.mingw.in + Added a Makefile for MinGW (needs to be processed by configure). + + * src/mmsystem.h src/mmreg.h + Add files from the Wine project (under the LGPL) to allow build of + sndfile-play.exe under MinGW. + +2004-05-12 Erik de Castro Lopo + + * src/GSM610/gsm610_priv.h + Replace ugly macros with inline functions. + + * src/GSM610/*.c + Remove temporary variables used by macros and other minor fixes required by + above change. + +2004-05-10 Erik de Castro Lopo + + * tests/pipe_test.tpl tests/stdio_test.c Win32/Makefile.msvc + Make sure these programs compile (even though they do nothing) on Win32 + and add them to the "make check" target. + + * src/sfendian.h + Fix warning on Sparc CPU and code cleanup. + +2004-05-09 Erik de Castro Lopo + + * src/file_io.c + Fix warning messages when compiling under MinGW. + +2004-05-01 Erik de Castro Lopo + + * configure.ac + Set HAVE_FLEXIBLE_ARRAY in src/config.h depending on whether the compiler + accepts the flexible array struct member as per 1999 ISO C standard. + + * src/common.h src/ima_adpcm.c src/paf.c src/ms_adpcm.c + Added ugly #if HAVE_FLEXIBLE_ARRAY and provided a non-standards compliant + hack for non 1999 ISO C compliant compilers. + +2004-04-26 Erik de Castro Lopo + + * src/strings.c + If adding an SF_STR_SOFTWARE string, only append libsndfile-X.Y.Z if the + string does not already have libsndfile in the string. Thanks to Conrad + Parker. + + * tests/string_test.c + Add test to verify the above. + + * examples/sndfile-convert.c + Add ability to transcode meta data as well (Conrad Parker). + +2004-04-25 Erik de Castro Lopo + + * doc/command.html + Fix minor error. Thanks to Simon Burton. + + * doc/win32.html + Started adding instructions for compiling libsndfile under MinGW. + + * configure.ac + Add --enable-bow-docs to enable black text on a white background HTML docs. + + * doc/libsndfile.css.in + This is now a template file for configure which sets the foreground and + background colours. + +2004-04-20 Erik de Castro Lopo + + * configure.ac + Do some MinGW fixes. + + * configure.ac doc/Makefile.am + Install HTML docs when doing make install. + +2004-04-19 Erik de Castro Lopo + + * examples/sndfile-info.c + Print out the dB level with the signal max. + +2004-04-15 Erik de Castro Lopo + + * src/file_io.c + Define S_ISSOCK in src/file_io.c if required. + +2004-04-03 Erik de Castro Lopo + + * configure.ac + Improve printout configuration summary (as suggested by Axel Röbel). + + * doc/index.html + Add link to pre-release location. + + * src/sndfile.h.in + Remove comma after last element of enum. + + * src/float32.c src/double64.c + Fix read/write of float/double encoded raw files to/from pipes. + + * tests/pipe_test.c tests/pipe_test.tpl tests/pipe_test.def + Turn pipe_test.c into an autogenerated file and add tests for reading/ + writing floats and doubles. + + * tests/Makefile.am + Hook tests/pipe_test.* into build system. + +2004-04-02 Erik de Castro Lopo + + * configure.ac acinclude.m4 + Rename AC_C_STRUCT_HACK macro to AC_C99_FLEXIBLE_ARRAY. + +2004-03-31 Erik de Castro Lopo + + * tests/misc_test.c + Perform update_header_test in RDWR mode as well. + + * src/aiff.c + Fix problems when updating header in RDWR mode. + +2004-03-30 Erik de Castro Lopo + + * src/wav.c src/w64.c src/wav_w64.c + Integrate code supplied by David Viens for supporting microsoft's + WAVEFORMATEXTENSIBLE stuff. Thanks David for supplying this. + + * configure.ac doc/*.html + Bump version to 1.0.9. + +2004-03-28 Erik de Castro Lopo + + * src/command.c src/sndfile.c src/sndfile.h.in src/wav.c + Started work on supporting microsoft's WAVEFORMATEXTENSIBLE gunk. + +2004-03-26 Erik de Castro Lopo + + * src/avr.c + New file to handle Audio Visual Resaerch files. + + * src/sndfile.h.in src/common.h src/sndfile.c src/command.c + Hook AVR into everything else. + + * tests/Makefile.am tests/write_read_test.tpl tests/misc_test.c + Add testing for AVR files. + +2004-03-22 Erik de Castro Lopo + + * src/file_io.c + Fix psf_set_file() for win32. Thanks to Vincent Trussart (Plogue Art et + Technologie) for coming up with the solution. + +2004-03-21 Erik de Castro Lopo + + * tests/write_read_test.tpl + Fixed a bug that was causing valgrind to report a memory leak. The bug was + in the test code itself, not the library. + +2004-03-20 Erik de Castro Lopo + + * examples/generate.cs + An example showing how to use libsndfile from C#. Thanks to James Robson + for providing this. + +2004-03-19 Erik de Castro Lopo + + * src/common.c + Fix problems with WAV files containing large chunks after the 'data' + chunk. Thanks to Koen Tanghe for providing a sample file. + +2004-03-17 Erik de Castro Lopo + + * configure.ac + Detect presense of ALSA (Advanced Linux Sound Architecture). + + * examples/sndfile-play.c + Add ALSA output support. + + * examples/Makefile.am + Add ALSA_LIBS to link line of sndfile-play.c. + +2004-03-15 Erik de Castro Lopo + + * acinclude.m4 + Add new macro (AC_C_STRUCT_HACK) to detect whether the C compiler allows + the use of the what is known as the struct hack introduced by the 1999 ISO + C Standard. + + * configure.ac + The last release would not compile with gcc-2.95 due to the use of features + (ie struct hack) introduced by the 1999 ISO C Standard. + Add check to make sure compiler handles this and bomb out if it doesn't. + +2004-03-14 Erik de Castro Lopo + + * tests/write_read_test.tpl + Fix compiler warning on Win32. + + * src/file_io.c + Fix use of an un-initialised variable in Win32 stuff. + + * Win32/config.h examples/sndfile-play.c + Win32 fixes. + +2004-03-10 Erik de Castro Lopo + + * configure.ac + Fix bug which occurres when configuring for MinGW. + If compiler is gcc and cross compiling use -nostdinc. + +2004-03-09 Erik de Castro Lopo + + * src/common.h src/aiff.c src/wav.c src/float32.c src/double64.c + src/sndfile.c + Fix a bug with PEAK chunk handling for files with more than 16 channels. + Thanks to Remy Bruno for finding this. + +2004-03-08 Erik de Castro Lopo + + * src/common.c + Fix a bug which was preventing WAV files being openned correctly if the + file had a very large header. Thanks to Eldad Zack for finding this. + +2004-03-04 Erik de Castro Lopo + + * configure.ac src/file_io.c + Fix cross-compiling from Linux to Win32 using the MinGW tools. + +2004-03-01 Erik de Castro Lopo + + * src/create_symbols_file.sh + Christian Weisgerber pointed out that the shell script did not run on a + real Bourne shell although it did run under Bash in Bourne shell mode. + + * src/create_symbols_file.py + Rewrite of above in Python. Also add support for writing Win32 .def files. + The Python script generates Symbols.linux, Symbols.darwin and + libsndfile.def (Win32 version). These files get shipped with the tarball + so there should not be necessary to run the Python script when building + the code from the tarball. + + * configure.ac src/Makefile.am Win32/Makefile.am + Hook new Python script into the build system. + +2004-02-25 Erik de Castro Lopo + + * src/configure.ac + Add --enable-gcc-werror option and move GCC specific stuff down. + +2004-02-24 Erik de Castro Lopo + + * acinclude.m4 configure.ac + Fix clip mode detection (tested in one of HP's testdrive Itanium II boxes). + + * src/file_io.c + Added check for sizeof (off_t) != sizeof (sf_count_t) to prevent recurrence + of missing large file support on Linux and Solaris. + +2004-02-19 Erik de Castro Lopo + + * examples/sndfile-play.c + Fix a MacOSX specific bug which was caused by a space being inserted in + the middle of a file name. + + * configure.ac src/Makefile.am examples/Makefile.am + Fix a couple of MacOSX build issues. + +2004-02-17 Erik de Castro Lopo + + * doc/command.html + Document SFC_SET_CLIPPING and SFC_GET_CLIPPING. + +2004-02-14 Erik de Castro Lopo + + * doc/*.html + Applied patch from Frank Neumann (author of lakai) which fixes many minor + typos in documentation. Thanks Frank. + +2004-02-13 Erik de Castro Lopo + + * ChangeLog + Changed my email address throughout source and docs. + +2004-02-08 Erik de Castro Lopo + + * src/file_io.c + Make sure config.h is included before stdio.h to make sure large file + support is enabled on Linux (and Solaris). + + * tests/misc_test.c + Disable update_header test on Win32. This should work but doesn't and + I'm not sure why. + + * Make.bat Win32/Makefile.msvc + Updates. + +2004-01-07 Erik de Castro Lopo + + * src/common.h + Changed logindex, headindex and headend files of SF_PRIVATE from unsigned + int to int to prevent weird arithmetic bugs. + + * src/common.c src/aiff.c src/wav.c src/w64.c + Fixed compiler warnings resulting from above change. + +2004-01-06 Erik de Castro Lopo + + * src/common.c + Fixed a bug in header reader for some files with data after the sample data. + +2003-12-29 Erik de Castro Lopo + + * tests/lossy_comp_test.c tests/Makefile.am + Add tests for AIFF/IMA files. + +2003-12-26 Erik de Castro Lopo + + * src/macbinary3.c src/macos.c + Two new files required for handling SD2 files. + + * src/common.h + Add prototypes for functions in above two files. + + * src/Makefile.am + Hook new files into build system. + +2003-12-21 Erik de Castro Lopo + + * configure.ac + Add checks for mmap() and getpagesize() which might be used at some time + for faster file reads. + Add detection of MacOSX. + +2003-12-13 Erik de Castro Lopo + + * doc/FAQ.html + Minor mods to pkg-config section. + +2003-12-12 Erik de Castro Lopo + + * src/create_symbols_file.sh + Andre Pang (also known as Ozone) pointed out that on MacOSX, all non + static symbols are exported causing troubles when trying to link + libsndfile with another library which has any of the same symbols. + He fixed this by supplying the MacOSX linker with a file containing + all the public symbols so that only they would be exported and then + supplied a patch for libsndfile. + This wasn't quite ideal, because I would have to maintain two (3 if + you include Win32) separate files containing the exported symbols. + A better solution was to create this script which can generate a + Symbols file for Linux, MacoSX and any other OS that supports + minimising the number of exported symbols. + + * configure.ac src/Makefile.am + Hook the new script into the build process. + +2003-12-10 Erik de Castro Lopo + + * doc/index.html + Added comments about Steve Dekorte's SoundConverter scam. + +2003-12-07 Erik de Castro Lopo + + * src/file_io.c + Axel Röbel pointed out that on Mac OSX a pipe is not considered a fifo + (S_ISFIFO (st.st_mode) is false) but a socket (S_ISSOCK (st.st_mode) is + true). The test has therefore been changed to is S_ISREG and anything + which which does not return true for S_ISREG is considered a pipe. + +2003-11-25 Erik de Castro Lopo + + * tests/misc_test.c + Fix update_header_test to pass SDS. + + * src/sds.c + More minor fixes. + + * tests/floating_point_test.c + Add test for SDS files. + + * src/command.c + Add SDS to major_formats array. + +2003-11-24 Erik de Castro Lopo + + * tests/write_read_test.tpl tests/misc_test.c + Add tests for SDS files. + + * src/sds.c + Fix a bug in header update code. + +2003-11-23 Erik de Castro Lopo + + * src/sds.c + Get file write working. + + * src/paf.c + Fix a potential bug in paf24_seek(). + +2003-11-04 Erik de Castro Lopo + + * doc/FAQ.html + Add Q/A about u-law encoded WAV files. + + * Win32/*.h + Updated so it compiles on Win32. + +2003-11-03 Erik de Castro Lopo + + * examples/sndfile-convert.c + Add -alaw and -ulaw command line arguments. + + * configure.ac + Add library versioning comments. + Add arguments to AC_INIT. + +2003-10-28 Erik de Castro Lopo + + * src/file_io.c + Ross Bencina has contributed code to replace all of the (mostly broken) + Win32 POSIX emulation calls with calls the native Win32 file I/O API. + This code still needs testing but is likely to be a huge improvemnt + of support for Win32. Thanks Ross. + +2003-10-27 Erik de Castro Lopo + + * src/dwvw.c + Removed filedes field from the DWVW_PRIVATE struct. + + * src/file_io.c + Change psf_fopen() so it returns psf->error instead of the file descriptor. + Add new functions psf_set_stdio() and psf_set_file(). + + * src/sndfile.c + Change these to work with changed psf_fopen() return value. + Remove all uses of psf->filedes from sndfile, making it easier to slot native + Win32 API file handling functions. + + * src/test_file_io.c + Minor changes to make it compile with new file_io.c stuff. + +2003-10-26 Erik de Castro Lopo + + * src/gsm610.h + Rename a variable from true to true_flag. As Ross Bencina points out, + true is defined in the C99 header . + + * src/file_io.c + If fstat() fails, return SF_TRUE instead of -1 (Ross Bencina). + +2003-10-09 Erik de Castro Lopo + + * src/common.h + Increase the size of SF_BUFFER_LEN and SF_HEADER_LEN. + + * src/sndfile.c + Fix sf_read/write_raw which were dividing by psf->bytwidth and + psf->blockwidth which can both be zero. + + * examples/sndfile-info.c + Increase size of BUFFER_LEN. + +2003-09-21 Erik de Castro Lopo + + * configure.ac + Add checks for and ssize_t. + Other Win32/MinGW checks. + + * src/aiff.c src/au_g72x.c src/file_io.c src/gsm610.c src/interleave.c + src/paf.c src/sds.c src/svx.c src/voc.c src/w64.c src/wav.c src/xi.c + Fix compiler warnings. + +2003-09-20 Erik de Castro Lopo + + * tests/scale_clip_test.tpl + Add definition of M_PI if needed. + +2003-09-19 Erik de Castro Lopo + + * configure.ac + Detect if S_IRGRP is declared in . + + * src/file_io.c tests/*.tpl tests/*.c + More fixes for Win32/MSVC++ and MinGW. MinGW does have but that + file doesn't declare S_IRGRP. + +2003-10-18 Erik de Castro Lopo + + * src/config.h.in + Add comment stating that the sf_count_t typedef is determined when + libsndfile is being compiled. + + * tests/utils.tpl + Modified so that utils.c gets one copy of the GPL and not two. + + +2003-09-17 Erik de Castro Lopo + + * Win32/unistd.h src/sf_unistd.h + Move first file to the second. This will help for Win32/MSVC++ and MinGW. + + * Win32/Makefile.am src/Makefile.am + Changed in line with above. + + * Win32/Makefile.msvc + Removed "/I Win32" which is no longer required. + + * src/file_io.c src/test_file_io.c tests/*.tpl tests/*.c + If HAVE_UNISTD_H include else include . This should + work for Win32, MinGW and other fakes Unix-like OSes. + + * src/*.c + Removed #include from files which didn't need it. + +2003-09-16 Erik de Castro Lopo + + * libsndfile.spec.in + Apply fix from Andrew Schultz. + +2003-09-07 Erik de Castro Lopo + + * src/vox_adpcm.c + Only set psf->sf.samplerate if the existing value is invalid. + +2003-09-06 Erik de Castro Lopo + + * examples/sndfile-play.c + Started adding support for ALSA output. + +2003-09-04 Erik de Castro Lopo + + * src/sndfile.h.in + Removed from sndfile.h. + + * src/*.c examples/*.c tests/*.c tests/*.tpl + Added where needed. + +2003-09-02 Erik de Castro Lopo + + * src/common.h + Added ARRAY_LEN, SF_MAX and SF_MIN macros. + +2003-08-19 Erik de Castro Lopo + + * doc/index.html + Remove statements about alternative licensing arrangements. + +2003-08-17 Erik de Castro Lopo + + * MacOS MacOS9 Makefile.am configure.ac + Change directory name from MacOS to MacOS9 + + * MacOS9/MacOS9-readme.txt + Change name to make it really obvious, add text to top of file to make it + still more obvious again. + +2003-08-16 Erik de Castro Lopo + + * src/test_log_printf.c + Add tests for %u conversions. + + * src/common.c + Fix psf_log_printf() %u conversions. + +2003-08-15 Erik de Castro Lopo + + * src/aiff.c + Fixed a bug where opening a file with a non-trival header in SFM_RDWR mode + would over-write part of the header. Thanks to Axel Röbel for pointing + this out. Axel also provided a patch to fix this but I came up with a + neater and more general solution. + Return error when openning an AIFF file with data after the SSND chunk + (Thanks Axel Röbel). + + * tests/aiff_rw_test.c + Improvements to test program which will later allow it to be generalised to + test WAV, SVX and others as required. + +2003-08-14 Erik de Castro Lopo + + * tests/pipe_test.c + Add useek_pipe_rw_test() submitted by Russell Francis. + + * src/sndfile.c + In sf_open_fd(), check if input file descriptor is a pipe. + + * src/sndfile.[ch] + Fix typo in variable name do_not_close_descriptor. + +2003-08-13 Erik de Castro Lopo + + * src/test_log_printf.c + Improve the tests for %d and %s conversions. + + * src/common.c + Fixed a few problems in psf_log_printf() found using new tests. + +2003-08-06 Erik de Castro Lopo + + * configure.ac + Add -Wwrite-strings warning to CFLAGS if the compiler is GCC. Thanks to + Peter Miller (Aegis author) for suggesting this and supplying a patch. + + * src/*.c examples/*.c tests/*.c + Fix all compiler warnings arising from the above. + +2003-08-02 Erik de Castro Lopo + + * tests/aiff_rw_test.c tests/Makefile.am + New test program to check for errors re-writing the headers of AIFC files + opened in mode SFM_RDWR. + +2003-07-21 Erik de Castro Lopo + + * examples/sndfile-play.c + Applied a patch from Tero Pelander to allow this program to run on systems + using devfs which used /dev/sound/dsp instead of /dev/dsp. + +2003-07-11 Erik de Castro Lopo + + * doc/new_file_type.HOWTO + Updated document. Still incomplete. + +2003-06-29 Erik de Castro Lopo + + * src/sndfile.c + Fix VALIDATE_SNDFILE_AND_ASSIGN_PSF which was returning an error rather + than saving it and returning zero. + +2003-06-25 Erik de Castro Lopo + + * src/file_io.c + Two fixes for Mac OS9. + Fix all casts from sf_count_t to ssize_t (not size_t). + +2003-06-22 Erik de Castro Lopo + + * src/wav.c + Fix for reading files with RIFF length of 8 and data length of 0. + +2003-06-14 Erik de Castro Lopo + + * src/*.c tests/*.c tests/*.tpl + Added comments to mark code for removal when make Lite version of + libsndfile. + +2003-06-09 Erik de Castro Lopo + + * examples/sndfile-convert.c + Add extra error checking for unrecognised arguments. + +2003-06-08 Erik de Castro Lopo + + * src/ima_adpcm.c + Started adding code to write IMA ADPCM encoded AIFF files. + + * src/test_log_printf.c src/Makefile.am + New file to test psf_log_printf() function and add hooks into build system. + + * src/common.c + Move psf_log_printf() function to top of the file and only compile the rest + of the file if if PSF_LOG_PRINTF_ONLY is not defined. + +2003-06-03 Erik de Castro Lopo + + * Win32/config.h Win32/sndfile.h + Updated with new config variables. + + * Win32/unistd.h src/file_io.c + Added implementation of S_ISFIFO macro which Win32 seems to lack and is + used in src/file_io.c. + + * tests/utils.tpl + Added #include to pull in Win32/unistd.h so it compiles for + Win32. + + * src/Makefile.msvc + Added src\test_file_io.exe build target and run this as the very first + test. + + * tests/win32_test.c + Add support for testing Cygwin32. + + * configure.ac + Detect POSIX fsync() and fdatasync() functions. + + * src/file_io.c + If compiling for Cygwin, call fsync() before calling fstat() to retrieve + file length. + + * tests/pcm_test.tpl + Add a test for lrintf() function. This was required to detect a really + broken lrint() and lrintf() on Cygwin. + + * tests/misc_test.c + Don't run permission test when compiling under Cygwin. + + * src/float_cast.h + Fix fallback macro for lrint() and lrintf() to cast to long instead of int + to match official function prototypes. + +2003-06-02 Erik de Castro Lopo + + * examples/sndfile-convert.c + Modifications to improve accuracy of conversions; use double data for + floating point and int for everything else. + + * src/ima_apdcm.c + Completed work on decoding IMA ADPCM encoded AIFF files. Still need to + get encoding working. + +2003-05-28 Erik de Castro Lopo + + * src/aiff.c src/ima_adpcm.c + Start working on getting IMA ADPCM encoded AIFF files working. + +2003-05-27 Erik de Castro Lopo + + * configure.ac + Fixed the touch command for when the autogen program is not found (Matt + Flax). + + * src/ulaw.c src/alaw.c + Made these pipe-able. + +2003-05-24 Erik de Castro Lopo + + * src/paf.c src/ircam.c + Fixed writing to pipe. + + * src/wav.c src/aiff.c src/nist.c src/mat*.c src/svx.c src/w64.c + Return SFE_NO_PIPE_WRITE if an attempt is made to write to a pipe. + +2003-05-23 Erik de Castro Lopo + + * examples/sndfile-info.c + Modified to detect unknown file lengths. + + * src/mat4.c + Fix reading from a pipe. + +2003-05-22 Erik de Castro Lopo + + * tests/pipe_test.c + Add more file types to tests. + + * src/mat4.c + Removed explicit setting of psf->sf.seekable to SF_TRUE. + + * tests/utils.tpl + Add macro for generating and check data in the stdio and pipe tests. + + * tests/stdout_test.c tests/stdin_test.c + Use the above macro to generate known data on output and check data on + input. + + * src/voc.c src/htk.c common.h sndfile.c + Disallow reading/writing VOC and HTK files from/to pipes be returning new + error values. + + * src/w64.c + Fixes to allow reading from a pipe. + +2003-05-21 Erik de Castro Lopo + + * configure.ac src/sndfile.h.in + When the configure script determines the sizeof (sf_count_t), also set the + value of SF_COUNT_MAX in sndfile.h. + + * configure.ac + Remove -pedantic flag from default GCC compiler flags. + + * tests/pipe_test.c + Add a pipe_read_test() before doing pipe_write_test(). + + * tests/scale_clip_test.c + Add test to make sure non-normalized values also clip in the right way. + +2003-05-18 Erik de Castro Lopo + + * configure.ac + Add test to detect processor clipping capabilities. + + * tests/stdin_test.c tests/stdout_test.c + Fix a pair of compiler warnings. + + * src/common.h + Add new pipeoffset field to SF_PRIVATE. This will contain the current file + offset when operating on a pipe. + + * src/common.c + Removed direct calls to psf_fread()/psf_fseek()/psf_fgets() etc from + psf_binheader_readf and redirect them to new buffered versions + header_read(), header_seek() and header_gets(). + Add "G" format specifier to emulate fgets() functionality with buffering. + This will allow reading some file types from pipes. + + * src/file_io.c + When the file descriptor is a pipe, manintain psf->pipeoffset. + + * src/pvf.c + Change use of psf_fgets() to psf_binheader_readf() as required but changes to header re + + * src/au.c + Fix reading from a pipe. + +2003-05-17 Erik de Castro Lopo + + * src/pcm.c + Add clipping versions of the f2XXX_array() functions to allow option of + clipping data that would otherwise overflow. + + * tests/scale_clip_test.tpl tests/scale_clip_test.def + New files test that clipping option does actually work. + +2003-05-14 Erik de Castro Lopo + + * doc/index.html + Fixed a typo ("OS(" instead of "OS9"). + +2003-05-13 Erik de Castro Lopo + + * tests/open_fail_test.c + Include to prevent warning message of missing declaration of + memset(). + +2003-05-12 Erik de Castro Lopo + + * src/common.h + Add new "add_clipping" field to SF_PRIVATE. + + * src/sndfile.h.in src/sndfile.c + Add command SFC_SET_CLIPPING which sets/resets add_clipping field. + +2003-05-11 Erik de Castro Lopo + + * doc/api.html + Add docs for sf_set_string() and sf_get_string(). + + * src/common.h src/sndfile.c + Add new SFE_STR_BAD_STRING error. + + * tests/stdin_test.c tests/stdout_test.c + Removed all non-error print statements. + + * tests/stdio_test.c tests/pipe_test.c tests/Makefile.am + Add print statements removed from two files above. + +2003-05-10 Erik de Castro Lopo + + * libsndfile.spec.in + Fixed a coulpe of minor errors discovered by someone calling themselves + Agent Smith. + + * src/common.c src/common.h src/file_io.h + Added is_pipe field to SF_PRIVATE and declaration of psf_is_pipe() + function. (Axel Röbel) + + * src/sndfile.c + Fixed determination of whether the file is a pipe. (Axel Röbel) + + * src/paf.c + Force paf24 to start with undefined mode. (Axel Röbel) + + * tests/pipe_test.c + Mods to make this test work and actually do the test on RAW files. (Axel + Röbel). + +2003-05-05 Erik de Castro Lopo + + * src/sndfile.c + Fixed a potential bug where psf->sf.seekable was being set to FALSE when + operating on stdin or stdout but then the default initialiser was reseting + it to TRUE. Thanks to Axel Röbel. + + * src/aiff.c + Fixed a bug in the header parser where it was not handling an odd length + COMM chunk correctly. Thanks to Axel Röbel. + + * src/test_file_io.c + Add more tests. + + * tests/win32_test.c + New file for showing the bugs in the Win32 implementation of the POSIX API. + It also runs on Linux for sanity checking. + + * tests/Makefile.am Win32/Makefile.msvc + Hook the new test program into the build system. + +2003-05-04 Erik de Castro Lopo + + * src/test_file_io.c + New test program to test operation of functions defined in file_io.c. This + should make supporting win32 significantly easier. + + * src/Makefile.am + Hook new test program into the build system. + + * src/file_io.c + Add compile/run time check that sizeof statbuf.st_size and sf_count_t are + the same. + + * src/common.h src/sndfile.c + Added new error code and error message for new check. + + * tests/benchmark.tpl + Fix to use frames instead of samples in SF_INFO. + +2003-05-03 Erik de Castro Lopo + + * src/file_io.c + More stuffing about working around PLAIN OLD-FASHIONED **BUGS** in Win32. + + * examples/sndfile-info.c + Applied patch from Conrad Parker to add "--help" and "-h" options as + well as an improved usage message. + +2003-05-02 Erik de Castro Lopo + + * src/au.c + Added embedded file support. + + * tests/multi_file_test.c + Added tests for embedded AU files. + Added verbose testing mode. + + * src/common.h src/sndfile.c + Added an embedded AU specific error code and message. + + * src/wav.c + Added patch from Conrad Parker which filled in a little more information + about ACIDized WAV files. + +2003-04-30 Erik de Castro Lopo + + * src/file_io.c + Fixed Win32 version of psf_fseek() which was calling psf_get_filelen() + which was in turn calling psf_fseek() which in the end blew the stack. + Now of course this would have been easy to find on Linux, but this blow + up was happening in kernel32.dll and the fscking MSVC++ debugger couldn't + figure out what call caused this (it couldn't even tell me the stack had + overflowed) and was absolutley useless for this debugging exercise. + On top of that, the reason I got into this mess was that windoze doesn't + have a working fstat() function which can return file lengths > 2 Gig. It + HAS a fscking _fstati64() but the file length value is only updated AFTER + the bloody file is closed. That makes it completely useless. + How the hell do people stand working on this crap excuse of an OS? + +2003-04-29 Erik de Castro Lopo + + * Win32/unistd.h src/file_io.c + Moved definitions of S_IGRP etc from file_io.c to unistd.h so that these + can be used in the test programs. + + * Win32/libsndfile.def + Added sf_open_fd. + + * Win32/sndfile.h + Updated to match src/sndfile.h.in. + + * Win32/Makefile.msvc + Added dither.c and htk.c to libsndfile.dll target. + +2003-04-28 Erik de Castro Lopo + + * src/file_io.c + First attempt at getting the Win32 versions of the these functions working. + They still need to be tested. + +2003-04-27 Erik de Castro Lopo + + * src/strings.c + Found and fixed a bug which was causing psf_store_string() to fail on + Motorola 68k processors. Many thanks to Joshua Haberman (Debian maintainer + of libsndfile) for compiling and running debug code to help me debug the + problem. + +2003-04-26 Erik de Castro Lopo + + * src/sndfile.c src/file_io.c src/wav.c src/aiff.c + Much hacking to get reading and writing of embedded files working (ie sound + files at a non-zero files offset). + + * doc/embedded_files.html + First pass atempt at documenting reading/writing embedded files. + +2003-04-21 Erik de Castro Lopo + + * doc/FAQ.html + Updated answer to "Why doesn't libsndfile do interleaving/de-interleaving?" + +2003-04-19 Erik de Castro Lopo + + * src/wav.c src/aiff.c + Fix retrieving and storing of string data from files. Need to be careful + about using psf->buffer for strings. + +2003-04-18 Erik de Castro Lopo + + * src/file_io.c + Fix psf_fseek() for seeks withing embedded files. + +2003-04-15 Erik de Castro Lopo + + * src/sndfile.h.in + Changed the definition of SNDFILE slightly to produce warnings when it isn't + used correctly. This should have zero affect in code which uses the SNDFILE + type correctly. + + * src/sndfile.c + Fixed a few compiler warnings cause by the changes to the SNDFILE type. + +2003-04-12 Erik de Castro Lopo + + * doc/FAQ.html + Added question and answer to the question "How about adding the ability + to write/read sound files to/from memory buffers?". + +2003-04-08 Erik de Castro Lopo + + * tests/write_read_test.tpl + Removed un-needed enums declaring TRUE and FALSE and replaced usage of + these with SF_TRUE and SF_FALSE. + + * tests/multi_file_test.c + New test program to test sf_open_fd() on files containing data other than + a single sound file. + +2003-04-06 Erik de Castro Lopo + + * src/file_io.c + When creating files, set the readable by others flag. This still allows + further restrictions to be enforced by use of the user's umask. Fix + suggested by Eric Lyon. + +2003-04-05 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c + Changed sf_open_fd(). Dropped offset parameter and added a close_desc + parameter. If close desc is TRUE, the file descritpor passed into the + library will be closed when sf_close() is called. + + * tests/utils.tpl + Modified call to sf_open_fd() to set close_desc parameter to SF_TRUE. + +2003-04-04 Erik de Castro Lopo + + * tests/write_read_test.tpl + Add a string (using sf_set_string() function) before and after data section + of all files. This will make sure that if string data can be added, it + doesn't overwrite real audio data. + +2003-04-02 Erik de Castro Lopo + + * src/sndfile.c + Started work on supporting a non-zero offset parameter for sf_open_fd (). + + * src/.c + Removed many uses of psf_fseek (SEEK_END) which to allow for future use of + sf_open_fd() with non-zero offset. + Associated refactoring. + + * src/aiff.c + Implemented functionality required to get sf_get_string() and + sf_set_string() working for AIFF files. + +2003-04-01 Erik de Castro Lopo + + * tests/utils.tpl + Modified test_open_file_or_die() to alternately use sf_open() and + sf_open_fd(). + + * src/svx.c + Fixed a bug which occurred when openning an existing file for read/write + using sf_open_fd(). In this case, the existing NAME chunk needs to be + read into psf->filename. + Fixed printing of sf_count_t types to logbuffer. + +2003-03-31 Erik de Castro Lopo + + * src/sndfile.h.in + Added prototype for new function sf_open_fd(). + + * src/sndfile.c + Moved most of the code in sf_open() to a new function psf_open_file(). + Created new function sf_open_fd() which also uses psf_open_file() but + does not currently support the offset parameter. + + * doc/api.html + Document sf_open_fd(). + +2003-03-09 Erik de Castro Lopo + + * src/sndfile.c + Fixed a memory leak reported by Evgeny Karpov. Memory leak only occurred + when an attempt was made to read and the open() call fails. + +2003-03-08 Erik de Castro Lopo + + * tests/open_fail_test.c + New test program to check for memory leaks when sf_open fails on a valid + file. Currently this must be run manually under valgrid. + + * tests/Makefile.am + Hook new test program into build. + +2003-03-03 Erik de Castro Lopo + + * Octave/sndfile_save.m Octave/sndfile_play.m + Added a -mat-binary option to the octave save command to force the output + to binary mode even if the user has set ascii data as the default. Found + by Christopher Moore. + +2003-02-27 Erik de Castro Lopo + + * doc/dither.html + New file which will document the interface which allows the addition of + audio dither when sample word sizes are being reduced. + + * src/dither.c + More work. + +2003-02-26 Erik de Castro Lopo + + * tests/misc_test.c + In update_header_test(), make HTK files a special case. + + * doc/index.html + Added HTK to the feature matrix. + +2003-02-25 Erik de Castro Lopo + + * src/htk.c + New file for reading/writing HMM Tool Kit files. + + * src/sndfile.h.in src/sndfile.c src/command.c src/Makefile.am + Hook in htk.c + + * tests/write_read_test.tpl tests/misc_test.c tests/Makefile.am + Add tests for HTK files. + +2003-02-22 Erik de Castro Lopo + + * src/wav.c + Fixed a bug where the LIST chunk length was being written incorrectly. + + * tests/string_test.c + Added call to check_log_buffer(). + Minor cleanups. + +2003-02-10 Erik de Castro Lopo + + * src/wav_w64.h + Applied patch from Antoine Mathys to add extra WAV format definitions and + a G72x_ADPCM_WAV_FMT struct definition. + + * src/wav_w64.c + Applied patch from Antoine Mathys which converts wav_w64_format_str() from + one huge inefficient switch statement to a binary search. + + * tests/string_test.c + Dump log buffer if tests fail. + +2003-02-07 Erik de Castro Lopo + + * tests/string_test.c + David Viens supplied some modifications to this file which showed up a bug + when using sf_set_string() and the sf_writef_float() functions. + + * src/sndfile.c + Fixed the above bug. + +2003-02-06 Erik de Castro Lopo + + * doc/FAQ.html + Added Q and A on how to detect libsndfile in configure.in (at the suggestion + of Davy Durham). + +2003-02-05 Erik de Castro Lopo + + * src/sndfile.h.in + Add enums and typedefs for dither. + Deprecate SFC_SET_ADD_DITHER_ON_WRITE and SFC_SET_ADD_DITHER_ON_READ, to be + replaced with SFC_SET_DITHER_ON_WRITE and SFC_SET_DITHER_ON_READ which will + allow different dither algorithms to be enabled. + Added SFC_GET_DITHER_INFO_COUNT and SFC_GET_DITHER_INFO. + + * src/sndfile.h.in src/Version_script.in Win32/libsndfile.def. + Added public sf_dither_*() functions. + + * src/sndfile.c + Implement commands above. + + * src/dither.c + More work. Framework and external hooks into dither algorithms complete. + +2003-02-03 Erik de Castro Lopo + + * doc/version-1.html libsndfile_version_convert.py + Remove redundant files. + + * doc/index.html doc/api.html + Remove links to version-1.html. + + * src/dither.c + New file to allow the addition of audio dither on input and output. + + * src/common.h + Add prototype for dither_init() function. + + * Makefile.am doc/Makefile.am + Changes for added and removed files. + +2003-02-02 Erik de Castro Lopo + + * Win32/Makefile.msvc + Changes to force example binaries to be placed in the top level directory + instead of the examples/ directory. + Add src/strings.c and src/xi.c to the build. + Add string_test to build and to tests on WAV files. + + * doc/index.html + Added XI to support matrix. + +2003-01-27 Erik de Castro Lopo + + * src/sndfile.h.in + Added prototypes for sf_get_string() and sf_set_string() and SF_STR_* + enum values. + + * src/sndfile.c + Added public interface to sf_get_string() and sf_set_string(). + + * src/wav.c + Added code for setting and getting strings in WAV files. + + * tests/string_test.c + New test program for sf_get_string() and sf_set_string() functionality. + + * tests/Makefile.am + Hook new test program into build and test framework. + +2003-01-26 Erik de Castro Lopo + + * src/common.h + Added fields to SF_PRIVATE for string data needed to implement + sf_get_string() and sf_set_string(). + + * src/strings.c + New file for storing and retrieving strings to/from files. + + * src/Makefile.am + Added strings.c to build. + +2003-01-25 Erik de Castro Lopo + + * src/xi.c + Read seems to be working so looking at write. + + * src/sndfile.h.in + Added SF_FORMAT_XI, SF_FORMAT_DPCM_8 and SF_FORMAT_DPCM_16 enum values. + + * tests/floating_point_test.c tests/lossy_comp_test.c tests/Makefile.am + Added test for 8 and 16 bit XI format files. + +2003-01-24 Erik de Castro Lopo + + * doc/index.html + Added a non-lawyer readable summary of the licensing provisions as + suggested by Steve Dekorte. + +2003-01-23 Erik de Castro Lopo + + * src/wav.c + Fixed a compiler warning found by Alexander Lerch. + +2003-01-18 Erik de Castro Lopo + + * configure.ac + Fixed the multiple linking of libm. + +2003-01-17 Erik de Castro Lopo + + * Win32/Makefile.mcvs + Added comments on the correct way to set up the MSVCDir environment + variable. + + * doc/win32.html + Add on how to set up the MSVCDir environment variable. + +2003-01-15 Erik de Castro Lopo + + * examples/sndfile-play.c examples/sndfile-info.c + When run on Win32 without any command line parameters print a message and + then sleep for 5 seconds. This means the when somebody double clicks on + these programs in explorer the user will actually see the message. + +2003-01-14 Erik de Castro Lopo + + * tests/misc_test.c + Bypass permission test if running as root because root is allowed to open + a readonly file for write. + +2003-01-08 Erik de Castro Lopo + + * Win32/Makefile.msvc + Added pvf.c and xi.c source files to project. + + * src/sndfile.h + Updated for PVF files. + +2003-01-07 Erik de Castro Lopo + + * src/sndfile.c + Modified validate_sfinfo() to force samplerate, channels and sections + to be >= 1. + In format_from_extension() replaced calls to does_extension_match() + with strcmp(). + + * src/xi.c + More work. + +2003-01-06 Erik de Castro Lopo + + * doc/Makefile.am + Added octave.html which had been left out. Found by Jan Weil. + +2003-01-05 Erik de Castro Lopo + + * src/pvf.c src/common.h src/sndfile.c + Fixed error handling for PVF files. + + * src/xi.c + New file for handling Fasttracker 2 Extended Instrument files. Not working + yet and included when configured with --enable-experimental. + + * src/sndfile.c src/common.h + Hooked in new file xi.c. + +2002-12-30 Erik de Castro Lopo + + * src/rx2.c + Added a patch from Marek Peteraj which sheds a little more light on the + slices within an RX2 file. Still need to find out data encoding. + +2002-12-20 Erik de Castro Lopo + + * src/wav.c + Started work on decoding 'acid' and 'strc' chunks. + +2002-12-14 Erik de Castro Lopo + + * tests/peak_check_test.c + Minor cleanup. + +2002-12-12 Erik de Castro Lopo + + * tests/write_read_test.tpl + Added check to make sure no error was generated when an attempt was made to + read past the end of the file. + +2002-12-11 Erik de Castro Lopo + + * doc/lists.html + Added "mailto" links for all three lists. + + * src/pvf.c + New file for Portable Voice Format files. + + * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am + Added hooks for SF_FORMAT_PVF format files. + + * tests/write_read_test.tpl tests/std*.c + Add tests for SF_FORMAT_PVF. + + * doc/index.html + Add PVF to the compatibility matrix. + + * src/pcm.c src/alaw.c src/ulaw.c src/float32.c src/double64.c + Previously, attempts to read beyond the end of a file would set psf->error + to SFE_SHORT_ERROR. This behaviour diverged from the behaviour of the POSIX + read() call but has now been fixed. + Attempts to read beyond the end of the file will return a short read count + but will not longer set any error. + +2002-12-09 Erik de Castro Lopo + + * src/sndfile.c + Add more sanity checking when opening a RAW file for read. When format is + not RAW, zero out all members of the SF_INFO struct. + + * tests/raw_test.c + Add bad_raw_test() to check for above problem. + + * tests/stdin_test.c examples/sndfile-info.c + Set the format field of the SF_INFO struct to zero before calling + sf_open(). + + * doc/api.html + Add information about the need to set the format field of the SF_INFO struct + to zero when opening non-RAW files for read. + + * configure.ac + Removed use of conversion script on Solaris. Not all Solaris versions + support it. + + * doc/lists.html + New file containg details of the mailing lists. + + * doc/index.html + Add a link to the above new file. + +2002-12-04 Erik de Castro Lopo + + * tests/dft_cmp.c + Fixed a SIGFPE on Alpha caused by a log10 (0.0). Thanks to Joshua Haberman + for providing the gdb traceback. + +2002-11-28 Erik de Castro Lopo + + * src/wav.c + Added more capabilities to 'smpl' chunk parser. + + * src/sndfile.c + Fixed some (not all) possible problems found with Flawfinder. + +2002-11-24 Erik de Castro Lopo + + * src/sndfile.c + Fixed a bug in sf_seek(). This bug could only occur when an attempt was + made to read beyond the end and then sf_seek() was called with a whence + parameter of SEEK_CUR. + + * src/file_io.c + Win32's _fstati64() does not work, it returns BS. Re-implemented + psf_get_filelen() in terms of psf_fseek(). + + * tests/write_read_test.tpl + Add a test to detect above bug. + + * src/float_cast.h + Modification to prevent compiler warnings on Mac OS X. + + * src/file_io.c + Fixes for windows (what a f**ked OS). + +2002-11-08 Erik de Castro Lopo + + * configure.ac + Disable use of native lrint()/lrintf() on Mac OSX. These functions exist on + Mac OSX 10.2 but not on 10.1. Forcing the use of the versions in + src/float_cast.h means that a library compiled on 10.2 will still work on + 10.1. + +2002-11-06 Erik de Castro Lopo + + * configure.in configure.ac + Renamed configure.in to configure.ac as expected by later versions of + autoconf. + Slight hacking of configure.ac to work with version 2.54 of autoconf. + Changed to using -dumpversion instead of --version for determining GCC + version numer as suggested by Anand Kumria. + + * src/G72x/Makefile.am + Slight hacking required for operation with automake 1.6.3. + +2002-11-05 Erik de Castro Lopo + + * src/common.c + In psf_binheader_readf() changed type parameter type "b" type from size_t + to int to prevent errors on IA64 CPU where sizeof (size_t) != sizeof (int). + Thanks to Enrique Robledo Arnuncio for debugging this. + +2002-11-04 Erik de Castro Lopo + + * test/command_test.tpl + Changed test value so test would pass on Solaris. + + * src/Version_script.in + Modified version numbering so that later versions of 1.0.X can replace + earlier versions without recompilation. + + * src/vox_adpcm.c + Fixed bug causing short reads. + +2002-11-03 Erik de Castro Lopo + + * test/floating_point_test.c + Code cleanup using functions from util.c. + Add test for IEEE replacement floats and doubles. + +2002-11-01 Erik de Castro Lopo + + * src/wav.c + Fixed a possible divide by zero error when read the 'smpl' chunk. Thanks to + Serg Repalov for the example file. + + * tests/pcm_test.tpl + Used sf_command (SFC_TEST_IEEE_FLOAT_REPLACE) to test IEEE replacement code. + Clean up pcm_double_test(). + + * src/float32.c src/double64.c + Force use of IEEE replacement code using psf->ieee_replace is TRUE, + Print message to log_buffer as well. + Rename all broken_read_* and broken_write* functions to replace_read_* and + replace_write_*. + + * tests/util.tpl + Added string_in_log_buffer(). + + * tests/pcm_test.tpl + Use string_in_log_buffer() to ensure that IEEE replacement code has been + used. + + * configure.in + Removed --enable-force-broken-float option. IEEE replacement code is now + always tested. + +2002-10-31 Erik de Castro Lopo + + * src/double64.c + Implement code for read/writing IEEE doubles on platforms where the native + double format is not IEEE. + + * src/float32.c src/common.h + Remove float32_read() and float32_write(). Replace with float32_le_read(), + float32_be_read(), float32_le_write() and float32_be_write() to match stuff + in src/double64.c. + + * src/common.c + Fix all usage of float32_write(). + + * src/sndfile.h.in + Added SFC_TEST_IEEE_FLOAT_REPLACE command (testing only). + + * src/common.h + Added SF_PRIVATE field ieee_replace. + + * src/sndfile.c + In sf_command() set/reset psf->ieee_replace. + +2002-10-26 Erik de Castro Lopo + + * tests/pcm_test.tpl + Fixed a problem when testing with --enable-force-broken-float. The test was + generating a value of negative zero and the broken float code is not able + to write negative zero. Removing the negative zero fixed the test. + +2002-10-25 Erik de Castro Lopo + + * src/file_io.c + Added fix for Cygwin (suggested by Maros Michalik). + +2002-10-23 Erik de Castro Lopo + + * src/file_io.c + Improved error detection and handling. + + * src/file_io.c src/common.h + Removed functions psf_ferror() and psf_clearerr() which were redundant + after above improvements. + + * src/aiff.c src/svx.c src/w64.c src/wav.c + Removed all use of psf_ferror() and psf_clearerr(). + + * src/sndfile.c + Removed #include of , , and which + are no longer needed. + + * tests/misc_test.c + Added test to make sure the correct error message is returned with an + existing read-only file is openned for write. + +2002-10-21 Erik de Castro Lopo + + * doc/index.html doc/api.html + Updated for OKI Dialogic ADPCM files. + + * src/command.c + Added VOX ADPCM to sub_fomats. + +2002-10-20 Erik de Castro Lopo + + * src/vox_adpcm.c src/Makefile.am + New file for handling OKI Dialogic ADPCM files. + + * src/sndfile.h + Add new subtype SF_FORMAT_VOX_ADPCM. + + * src/sndfile.c + Renamed function is_au_snd_file () to format_from_extenstion () and expanded + its functionality to detect headerless VOX files. + + * src/raw.c + Added hooks for SF_FORMAT_VOX_ADPCM. + + * examples/sndfile-info.c + Print out file duration (suggested by Conrad Parker). + + * libsndfile.spec.in + Force installation of sndfile.pc file (found by John Thompson). + + * tests/Makefile.am tests/lossy_comp_test.c tests/floating_point_test.c + Add tests for SF_FORMAT_VOX_ADPCM. + +2002-10-18 Erik de Castro Lopo + + * tests/misc_test.c + Add test which attempts to write to /dev/full (on Linux anyway) to check + for correct handling of writing to a full filesystem. + + * src/sndfile.c + Return correct error message if the header cannot be written because the + filesystem is full. + + * tests/util.tpl + Corrected printing of file mode in error reporting. + + * src/mat5.c + Fixed a bug where a MAT5 file written by libsndfile could not be opened by + Octave 2.1.36. + +2002-10-13 Erik de Castro Lopo + + * src/common.h src/file_io.c + All low level file I/O have been modified to be better able to report + system errors resulting from calling system level open/read/write etc. + + * src/*.c + Updated for compatibility with above changes. + + * examples/cooledit-fixer.c + New example program which fixes badly broken file created by Syntrillium's + Cooledit which are marked as containing PCM samples but actually contain + floating point data. + + * examples/Makefile.am + Hooked cooledit-fixer into the build system. + +2002-10-10 Erik de Castro Lopo + + * doc/command.html + Document SFC_GET_FORMAT_INFO. + +2002-10-09 Erik de Castro Lopo + + * examples/wav32_aiff24.c examples/sndfile2oct.c examples/sfhexdump.c + examples/sfdump.c + Removed these files because they weren't interesting. + + * examples/sfconvert.c examples/sndfile-convert.c + Renamed the first to the latter. + + * examples/Makefile.am + Added sndfile-convert to the bin_PROGRAMS, so it is installed when the lib + is installed. + Removed old programs wav32_aiff24 and sndfile2oct. + + * man/sndfile-convert.1 + New man page. + + * examples/sndfile-convert.c + Added some gloss now that sndfile-convert.c is an installed program. + + * src/sndfile.h.in src/sndfile.c src/common.h src/command.h + Added command SFC_GET_FORMAT_INFO. + + * tests/command_test.c + Added tests form SFC_GET_FORMAT_INFO. + +2002-10-08 Erik de Castro Lopo + + * src/sndfile.c + In sf_format_check() return error if samplerate < 0. + +2002-10-07 Erik de Castro Lopo + + * src/aiff.c + Fixed bug in handling of COMM chunks with a 4 byte encoding byte but no + encoding string. + +2002-10-06 Erik de Castro Lopo + + * src/sndfile.c + Fixed repeated word in an error message. + +2002-10-05 Erik de Castro Lopo + + * doc/index.html + Improved advertising in Features section. + +2002-10-04 Erik de Castro Lopo + + * src/wav.c + Added decoding of 'labl' chunks within 'LIST' chunks. + + * src/common.h + Added (experimental only) SF_FORMAT_OGG and SF_FORMAT_VORBIS and definition + of ogg_open(). This is nowhere near working yet. + + * src/sndfile.c + Added detection of 'OggS' file marker and added call to ogg_open() to + switch statement. + + * src/ogg.c + New file. Very early start of Ogg Vorbis support. + + * src/wav.c + Added handling of brain-damaged and broken Cooledit "32 bit 24.0 float + type 1" files. These files are marked as being 24 bit WAVE_FORMAT_PCM with + a block alignment of 4 times the numbers of channels but are in fact 32 bit + floating point. + +2002-10-02 Erik de Castro Lopo + + * configure.in + Modified option --enable-experimental to set ENABLE_EXPERIMENTAL_CODE in + config.h to either 0 or 1. + + * src/sndfile.c + Modify sf_command (SFC_GET_LIB_VERSION) to append "-exp" to the version + string if experimental code has been enabled. + +2002-10-01 Erik de Castro Lopo + + * src/Makefile.am + Added -lm to libsndfile_la_LIBADD. This means that -lm is not longer needed + in the link line when linking something to libsndfile. + + * tests/Makefile.am examples/Makefile.am + Removed -lm from all link lines. + + * sndfile.pc.in + Removed -lm from Libs line. + +2002-09-24 Erik de Castro Lopo + + * src/file_io.c + Removed all perror() calls. + + * src/nist.c + Removed calls to exit() function. + Added check to detect NIST files dammaged from Unix CR -> Win32 CRLF + conversion process. + +2002-09-24 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c + New function sf_strerror() which will eventually replace functions + sf_perror() and sf_error_str(). + Function sf_error_number() has also been changed, but this was documented + as being for testing only. + + * doc/api.html + Documented above changes. + + * tests/*.c examples/*.c + Changed to new error functions. + +2002-09-22 Erik de Castro Lopo + + * configure.in + Detect GCC version, and print a warning message about writeable strings + it GCC major version number is less than 3. + +2002-09-21 Erik de Castro Lopo + + * src/sndfile.h.in doc/api.html + Documentation fixes. + +2002-09-19 Erik de Castro Lopo + + * src/Version_script.in src/Makefile.am configure.in + Use the version script to prevent the exporting of all non public symbols. + This currently only works with Linux. Will test on Solaris as well. + + * src/float_cast.h + Added #ifndef to prevent the #warning directives killing the SGI MIPSpro + compiler. + + * src/au_g72x.c src/double64.c src/float32.c src/gsm610.c src/ima_adpcm.c + src/ms_adpcm.c + Fix benign compiler warnings arising from previously added compiler + flags. + +2002-09-18 Erik de Castro Lopo + + * src/sndfile.c + Fixed a bug in sf_error_str() where errnum was used as the index instead + of k. Found by Tim Hockin. + + * examples/sndfile-play.c + Fixed a compiler warning resulting from a variable shadowing a previously + defined local. + +2002-09-17 Erik de Castro Lopo + + * src/sndfile.h.in src/sndfile.c + Added command SFC_SET_RAW_START_OFFSET. + + * doc/command.html + Document SFC_SET_RAW_START_OFFSET. + + * tests/raw_test.c tests/Makefile.am + Add new file for testing SF_FORMAT_RAW specific functionality. + + * tests/dwvw_test.c + Updates. + +2002-09-16 Erik de Castro Lopo + + * src/wav.c + Modified reading of 'smpl' chunk to take account of the sampler data field. + + * tests/utils.tpl tests/utils.h + Added function print_test_name(). + + * tests/misc_test.c tests/write_read_test.tpl tests/lossy_comp_test.c + tests/pcm_test.tpl tests/command_test.tpl tests/floating_point_test.c + Convert to use function print_test_name(). + +2002-09-15 Erik de Castro Lopo + + * doc/octave.html + Added a link to some other Octave scripts for reading and writing sound + files. + + * src/paf.c + Change type of dummy data field to int. This should fix a benign compiler + warning on some CPUs. + Removed superfluous casts resulting from the above change. + + * src/rx2.c + More hacking. + +2002-09-14 Erik de Castro Lopo + + * src/mat5.c src/common.c + Changed usage of snprintf() to LSF_SNPRINTF(). + + * Win32/Makefile.msvc + Updated to include new files and add new tests. + + * Win32/config.h Win32/sndfile.h + Updated. + + * doc/api.html + Added note about the possibility of "missing" features actually being + implemented as an sf_command(). + +2002-09-13 Erik de Castro Lopo + + * tests/misc_test.c + Added previously missing update_header_test and zero_data_tests for PAF, + MAT4 and MAT5 formats. + + * src/paf.c src/mat4.c src/mat5.c + Fixed bugs uncovered by new tests above. + + * src/mat5.c + Generalised parsing of name fields of MAT5 files. + + * src/mat5.c src/sndfile.c + Added support for unsigned 8 bit PCM MAT5 files. + + * tests/write_read_test.tpl + Added test for unsigned 8 bit PCM MAT5 files. + + * doc/index.html + Added unsigned 8 bit PCM MAT5 to capabilities matrix. + +2002-09-12 Erik de Castro Lopo + + * test/update_header_test.c tests/misc_test.c + Renamed update_header_test.c to misc_test.c. + Added zero_data_test() to check for case where file is opened for write and + closed immediately. The resulting file can be left in a state where + libsndfile cannot open it. Problem reported by Werner Schweer, the author + of Muse. + + * src/aiff.c + Removed superfluous cast. + + * src/wav.c src/svx.c + Fixed case of file generated with no data. + Removed superfluous cast. + + * src/sndfile.c + Fixed error on IA64 platform caused by incorrect termination of + SndfileErrors struct array. This problem was found in the Debian buildd + logs (http://buildd.debian.org/). + + * configure.in + Added Octave directory. + + * Octave/Makefile.ma + New Makfile.am for Octave directory. + + * Octave/sndfile_load.m Octave/sndfile_save.m Octave/sndfile_play.m + New files for working with Octave. + + * doc/octave.html + Document explaining the use of the above three Octave scripts. + +2002-09-10 Erik de Castro Lopo + + * src/sndfile.c + Fixed bug in RDWR mode. + +2002-09-09 Erik de Castro Lopo + + * src/common.c + Fixed psf_get_date_str() for systems which don't have gmtime_r() or + gmtime(). + + * src/file_io.c + Added #include for Win32. Reported by Koen Tanghe. + +2002-09-08 Erik de Castro Lopo + + * src/common.c + Added 'S' format specifier for psf_binheader_writef() which writes a C + string, including single null terminator to the header. + Added 'j' format specifier to allow jumping forwards or backwards in the + header. + Added function psf_get_date_str(). + + * src/mat5.c + Complete read and write support. + + * doc/index.html + Added entries for MAT4 and MAT5 in capabilities matrix. + +2002-09-06 Erik de Castro Lopo + + * src/mat4.c + Completed read and write support. + + * src/common.h src/sndfile.c + Added MAT4 and MAT5 specific error messages. + + * tests/write_read_test.tpl tests/Makefile.am + Added tests for MAT4 and MAT5 files. + + * tests/stdio_test.c tests/stdout_test.c tests/stdin_test.c + Added tests for MAT4 and MAT5 files. + +2002-09-05 Erik de Castro Lopo + + * src/command.c + Added elements for SF_FORMAT_MAT4 and SF_FORMAT_MAT5 to major_formats + array. + + * examples/sfconvert.c + Added mat4 and mat5 output targets. + +2002-09-04 Erik de Castro Lopo + + * src/sndfile.c + Added check to prevent errors openning read only formats for read/write. + + * src/interleave.c + New file for interleaving non-interleaved data. Non-interleaved data is + only supported on read. + + * src/Makefile.am + Added src/interleave.c to build. + +2002-09-03 Erik de Castro Lopo + + * src/double64.c src/common.h + Added double64_be_read(), double64_le_read(), double64_be_write() and + double64_le_write() which replace double64_read() and double64_write(). + + * src/common.c + Cleanup of psf_binheader_readf() and add ability to read big and little + endian doubles (required by mat4.c and mat5.c). + Add ability for psf_binheader_writef() to write doubles to sound file + headers. + +2002-09-01 Erik de Castro Lopo + + * src/mat5.c + New file for reading Matlab (tm) version 5 data files. This is also the + native binary file format for version 2.1.X of GNU Octave which will be + used for testing. + Not complete yet. + + * src/mat4.c + New file for reading Matlab (tm) version 4.2 data files. This is also the + native binary file format for version 2.0.X of GNU Octave which will be + used for testing. + Not complete yet. + + * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am + Mods to add Matlab files. + + * src/common.[ch] + Added readf_endian field to SF_PRIVATE struct allowing endianness to + remembered across calls to sf_binheader_readf(). + Fixed bug in width_specifier behaviour for printing hex values. + +2002-08-31 Erik de Castro Lopo + + * src/file_io.c + Check return value of close() call in psf_fclose(). + +2002-08-24 Erik de Castro Lopo + + * src/ms_adpcm.c + Commented out some code where 0x10000 was being subtracted from a short + and the result assigned to a short again. Andrew Zaja found this. + +2002-08-23 Erik de Castro Lopo + + * doc/command.html + Fixed typo found by Tommi Ilmonen. + + * src/ima_adpcm.c + Changed type of diff from short to int to prevent errors which can occur + during very rare circumstances. Thanks to FUWAFUWA. + +2002-08-16 Erik de Castro Lopo + + * tests/floating_point_test.c + Disable testing on machines without lrintf(). + + * Win32/Makefile.msvc + Added dwd.c and wve.c to build. + + * configure.in + Bumped version to 1.0.0. + +2002-08-15 Erik de Castro Lopo + + * src/file_io.c + Add a #include for Mac OS 9. Thanks to Stephane Letz. + + * src/wav.c + Changed an snprintf to LSF_SNPRINTF. + + * doc/Makefile.am + Added version-1.html. + +2002-08-14 Erik de Castro Lopo + + * configure.in + Bumped version to 1.0.rc6. + + * src/*.c + Modified scaling of normalised floats and doubles to integers. Until now + this has been done by multiplying by 0x8000 for short output, 0x80000000 + for 32 bit ints and so on. Unfortunately this can cause an overflow and + wrap around in the target value. All thes values have therefore been + reduced to 0x7FFF, 0x7FFFFFFF and so on. The conversion from ints to + normalised floats and doubles remains unchanged. This does mean that for + repeated conversions normalised float -> pcm16 -> normalised float would + result in a decrease in amplitude of 0x7FFF/0x8000 on every round trip. + This is undesirable but less undesireable than the wrap around I am trying + to avoid. + + * tests/floating_point_test.c + Removed file hash checking because new float scaling procedure introduced + above prevented the ability to crate a has on both x86 and PowerPC systems. + +2002-08-13 Erik de Castro Lopo + + * src/txw.c + Completed reading of TXW files. Seek doesn't work yet. + + * src/file_io.c + Added a MacOS 9 replacement for ftruncate(). + + * MacOS/sndfile.h + Added MacOS 9 header file. This should be copied into src/ to compile + libsndfile for MacOS9. + +2002-08-12 Erik de Castro Lopo + + * src/sndfile.c + Fixed commands SF_SET_NORM_DOUBLE and SFC_SET_NORM_FLOAT to return their + values after being set. Reported by Jussi Laako. + + * configure.in + If autogen is not found, touch all .c and .h files in tests/. + + * src/common.c + Added format width specifier to psf_log_printf() for %u, %d, %D and %X. + + * src/dwd.c + Completed implementation of read only access to these files. + + * src/common.h src/*.c src/pcm.c + Removed redundant field chars from SF_PRIVATE struct and modified + pcm_init() to do without it. + +2002-08-11 Erik de Castro Lopo + + * src/wve.c + New file implementing read of Psion Alaw files. This will be a read only + format. Implementation complete. + + * src/dwd/c + Started implementation of DiamondWare Digitized files. Also read only, not + complete. + + * src/wav.c + Add parsing of 'smpl' chunk. + + * src/paf.c + Fixed reading on un-normalized doubles and floats from 24 bit PAF files. + This brings it into line with the reading of 8 bit files into + un-normalized doubles which returns values in the range [-128, 127]. + + * src/common.c + Modified psf_log_printf() to accept the %% conversion specifier to allow + printing of a single '%'. + + * src/sds.c + Read only of 16 bit samples is working. Need to build a test harness for + this and other read only formats. + +2002-08-10 Erik de Castro Lopo + + * configure.in + Added --enable-experimental configure option. + Removed pkg-config message at the end of the configure process. + + * src/sds.c src/txw.c src/rx2.c src/sd2.c + Moved all the code in these files inside #if ENABLE_EXPERIMENTAL_CODE + blocks and added new *_open() function for the case where experimental is + not enabled. These new functions just return SFE_UNIMPLMENTED. + + * Win32/sndfile.h src/sndfile.h.in src/common.h + Removed un-necessary #pragma pack commands. + + * src/file_io.c + Implemented psf_ftruncate() and much other hacking for Win32. + + * Win32/Makefile.msvc + Updated. + + * doc/win32.html + Updated to include the copying of the sndfile.h file from the Win32/ + directory to the src/ directory. + + * Make.bat + Batch file to make compiling on Wi32 a little easier. Implements "make" and + "make check". + +2002-08-09 Erik de Castro Lopo + + * src/file_io.c + Add place holder for ftruncate() on Win32 which doesn't have ftruncate(). + This will need to be fixed later. + + * src/sndfile.h.in + New file (copy of sndfile.h) with sets up @TYPEOF_SF_COUNT_T@ which will be + replaced by the correct type during configure. + + * configure.in + Modified to find a good type for TYPEOF_SF_COUNT_T. + + * src/aiff.c + Fixed a bug when reading malformed headers. + + * src/common.c + Set read values to zero before performing read. + +2002-08-08 Erik de Castro Lopo + + * doc/command.html + Fixed some HTML tags which were not allowing jumps to links within the + page. + + * src/sds.c + Massive hacking on this. + + * src/wav.c + Added recognition of 'clm ' tag. + +2002-08-07 Erik de Castro Lopo + + * doc/index.html + Added beginning of a capabilities list beyond simple file formats which + can be read/written. + + * src/aiff.c + Added parsing of INST and MARK chunks of AIFF files. At the moment this + data is simply recorded in the log buffer. Later it will be possible to + read this data from an application using sf_command(). + + * src/wav.c + Added parsing of 'cue ' chunk which contains loop information in WAV files. + + * exampes/sndfile-info.c + Changed reporting of Samples to Frames. + + * src/wav.c src/w64.c src/aiff.c src/wav_w64.h + Moved from a samples to a frames nomenclature to avoid confusion. + + * doc/FAQ.html + What's the best format for storing temporary files? + + * src/sds.c + New file for reading/writing Midi Sample Dump Standard files. + + * src/Makefile.am src/sndfile.c src/common.[ch] + Added hooks for sds.c. + + * examples/sndfile-info.c + Changed from using sf_perror() to using sf_error_str(). + +2002-08-06 Erik de Castro Lopo + + * doc/api.html + Added explanation of mode parameter for sf_open(). + Added explanation of usage of SFM_* values in sf_seek(). + + * src/sndfile.[ch] src/command.c src/file_io.c src/common.h + Implemented SFC_FILE_TRUNCATE to allow a file to be truncated. File + truncation was suggested by James McCartney. + + * src/command.html + Documented SFC_FILE_TRUNCATE. + + * tests/command_test.c + Add tests for SFC_FILE_TRUNCATE. + + * src/sndfile.c + Added a thrid parameter to the VALIDATE_SNDFILE_AND_ASSIGN_PSF macro to + make resetting the error number optional. All uses of the macro other than + in error reporting functions were changed to reset the error number. + + * src/pcm.c + Fixed a bug were sf_read_* was logging an SFE_SHORT_READ even when no error + occurred. + + * tests/write_read_test.tpl + Added tests of internal error state. + +2002-08-05 Erik de Castro Lopo + + * src/GSM610/private.h src/GSM610/*.c src/GSM610/Makefile.am + Renamed private.h to gsm610_priv.h to prevent clash with other headers + named private.h in other directories. (Probably only a problem on MacOS 9). + + * src/G72x/private.h src/G72x/*.c src/G72x/Makefile.am + Renamed private.h to g72x_priv.h to prevent clash with other headers + named private.h in other directories. (Probably only a problem on MacOS 9). + + * MacOS/config.h + Changed values of HAVE_LRINT and HAVE_LRINTF to force use of code in + float_cash.h. + + * src/sndfile.h + Changes the name of samples field of the SF_INFO to frames. The old name + had caused too much confusion and it simply had to be changed. There will + be at least one more pre-release. + +2002-08-04 Erik de Castro Lopo + + * doc/index.html + Updated formats matrix to include RAW (header-less) GSM 6.10. + Fix specificaltion of table and spelling mistakes. + + * src/sndfile.c src/command.c + Fixed bug in SFC_CALC_MAX_SIGNAL family and psf_calc_signal_max (). + + * tests/command.c + Removed cruft. + Added test for SFC_CALC_MAX_SIGNAL and SFC_CALC_NORM_MAX_SIGNAL. + + * configure.in + Update version to 1.0.0rc5. + + * sfendian.h + Removed inclusion of un-necessary header. + +2002-08-03 Erik de Castro Lopo + + * src/aiff.c + Minor fixes of info written to log buffer. + + * src/float_cast.h + Add definition of HAVE_LRINT_REPLACEMENT. + + * tests/floating_point_test.c + Fix file hash check on systems without lrint/lrintf. + + * tests/dft_cmp.c + Limit SNR to less than -500.0dB. + + * examples/sndfile2oct.c + Fixed compiler warnings. + + * doc/api.html + Fixed error where last parameter of sf_error_str() was sf_count_t instead + of size_t. + +2002-08-02 Erik de Castro Lopo + + * doc/FAQ.html + Why doesn't libsndfile do interleaving/de-interleaving. + + * tests/pcm_test.tpl + On Win32 do not perform hash check on files containing doubles. + +2002-08-01 Erik de Castro Lopo + + * src/common.h + Defined SF_COUNT_MAX_POSITIVE() macro, a portable way of setting variables + of type sf_count_t to their maximum positive value. + + * src/dwvw.c src/w64.c + Used SF_COUNT_MAX_POSITIVE(). + +2002-07-31 Erik de Castro Lopo + + * src/paf.c + Fixed bug in reading/writing of 24 bit PCM PAF files on big endian systems. + + * tests/floating_point_tests.c + Fixed hash values for 24 bit PCM PAF files. + Disabled file has check if lrintf() function is not available and added + warning. + Decreased level of signal from a peak of 1.0 to a value of 0.95 to prevent + problems on platforms without lrintf() ie Solaris. + +2002-07-30 Erik de Castro Lopo + + * src/wav.c + Fixed a problem with two different kinds of mal-formed WAV file header. The + first had the 'fact' chunk before the 'fmt ' chunk, the other had an + incomplete 'INFO' chunk at the end of the file. + + * src/w64.c + Added fix to allow differentiation between W64 files and ACID files. + + * src/au_g72x.c src/common.h src/sndfile.c + Added error for G72x encoded files with more than one channel. + + * tests/pcm_test.tpl tests/utils.tpl + Moved function check_file_hash_or_die() to utils.tpl. Function was then + modified to calculate the has of the whole file. + + * src/wav.c + Fixed problem writing the 'fact' chunk on big endian systems. + + * tests/sfconvert.c + Fixed bug where .paf files were being written as Sphere NIST. + +2002-07-29 Erik de Castro Lopo + + * src/voc.c + Fix for reading headers generated using SFC_UPDATE_HEADER_NOW. + + * doc/command.html + Add docs for SFC_UPDATE_HEADER_NOW and SFC_SET_UPDATE_HEADER_AUTO. + +2002-07-28 Erik de Castro Lopo + + * man/sndfile-info.1 man/sndfile-play.1 + Added manpages supplied by Joshua Haberman the Debian maintainer for + libsndfile. Additional tweaks by me. + + * configure.in man/Makefile.am + Hooked manpages into autoconf/automake system. + + * src/sndfile.c + Added hooks for SFC_SET_UPDATE_HEADER_AUTO. + + * tests/update_header_test.c + Improved rigor of testing. + + * src/*.c + Fixed problem with *_write_header() functions. + +2002-07-27 Erik de Castro Lopo + + * doc/*.html + Updates to documentation to fix problems found by wdg-html-validator. + + * src/common.h src/command.c + Added normalize parameter to calls to psf_calc_signal_max() and + psf_calc_max_all_channels(). + + * src/sndfile.c + Added handling for commands SFC_CALC_NORM_SIGNAL_MAX and + SFC_CALC_NORM_MAX_ALL_CHANNELS. + + * doc/command.html + Added entry for SFC_CALC_NORM_SIGNAL_MAX and SFC_CALC_NORM_MAX_ALL_CHANNELS. + +2002-07-26 Erik de Castro Lopo + + * examples/sndfile-play.c Win32/Makefile.msvc + Get sndfile-play program working on Win32. The Win32 PCM sample I/O API + sucks. The sndfile-play program now works on Linux, MacOSX, Solaris and + Win32. + +2002-07-25 Erik de Castro Lopo + + * doc/FAQ.html + New file for frequently asked questsions. + +2002-07-22 Erik de Castro Lopo + + * doc/api.html + Documentation fixes. + + * src/au.[ch] src/au_g72x.c src/G72x/g72x.h + Add support of 40kbps G723 ADPCM encoding. + + * tests/lossy_comp_test.c tests/floating_point_test.c + Add tests for 40kbps G723 ADPCM encoding. + + * doc/index.html + Update support matrix. + +2002-07-21 Erik de Castro Lopo + + * doc/command.html + Documented SFC_GET_SIMPLE_FORMAT_COUNT, SFC_GET_SIMPLE_FORMAT, + SFC_GET_FORMAT_* and SFC_SET_ADD_PEAK_CHUNK. + + * src/sndfile.c src/pcm.c + Add ability to turn on and off the addition of a PEAK chunk for floating + point WAV and AIFF files. + + * src/sndfile.[ch] src/common.h src/command.c + Added sf_command SFC_CALC_MAX_ALL_CHANNELS. Implemented by Maurizio Umberto + Puxeddu. + + * doc/command.html + Docs for SFC_CALC_MAX_ALL_CHANNELS (assisted by Maurizio Umberto Puxeddu). + +2002-07-18 Erik de Castro Lopo + + * src/sndfile.c src/gsm610.c + Finalised support for GSM 6.10 AIFF files and added support for GSM 6.10 + encoded RAW (header-less) files. + + * src/wav.c + Add support for IBM_FORMAT_MULAW and IBM_FORMAT_ALAW encodings. + + * src/api.html + Fixed more documentation bugs. + +2002-07-17 Erik de Castro Lopo + + * src/sndfile.h src/common.h + Moved some yet-to-be-implelmented values for SF_FORMAT_* from the public + header file sndfile.h to the private header file common.h to avoid + confusion about the actual capabilities of libsndfile. + +2002-07-16 Erik de Castro Lopo + + * src/aiff.c src/wav.c + Fixed file parsing for WAV and AIFF files containing non-audio data after + the data chunk. + + * src/aiff.c src/sndfile.c + Add support for GSM 6.10 encoded AIFF files. + + * tests/lossy_comp_test.c tests/Makefile.am + Add tests for GSM 6.10 encoded AIFF files. + + * src/*.c + Fix compiler warnings. + +2002-07-15 Erik de Castro Lopo + + * tests/command_test.c + For SFC_SET_NORM_* tests, change the file format from SF_FORMAT_WAV to + SF_FORMAT_RAW. + + * src/sndfile.c + Added sf_command(SFC_TEST_ADD_TRAILING_DATA) to allow testing of reading + from AIFF and WAV files with non-audio data after the audio chunk. + + * src/common.h + Add test commands SFC_TEST_WAV_ADD_INFO_CHUNK and + SFC_TEST_AIFF_ADD_INST_CHUNK. When these commands are working, they will be + moved to src/sndfile.h + + * src/aiff.c src/wav.c + Begin implementation of XXXX_command() hook for sf_command(). + + * tests/write_read_test.tpl + Added sf_command (SFC_TEST_ADD_TRAILING_DATA) to ensure above new code was + working. + +2002-07-13 Erik de Castro Lopo + + * tests/update_header_test.c + Allow read sample count == write sample count - 1 to fix problems with VOC + files. + + * tests/write_read_test.tpl tests/pcm_test.tpl + Fixed some problems in the test suite discovered by using Valgrind. + +2002-07-12 Erik de Castro Lopo + + * tests/utils.[ch] tests/*.c + Renamed check_log_buffer() to check_log_buffer_or_die(). + + * src/sndfile.c + SFC_UPDATE_HEADER_NOW and SFC_SETUPDATE_HEADER_AUTO almost finished. Works + for all file formats other than VOC. + +2002-07-11 Erik de Castro Lopo + + * src/sndfile.[ch] src/common.h + Started adding functionality to allow the file header to be updated before + the file is closed on files open for SFM_WRITE. This was requested by + Maurizio Umberto Puxeddu who is using libsndfile for file I/O in iCSound. + + * tests/update_header_test.c + New test program to test that the above functionality is working correctly. + + * tests/peak_chunk_test.c tests/floating_point_test.c + Cleanups. + +2002-07-10 Erik de Castro Lopo + + * src/sfendian.[ch] + Changed length count parameters for all endswap_XXX() functions from + sf_count_t (which can be 64 bit even on 32 bit architectures) to int. These + functions are only called frin inside the library, are always called with + integer parameters and doing the actual calculation on 64 bit values is + slow in comparision to doing it on ints. + + * examples/sndfile-play.c + More playback hacking for Win32. + +2002-07-09 Erik de Castro Lopo + + * src/common.c + In psf_log_printf(), changed %D format conversion specifier to %M (marker) and + added %D specifier for printing the sf_count_t type. + + * src/*.c + Changed all usage of psf_log_printf() with %D format conversion specifiers + to use %M conversion instead. + + * tests/pcm_test.tpl tests/pcm_test.def + New files to autogen pcm_test.c. + + * src/pcm.c + Fixed bug in scaling floats and doubles to 24 bit PCM and vice versa. + +2002-07-08 Erik de Castro Lopo + + * configure.in + Fix setup of $ac_cv_sys_largefile_CFLAGS so that sndfile.pc gets valid + values for CFLAGS. + + * examples/sndfile-play.c + Start adding playback support for Win32. + +2002-07-07 Erik de Castro Lopo + + * src/*.c + Worked to removed compiler warnings. + Extensive refactoring. + + * src/common.[ch] + Added function psf_memset() which works like the standard C function memset + but takes and sf_count_t as the length parameter. + + * src/sndfile.c + Replaced calls to memset(0 with calls to psf_memset() as required. + +2002-07-06 Erik de Castro Lopo + + * src/sndfile.c + Added "libsndfile : " to the start of all error messages. This was suggested + by Conrad Parker author of Sweep ( http://sweep.sourceforge.net/ ). + + * src/sfendian.[ch] + Added endswap_XXXX_copy() functions. + + * src/pcm.c src/float32.c src/double64.c + Use endswap_XXXX_copy() functions and removed dead code. + Cleanups and optimisations. + +2002-07-05 Erik de Castro Lopo + + * src/sndfile.c src/sndfile.h + Gave values to all the SFC_* enum values to allow better control of the + interface as commands are added and removed. + Added new command SFC_SET_ADD_PEAK_CHUNK. + + * src/wav.c src/aiff.c + Modified wav_write_header and aiff_write_header to make addition of a PEAK + chunk optional, even on floating point files. + + * tests/benchmark.tpl + Added call to sf_command(SFC_SET_ADD_PEAK_CHUNK) to turn off addition of a + PEAK chunk for the benchmark where we are trying to miximize speed. + + * src.pcm.c + Changed tribyte typedef to something more sensible. + Further conversion speed ups. + +2002-07-03 Erik de Castro Lopo + + * src/command.c + In major_formats rename "Sphere NIST" to "NIST Sphere". + + * src/common.c src/sfendian.c + Moved all endswap_XXX_array() functions to sfendian.c. These functions will + be tweaked to provide maximum performance. Since maximum performance on one + platform does not guarantee maximum performance on another, a small set of + functions will be written and the optimal one chosen at compile time. + + * src/common.h src/sfendian.h + Declarations of all endswap_XXX_array() functions moved to sfendian.h. + + * src/Makefile.am + Add sfendian.c to build targets. + +2002-07-01 Erik de Castro Lopo + + * src/pcm.c src/sfendian.h + Re-coded PCM encoders and decoders to match or better the speed of + libsndfile version 0.0.28. + +2002-06-30 Erik de Castro Lopo + + * src/wav.c + Add checking for WAVPACK data in standard PCM WAV file. Return error if + found. This WAVPACK is *WAY* broken. It uses the same PCM WAV file header + and then stores non-PCM data. + + * tests/benchmark.tpl + Added more tests. + +2002-06-29 Erik de Castro Lopo + + * tests/benchmark.tpl + Added conditional definition of M_PI. + For Win32, set WRITE_PERMS to 0777. + + * Win32/Makefile.msvc + Added target to make generate program on Win32. + + * src/samplitude.c + Removed handler for Samplitude RAP file format. This file type seems rarer + than hens teeth and is completely undocumented. + + * src/common.h src/sndfile.c src/Makefile.am Win32/Makefile.msvc + Removed references to sampltiude RAP format. + + * tests/benchmark.tpl + Benchmark program now prints the libsndfile version number when run. This + program was also backported to version 0 to compare results. Version + 1.0.0rc2 is faster than version 0.0.28 on most conversions but slower on + some. The slow ones need to be fixed before final release. + +2002-06-28 Erik de Castro Lopo + + * tests/benchmark.def tests/benchmark.tpl + New files which generate tests/benchmark.c using Autogen. Added int -> + SF_FORMAT_PCM_24 test. + + * tests/benchmark.c + Now and Autogen output file. + + * tests/Makefile.am + Updated for above changes. + +2002-06-27 Erik de Castro Lopo + + * tests/benchmark.c + Basic benchmark program complete. Need to convert it to Autogen. + + * Win32/Makefile.msvc + Added benchmark.exe target. + +2002-06-26 Erik de Castro Lopo + + * examples/generate.c + New program to generate a number of different output file formats from a + single input file. This allows testing of the created files. + + * tests/benchmark.c + New test program to benchmark libsndfile. Nowhere near complete yet. + + * examples/Makefile.am tests/Makefile.am + New make rules for the two new programs. + +2002-06-25 Erik de Castro Lopo + + * Win32/libsndfile.def + Removed definition for sf_signal_max(). + + * src/sndfile.c + Removed cruft. + + * doc/index.html + A number of documentation bugs were fixed. Thanks to Anand Kumria. + + * doc/version-1.html + Minor doc updates. + + * configure.in + Bumped version to 1.0.0rc2. + + * src/sf_command.h src/Makefile.am + Removed the header file as it was no longer being used. Thanks to Anand + Kunria for spotting this. + + * doc/index.html + A number of documentation bugs were fixed. Thanks to Anand Kumria. + +2002-06-24 Erik de Castro Lopo + + * src/common.h + Test for Win32 before testing SIZEOF_OFF_T so that it works correctly + on Win32.. + + * src/file_io.c + Win32 fixes to ensure O_BINARY is used for file open. + + * doc/win32.html + New file documenting the building libsndfile on Win32. + + * doc/*.html + Updating of documentation. + +2002-06-23 Erik de Castro Lopo + + * tests/pcm_test.c + Minor changes to allow easier determination of test file name. + + * src/sndfile.[ch] + Removed function sf_signal_max(). + + * examples/sndfile-play.c + Changed call to sf_signal_max() to a call to sf_command(). + +2002-06-22 Erik de Castro Lopo + + * src/format.c src/command.c + Renamed format.c to command.c which will now include code for sf_command() + calls to perform operations other than format commands. + + * src/sndfile.c src/sndfile.h + Removed function sf_get_signal_max() which is replaced by commands passed + to sf_command(). + + * src/command.c + Implement commands SFC_CALC_SIGNAL_MAX. + + * doc/command.html + Documented SFC_CALC_SIGNAL_MAX. + +2002-06-21 Erik de Castro Lopo + + * examples/sndfile-play.c + Mods to make sndfile-play work on Solaris. The program sndfile-play now + runs on Linux, MaxOSX and Solaris. Win32 to come. + + * src/format.c + Added SF_FORMAT_DWVW_* to subtype_formats array. + + * src/nist.c + Added support for 8 bit NIST Sphere files. Example file supplied by Anand + Kumria. + +2002-06-20 Erik de Castro Lopo + + * examples/sndfile-info.c + Tidy up of output format. + + * examnples/sndfile-play.c + Mods to make sndfile-play work on MacOSX using Apple's CoreAudio API. + + * configure.in + Add new variables OS_SPECIFIC_INCLUDES and OS_SPECIFIC_LINKS which were + required to supply extra include paths and link parameters to get + sndfile-play working on MacOSX. + + * examples/Makefile.am + Use OS_SPOECIFIC_INCLUDES and OS_SPECIFIC_LINKS to build commands for + sndfile-play. + +2002-06-19 Erik de Castro Lopo + + * src/nist.c + Added ability to read/write new NIST Sphere file types (A-law, u-law). + Header parser was re-written from scratch. Example files supplied by Anand + Kumria. + + * src/sndfile.c + Support for A-law and u-law NIST files. + + * tests/Makefile.am tests/lossy_comp_test.c + Tests for A-law and u-law NIST files. + +2002-06-18 Erik de Castro Lopo + + * tests/utils.c + Fixed an error in error string. + +2002-06-17 Erik de Castro Lopo + + * acinclude.m4 + Removed exit command to allow cross-compiling. + + * Win32/unistd.h src/file_io.c + Moved contents of first file into the second file (enclosed in #ifdef). + Win32/unistd.h is now an empty file but still must be there for libsndfile + to compile on Win32. + + * src/sd2.c, src/sndfile.c: + Fixes for Sound Designer II files on big endian systems. + +2002-06-16 Erik de Castro Lopo + + * configure.in + Modified to work around problems with crappy MacOSX version of sed. + Added sanity check for proper values for CFLAGS. + +2002-06-14 Erik de Castro Lopo + + * src/sndfile.c + Code clean up in sf_open (). + + * Win32/Makefile.msvc + Michael Fink's contributed MSVC++ makefile was hacked to bits and put back + together in a new improved form. + + * src/file_io.c + Fixes for Win32; _lseeki64() returns an invalid argument for calls like + _lseeki64(fd, 0, SEEK_CUR) so need to use _telli64 (fd) instead. + + * src/common.h src/sndfile.c src/wav.c src/aiff.c + Added SFE_LOG_OVERRUN error. + Added termination for potential infinite loop when parsing file headers. + + * src/wav.c src/w64.c + Fixed bug casuing incorrect header generation when opening file read/write. + +2002-06-12 Erik de Castro Lopo + + * doc/api.html + Improved the documentation to make it clearer that the file read method + and the underlying file format are completely disconnected. Suggested + by Josh Green. + + * doc/command.html + Started correcting docs to take into account changes made to the + operations of the sf_command () function. Not complete yet. + + * src/sndfile.c + Reverted some changes which had broken the partially working SDII header + parsing. Now have access to an iBook with OS X so reading and writing SDII + files on all platforms should be a reality in the near future. On Mac this + will involve reading the resource fork via the standard MacOS API. To move + a file from Mac to another OS, the resource and data forks will need to be + combined before transfer. The combined file will be read on both Mac and + other OSes like any other file. + +2002-06-08 Erik de Castro Lopo + + * ltmain.sh + Applied a patch from http://fink.sourceforge.net/doc/porting/libtool.php + which allows libsndfile to compile on MacOSX 10.1. This patch should not + interfere with compiling on other OSes. + + * src/GSM610/private.h + Changes to fix compile problems on MacOSX (see src/GSM610/ChangeLog). + + * src/float_cast.h + Added MacOSX replacements for lrint() and lrintf(). + +2002-06-05 Erik de Castro Lopo + + * src/sndfile.c + Replaced the code to print the filename to the log buffer when a file is + opened. This code seems to have been left out during the merge of + sf_open_read() and sf_open_write() to make a single functions sf_open(). + +2002-06-01 Erik de Castro Lopo + + * src/wav.c + Fixed a bug where the WAV header parser was going into an infinite loop + on a badly formed LIST chunk. File supplied by David Viens. + +2002-05-25 Erik de Castro Lopo + + * configure.in + Added a message at the end of the configuration process to warn about the + need for the use of pkg-config when linking programs against version 1 of + libsndfile. + + * doc/pkg-config.html + New documentation file containing details of how to use pkg-config to + retrieve settings for CFLAGS and library locations for linking files + against version 1 of libsndfile. + +2002-05-17 Erik de Castro Lopo + + * src/wav.c + Fixed minor bug in handling of so-called ACIDized WAV files. + +2002-05-16 Erik de Castro Lopo + + * Win32/libsndfile.def Win32/Makefile.msvc + Two new files contributed by Michael Fink (from the winLAME project) + which allows libsndfile to be built on windows in a MSDOS box by doing + "nmake -f Makefile.msvc". Way cool! + +2002-05-15 Erik de Castro Lopo + + * configure.in + MacOSX is SSSOOOOOOO screwed up!!! I can't believe how hard it is to + generate a tarball which will configure and compile on that platform. + Joined the libtool mailing list to try and get some answers. + +2002-05-13 Erik de Castro Lopo + + * configure.in + Changed to autoconf version 2.50. MacOSX uses autoconf version 2.53 which + is incompatible with with version 2.13 which had been using until now. + The AC_SYS_LARGE_FILE macro distributed withe autoconf 2.50 is missing a + few features so AC_SYS_EXTRA_LARGE file was defined to replace it. + + * configure.in + Changed to automake version 1.5 to try and make a tarball which will + work on MacOSX. + +2002-05-12 Erik de Castro Lopo + + * src/wav_gsm610.c + Changed name to gsm610.c. Added reading/writing of headerless files. + + * src/sndfile.c src/raw.c + Added ability to read/write headerless (SF_FORMAT_RAW) GSM 6.10 files. + +2002-05-11 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Clean up in preparation for Autogen-ing this file. + + * src/GSM610/*.[ch] + Code cleanup and prepartion forgetting file seek working. Details in + src/GSM610/ChangeLog. + + * sndfile.pc.in + Testing complete. Is sndfile.m4 still needed? + +2002-05-09 Erik de Castro Lopo + + * tests/write_read_test.tpl tests/rdwr_test.tpl + Merged tests from these two programs into write_read_test.tpl and deleted + rdwr_test.tpl. + +2002-05-08 Erik de Castro Lopo + + * src/w64.c src/svx.c src/paf.c + Fixed bugs in read/write mode. + +2002-05-07 Erik de Castro Lopo + + * examples/Makefile.am + Renamed sfplay.c to sndfile-play.c and sndfile_info.c to sndfile-info.c for + consistency when these programs become part of the Debian package + sndfile-programs. + + * sndfile.pc.in + New file to replace sndfile-config.in. Libsndfile now uses the pkg-config + model for providing installation parameters to dependant programs. + + * src/sndfile.c + Cleanup of code in sf_open(). + +2002-05-06 Erik de Castro Lopo + + * tests/utils.tpl tests/write_read_test.tpl + More conversion to Autogen fixes and enchancements. + + * src/*.c + Read/write mode is now working for 16, 24 and 32 bit PCM as well as 32 + bit float and 64 bit double data. More tests still required. + + * src/Makefile.am + Added DISTCLEANFILES target to remove config.status and config.last. + + * Win32/Makefile.am MacOS/Makefile.am + Added DISTCLEANFILES target to remove Makefile. + +2002-05-05 Erik de Castro Lopo + + * src/*.[ch] tests/rdwr_test.c + More verifying workings of read/write mode. Fixing bugs found. + + * tests/utils.[ch] + Made these files Autogen generated files. + + * tests/util.tpl tests/util.def + New Autogen files to generate utils.[ch]. Moved some generic test functions + into this file. Autogen is such a great tool! + +2002-05-03 Erik de Castro Lopo + + * src/pcm.c src/float_cast.h Win32/config.h + Fixed a couple of Win32 specific bugs pointed out by Michael Fink + (maintainer of WinLAME) and David Viens. + + * tests/check_log_buffer.[ch] tests/utils.[ch] + Moved check_log_buffer() to utils.[ch] and deleted old file. + +2002-05-02 Erik de Castro Lopo + + * src/common.[ch] src/sndfile.c + New function psf_default_seek() which will be the default seek function + for things like PCM and floating point data. This default is set for + both read and write in sf_open() but can be over-ridden by any codec + during it's initialisation. + +2002-05-01 Erik de Castro Lopo + + * src/au.c + AU files use a data size value of -1 to mean unknown. Fixed au_open_read() + to allow opening files like this. + + * tests/rdwr_test .c + Added more tests. + + * src/sndfile.c + Fixed bugs in read/write mode found due to improvements in the test + program. + +2002-04-30 Erik de Castro Lopo + + * tests/rdwr_test .c + New file for testing read/write mode. + +2002-04-29 Erik de Castro Lopo + + * m4/* + Removed all m4 macros from this directory as they get concatenated to form + the file aclocal.m4 anyway. + + * sndfile.m4 + Moved this from the m4 directory to the root directory asn this is part of + the distribution and is installed during "make install". + +2002-04-29 Erik de Castro Lopo + + * src/float32.c + Removed logging of peaks for all file formats other than AIFF and WAV. + + * tests/write_read_test.tpl tests/write_read_test.def + New files which autogen uses to generate write_read_test.c. Doing it this + way makes write_read_test.c far easier to maintain. Other test programs + will be converted to autogen in the near future. + + * src/*.c + Fixed a few bugs found when testing on Sparc (bug endian) Solaris. + +2002-04-28 Erik de Castro Lopo + + * doc/*.html + Fixed documention versioning. + + * configure.in + Fixed a bug in the routines which search for Large File Support on systems + which have large file support by defualt. + +2002-04-27 Erik de Castro Lopo + + * src/*.[ch] + Found and fixed an issue which can cause a bug in other software (I was + porting Conrad Parker's Sweep program from version 0 of the library to + version 1). When opening a file for write, the libsndfile code would + set the sfinfo.samples field to a maximum value. + + * tests/write_read_test.c + Added tests to detect the above problem. + +2002-04-25 Erik de Castro Lopo + + * src/*.[ch] + Finished base implementation of read/write mode. Much more testing still + needed. + + * m4/largefile.m4 + Macro for detecting Large File Standard capabilities. This macro was ripped + out of the aclocal.m4 file of GNU tar-1.13. + + * configure.in + Added detection of large file support. Files larger than 2 Gigabytes should + now be supported on 64 bit platforms and many 32 bit platforms including + Linux (2.4 kernel, glibc-2.2), *BSD, MacOS, Win32. + + * libsndfile_convert_version.py + A Python script which attempts to autoconvert code written to use version 0 + to version 1. + +2002-04-24 Erik de Castro Lopo + + * src/*.[ch] + Finished base implementation of read/write mode. Much more testing still + needed. + + * tests/write_read_test.c + Preliminary tests for read/write mode added. More needed. + +2002-04-20 Erik de Castro Lopo + + * src/sndfile.[ch] + Removed sf_open_read() and sf_open_write() functions,replacting them with + sf_open() which takes an extra mode parameter (SF_OPEN_READ, SF_OPEN_WRITE, + or SF_OPEN_RDWR). This new function sf_open can now be modified to allow + opening a file formodification (RDWR). + +2002-04-19 Erik de Castro Lopo + + * src/*.c + Completed merging of separate xxx_open_read() and xxx_open_write() + functions. All tests pass. + +2002-04-18 Erik de Castro Lopo + + * src/au.c + Massive refactoring required to merge au_open_read() with au_open_write() + to create au_open(). + +2002-04-17 Erik de Castro Lopo + + * src/*.c + Started changes required to allow a sound file to be opened in read/write + mode, with separate file pointers for read and write. This involves merging + of encoder/decoder functions like pcm_read_init() and pcm_write_init() + int a new function pcm_init() as well as doing something similar for all + the file type specific functions ie aiff_open_read() and aiff_open_write() + were merged to make the function aiff_open(). + +2002-04-15 Erik de Castro Lopo + + * src/file_io.c + New file containing psf_fopen(), psf_fread(), psf_fwrite(), psf_fseek() and + psf_ftell() functions. These function will replace use of fopen/fread/fwrite + etc and allow access to files larger than 2 gigabytes on a number of 32 bit + OSes (Linux on x86, 32 bit Solaris user space apps, Win32 and MacOS). + + * src/*.c + Replaced all instances of fopen with psf_open, fread with psd_read, fwrite + with psf_write and so on. + +2002-03-11 Erik de Castro Lopo + + * src/dwvw.c + Finally fixed all known problems with 12, 16 and 24 bit DWVW encoding. + + * tests/floating_point_test.c + Added tests for 12, 16 and 24 bit DWVW encoding. + +2002-03-03 Erik de Castro Lopo + + * m4/endian.m4 + Defines a new m4 macro AC_C_FIND_ENDIAN, for determining the endian-ness of + the target CPU. It first checks for the definition of BYTE_ORDER in + , then in and . If none of these work + and the C compiler is not a cross compiler it compiles and runs a program + to test for endian-ness. If the compiler is a cross compiler it makes a + guess based on $target_cpu. + + * configure.in + Modified to use AC_C_FIND_ENDIAN. + + * src/sfendian.h + Simplified. + +2002-02-23 Erik de Castro Lopo + + * tests/floating_point_test.c + Tests completely rewritten using the dft_cmp function. Now able to + calculate a quick guesstimate of the Signal to Noise Ratio of the encoder. + +2002-02-15 Erik de Castro Lopo + + * tests/dft_cmp.[ch] + New files containing functions for comparing pre and post lossily + compressed data using a quickly hacked DFT. + + * tests/utils.[ch] + New files containing functions for saving pre and post encoded data in a + file readable by the GNU Octave package. + +2002-02-13 Erik de Castro Lopo + + * m4/lrint.m4 m4/lrintf.m4 + Fixed m4 macros to define HAVE_LRINT and HAVE_LRINTF even when the test + is cached. + +2002-02-12 Erik de Castro Lopo + + * tests/floating_point_test.c + Fixed improper use of strncat (). + +2002-02-11 Erik de Castro Lopo + + * tests/headerless_test.c + New test program to test the ability to open and read a known file type as a + RAW header-less file. + +2002-02-07 Erik de Castro Lopo + + * tests/losy_comp_test.c + Added a test to ensure that the data read from a file is not all zeros. + + * examples/sfconvert.c + Added "-gsm610" encoding types. + +2002-01-29 Erik de Castro Lopo + + * examples/sfconvert.c + Added "-dwvw12", "-dwvw16" and "-dwvw24" encoding types. + + * tests/dwvw_test.c + New file for testing DWVW encoder/decoder. + +2002-01-28 Erik de Castro Lopo + + * src/dwvw.c + Implemented writing of DWVW. 12 bit seems to work, 16 and 24 bit still broken. + + * src/aiff.c + Improved reporting of encoding types. + + * src/voc.c + Clean up. + +2002-01-27 Erik de Castro Lopo + + * src/dwvw.c + New file implementing lossless Delta Word Variable Width (DWVW) encoding. + Reading 12 bit DWVW is now working. + + * src/aiff.c common.h sndfile.c + Added hooks for DWVW encoded AIFF and RAW files. + +2002-01-15 Erik de Castro Lopo + + * src/w64.c + Robustify header parsing. + + * src/wav_w64.h + Header file wav.h was renamed to wav_w64.h to signify sharing of + definitions across the two file types. + + * src/wav.c src/w64.c src/wav_w64.c + Refactoring. + Modified and moved functions with a high degree of similarity between + wav.c and w64.c to wav_w64.c. + +2002-01-14 Erik de Castro Lopo + + * src/w64.c + Completed work on getting read and write working. + + * examples/sfplay.c + Added code to scale floating point data so it plays at a reasonable volume. + + * tests/Makefile.am tests/write_read_test.c + Added tests for W64 files. + +2002-01-13 Erik de Castro Lopo + + * src/*.c + Modded all code in file header writing routines to use + psf_new_binheader_writef(). + Removed psf_binheader_writef() from src/common.c. + Globally replaced psf_new_binheader_writef with psf_binheader_writef. + +2002-01-12 Erik de Castro Lopo + + * src/*.c + Modded all code in file parsing routines to use psf_new_binheader_readf(). + Removed psf_binheader_readf() from src/common.c. + Globally replaced psf_new_binheader_readf with psf_binheader_readf. + + * src/common.[ch] + Added new function psf_new_binheader_writef () which will soon replace + psf_binheader_writef (). The new function has basically the same function + as the original but has a more flexible and capable interface. It also + allows the writing of 64 bit integer values for files contains 64 bit file + offsets. + +2002-01-11 Erik de Castro Lopo + + * src/formats.c src/sndfile.c src/sndfile.h + Added code allowing full enumeration of supported file formats via the + sf_command () interface. + This feature will allow applications to avoid needing recompilation when + support for new file formats are added to libsndfile. + + * tests/command_test.c + Added test code for the above feature. + + * examples/list_formats.c + New file. An example of the use of the supported file enumeration + interface. This program lists all the major formats and for each major + format the supported subformats. + +2002-01-10 Erik de Castro Lopo + + * src/*.[ch] tests/*.c + Changed command parameter of sf_command () function from a test string to + an int. The valid values for the command parameter begin with SFC_ and are + listed in src/sndfile.h. + +2001-12-20 Erik de Castro Lopo + + * src/formats.c src/sndfile.c + Added an way of enumerating a set of common file formats using the + sf_command () interface. This interface was suggested by Dominic Mazzoni, + one of the main authors of Audacity (http://audacity.sourceforge.net/). + +2001-12-26 Erik de Castro Lopo + + * src/sndfile.c + Added checking of filename parameter in sf_open_read (). Previousy, if a + NULL pointer was passed the library would segfault. + +2001-12-18 Erik de Castro Lopo + + * src/common.c src/common.h + Changed the len parameter of the endswap_*_array () functions from type + int to type long. + + * src/pcm.c + Fixed a problem which + +2001-12-15 Erik de Castro Lopo + + * src/sndfile.c + Added conditional #include for EMX/gcc on OS/2. Thanks to + Paul Hartman for pointing this out. + + * tests/lossy_comp_test.c tests/floating_point_test.c + Added definitions for M_PI for when it isn't defined in . + +2001-11-30 Erik de Castro Lopo + + * src/ircam.c + Re-implemented the header reader. Old version was making incorrect + assumptions about the endian-ness of the file from the magic number at the + start of the file. The new code looks at the integer which holds the + number of channels and determines the endian-ness from that. + +2001-11-30 Erik de Castro Lopo + + * src/aiff.c + Added support for other AIFC types ('raw ', 'in32', '23ni'). + Further work on IMA ADPCM encoding. + +2001-11-29 Erik de Castro Lopo + + * src/ima_adpcm.c + Renamed from wav_ima_adpcm.c. This file will soon handle IMA ADPCM + encodings for both WAV and AIFF files. + + * src/aiff.c + Started adding IMA ADPCM support. + +2001-11-28 Erik de Castro Lopo + + * src/double.c + New file for handling double precision floating point (SF_FORMAT_DOUBLE) + data. + + * src/wav.c src/aiff.c src/au.c src/raw.c + Added support for SF_FORMAT_DOUBLE data. + + * src/common.[ch] + Addition of endswap_long_array () for endian swapping 64 bit integers. This + function will work correctly on processors with 32 bit and 64 bit longs. + Optimised endswap_short_array () and endswap_int_array (). + + * tests/pcm_test.c + Added and extra check. After the first file of each type is written to disk + a checksum is performed of the first 64 bytes and checked against a pre- + calculated value. This will work whatever the endian-ness of the host + machine. + +2001-11-27 Erik de Castro Lopo + + * src/aiff.c + Added handling of u-law, A-law encoded AIFF files. Thanks to Tom Erbe for + supplying example files. + + * tests/lossy_comp_test.c + Added tests for above. + + * src/common.h src/*.c + Removed function typedefs from common.h and function pointer casting in all + the other files. This allows the compiler to perform proper type checking. + Hopefully this will prevernt problems like the sf_seek bug for OpenBSD, + BeOS etc. + + * src/common.[ch] + Added new function psf_new_binheader_readf () which will eventually replace + psf_binheader_readf (). The new function has basically the same function as + the original but has a more flexible and capable interface. It also allows + the reading of 64 bit integer values for files contains 64 bit file + offsets. + +2001-11-26 Erik de Castro Lopo + + * src/voc.c + Completed implementation of VOC file handling. Can now handle 8 and 16 bit + PCM, u-law and A-law files with one or two channels. + + * src/write_read_test.c tests/lossy_comp_test.c + Added tests for VOC files. + +2001-11-22 Erik de Castro Lopo + + * src/float_cast.h + Added inline asm version of lrint/lrintf for MacOS. Solution provided by + Stephane Letz. + + * src/voc.c + More work on this braindamaged format. The VOC files produced by SoX also + have a number of inconsistencies. + +2001-11-19 Erik de Castro Lopo + + * src/paf.c + Added support for 8 bit PCM PAF files. + + * tests/write_read_test.c + Added tests for 8 bit PAF files. + +2001-11-18 Erik de Castro Lopo + + * tests/pcm_test.c + New test program to test for correct scaling of integer values between + different sized integer containers (ie short -> int). + The new specs for libsndfile state that when the source and destination + containers are of a different size, the most significant bit of the source + value becomes the most significant bit of the destination container. + + * src/pcm.c src/paf.c + Modified to pass the above test program. + + * tests/write_read_test.c tests/lossy_comp_test.c + Modified to work with the new scaling rules. + +2001-11-17 Erik de Castro Lopo + + * src/raw.c tests/write_read_test.c tests/write_read_test.c + Added ability to do raw reads/writes of float, u-law and A-law files. + + * src/*.[ch] examples/*.[ch] tests/*.[ch] + Removed dependance on pcmbitwidth field of SF_INFO struct and moved to new + SF_FORMAT_* types and use of SF_ENDIAN_BIG/LITTLE/CPU. + +2001-11-12 Erik de Castro Lopo + + * src/*.[ch] + Started implmentation of major changes documented in doc/version1.html. + + Removed all usage of off_t which is not part of the ISO C standard. All + places which were using it are now using type long which is the type of + the offset parameter for the fseek function. + This should fix problems on BeOS, MacOS and *BSD like systems which were + failing "make check" because sizeof (long) != sizeof (off_t). + +-------------------------------------------------------------------------------- +This is the boundary between version 1 of the library above and version 0 below. +-------------------------------------------------------------------------------- + +2001-11-11 Erik de Castro Lopo + + * examples/sfplay_beos.cpp + Added BeOS version of sfplay.c. This needs to be compiled using a C++ + compiler so is therefore not built by default. Thanks to Marcus Overhagen + for providing this. + +2001-11-10 Erik de Castro Lopo + + * examples/sfplay.c + New example file showing how libsndfile can be used to read and play a + sound file. + At the moment on Linux is supported. Others will follow in the near future. + +2001-11-09 Erik de Castro Lopo + + * src/pcm.c + Fixed problem with normalisation code where a value of 1.0 could map to + a value greater than MAX_SHORT or MAX_INT. Thanks to Roger Dannenberg for + pointing this out. + +2001-11-08 Erik de Castro Lopo + + * src/pcm.c + Fixed scaling issue when reading/writing 8 bit files using + sf_read/sf_write_short (). + On read, values are scaled so that the most significant bit in the char + ends up in the most significant bit of the short. On write, values are + scaled so that most significant bit in the short ends up as the most + significant bit in the char. + +2001-11-07 Erik de Castro Lopo + + * src/au.c src/sndfile.c + Added support for 32 bit float data in big and little endian AU files. + + * tests/write_read_test.c + Added tests for 32 bit float data in AU files. + +2001-11-06 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Finalised testing of stereo files where possible. + +2001-11-05 Erik de Castro Lopo + + * src/wav_ms_adpcm.c + Fixed bug in writing stereo MS ADPCM WAV files. Thanks to Xu Xin for + pointing out this problem. + +2001-10-24 Erik de Castro Lopo + + * src/wav_ms_adpcm.c + Modified function srate2blocksize () to handle 44k1Hz stereo files. + +2001-10-21 Erik de Castro Lopo + + * src/w64.c + Added support for Sonic Foundry 64 bit WAV format. As Linux (my main + development platform) does not yet support 64 bit file offsets by default, + current handling of this file format treats everything as 32 bit and fails + openning the file, if it finds anything that goes beyond 32 bit values. + + * src/sndfile.[hc] src/common.h src/Makefile.am + Added hooks for W64 support. + +2001-10-21 Erik de Castro Lopo + + * configure.in + Added more warnings options to CFLAGS when the gcc compiler is detected. + + * src/*.[ch] tests/*.c examples/*.c + Started fixing the warning messages due to the new CFLASG. + + * src/voc.c + More work on VOC file read/writing. + + * src/paf.c + Found that PAF files were not checking the normalisation flag when reading + or writing floats and doubles. Fixed it. + + * tests/floating_point_test.c + Added specific test for the above problem. + + * src/float_cast.h src/pcm.c + Added a section for Win32 to define lrint () and lrintf () in the header + and implement it in the pcm.c + +2001-10-20 Erik de Castro Lopo + + * sndfile-config.in m4/sndfile.m4 + These files were donated by Conrad Parker who also provided instructions + on how to install them using autoconf/automake. + + * src/float_cast.h + Fiddled around with this file some more. On Linux and other gcc supported + OSes use the C99 functions lrintf() and lrint() for casting from floating + point to int without incurring the huge perfromance penalty (particularly + on the i386 family) caused by the regular C cast from float to int. + These new C99 functions replace the FLOAT_TO_* and DOUBLE_TO_* macros which + I had been playing with. + + * configure.in m4/lrint.m4 m4/lrintf.m4 + Add detection of these functions. + +2001-10-17 Erik de Castro Lopo + + * src/voc.c + Completed code for reading VOC files containing a single audio data + segment. + Started implementing code to handle files with multiple VOC_SOUND_DATA + segments but couldn't be bothered finishing it. Multiple segment files can + have different sample rates for different sections and other nasties like + silence and repeat segments. + +2001-10-16 Erik de Castro Lopo + + * src/common.h src/*.c + Removed SF_PRIVATE struct field fdata and replaced it with extra_data. + + * src/voc.c + Further development of the read part of this woefult file format. + +2001-10-04 Erik de Castro Lopo + + * src/float_cast.h + Implemented gcc and i386 floating point to int cast macros. Standard cast + will be used when not on gcc for i385. + + * src/pcm.c + Modified all uses of FLOAT/DOUBLE_TO_INT and FLOAT/DOUBLE_TO_SHORT casts to + comply with macros in float_cast.h. + +2001-10-04 Erik de Castro Lopo + + * src/voc.c + Changed the TYPE_xxx enum names to VOC_TYPE_xxx to prevent name clashes + on MacOS with CodeWarrior 6.0. + + * MacOS/MacOS-readme.txt + Updated the compile instructions. Probably still need work as I don't have + access to a Mac. + +2001-10-01 Erik de Castro Lopo + + * src/wav.c src/aiff.c common.c + Changed all references to snprintf to LSF_SNPRINTF and all vsnprintf to + LSF_VSNPRINTF. LSF_VSNPRINTF and LSF_VSNPRINTF are defined in common.h. + + * src/common.h + Added checking of HAVE_SNPRINTF and HAVE_VSNPRINTF and defining + LSF_VSNPRINTF and LSF_VSNPRINTF to appropriate values. + + * src/missing.c + New file containing a minimal implementation of snprintf and vsnprintf + functions named missing_snprintf and missing_vsnprintf respectively. These + are only compliled into the binary if snprintf and/or vsnprintf are not + available. + +2001-09-29 Erik de Castro Lopo + + * src/ircam.c + New file to handle Berkeley/IRCAM/CARL files. + + * src/sndfile.c src/common.h + Modified for IRCAM handling. + + * tests/*.c + Added tests for IRCAM files. + +2001-09-27 Erik de Castro Lopo + + * src/wav.c + Apparently microsoft windows (tm) doesn't like ulaw and Alaw WAV files with + 20 byte format chunks (contrary to ms's own documentation). Fixed the WAV + header writing code to generate smaller ms compliant ulaw and Alaw WAV + files. + +2001-09-17 Erik de Castro Lopo + + * tests/stdio_test.sh tests/stdio_test.c + Shell script was rewritten as a C program due to incompatibilities of the + sh shell on Linux and Solaris. + +2001-09-16 Erik de Castro Lopo + + * tests/stdio_test.sh tests/stdout_test.c tests/stdin_test.c + New test programs to verify the correct operation of reading from stdin and + writing to stdout. + + * src/sndfile.c wav.c au.c nist.c paf.c + Fixed a bugs uncovered by the new test programs above. + +2001-09-15 Erik de Castro Lopo + + * src/sndfile.c wav.c + Fixed a bug preventing reading a file from stdin. Found by T. Narita. + +2001-09-12 Erik de Castro Lopo + + * src/common.h + Fixed a problem on OpenBSD 2.9 which was causing sf_seek() to fail on IMA + WAV files. Root cause was the declaration of the func_seek typedef not + matching the functions it was actually being used to point to. In OpenBSD + sizeof (off_t) != sizeof (int). Thanks to Heikki Korpela for allowing me + to log into his OpenBSD machine to debug this problem. + +2001-09-03 Erik de Castro Lopo + + * src/sndfile.c + Implemented sf_command ("norm float"). + + * src/*.c + Implemented handling of sf_command ("set-norm-float"). Float normalization + can now be turned on and off. + + * tests/double_test.c + Renamed to floating_point_test.c. Modified to include tests for all scaled + reads and writes of floats and doubles. + + * src/au_g72x.c + Fixed bug in normalization code found with improved floating_point_test + program. + + * src/wav.c + Added code for parsing 'INFO' and 'LIST' chunks. Will be used for extract + text annotations from WAV files. + + * src/aiff.c + Added code for parsing '(c) ' and 'ANNO' chunks. Will be used for extract + text annotations from WAV files. + +2001-09-02 Erik de Castro Lopo + + * examples/sf_info.c example/Makefile.am + Renamed to sndfile_info.c. The program sndfile_info will now be installed + when the library is installed. + + * src/float_cast.h + New file defining floating point to short and int casts. These casts will + eventually replace all flot and double casts to short and int. See comments + at the top of the file for the reasoning. + + * src/*.c + Changed all default float and double casts to short or int with macros + defined in floatcast.h. At the moment these casts do nothing. They will be + replaced with faster float to int cast operations in the near future. + +2001-08-31 Erik de Castro Lopo + + * tests/command_test.c + New file for testing sf_command () functionality. + + * src/sndfile.c + Revisiting of error return values of some functions. + Started implementing sf_command () a new function will allow on-the-fly + modification of library behaviour, or instance, sample value scaling. + + * src/common.h + Added hook for format specific sf_command () calls to SNDFILE struct. + + * doc/api.html + Updated and errors corrected. + + * doc/command.html + New documentation file explaining new sf_command () function. + +2001-08-11 Erik de Castro Lopo + + * src/sndfile.c + Fixed error return values from sf_read*() and sf_write*(). There were + numerous instances of -1 being returned through size_t. These now all set + error int the SF_PRIVATE struct and return 0. Thanks to David Viens for + spotting this. + +2001-08-01 Erik de Castro Lopo + + * src/common.c + Fixed use of va_arg() calls that were causing warning messages with the + latest version of gcc (thanks Maurizio Umberto Puxeddu). + +2001-07-25 Erik de Castro Lopo + + * src/*.c src/sfendian.h + Moved definition of MAKE_MARKER macro to sfendian.h + +2001-07-23 Erik de Castro Lopo + + * src/sndfile.c + Modified sf_get_lib_version () so that version string will be visible using + the Unix strings command. + + * examples/Makefile.am examples/sfinfo.c + Renamed sfinfo program and source code to sf_info. This prevents a name + clash with the program included with libaudiofile. + +2001-07-22 Erik de Castro Lopo + + * tests/read_seek_test.c tests/lossy_comp_test.c + Added tests for sf_read_float () and sf_readf_float (). + + * src/voc.c + New files for handling Creative Voice files (not complete). + + * src/samplitude.c + New files for handling Samplitude files (not complete). + +2001-07-21 Erik de Castro Lopo + + * src/aiff.c src/au.c src/paf.c src/svx.c src/wav.c + Converted these files to using psf_binheader_readf() function. Will soon be + ready to attempt to make reading writing from pipes work reliably. + + * src/*.[ch] + Added code for sf_read_float () and sf_readf_float () methods of accessing + file data. + +2001-07-20 Erik de Castro Lopo + + * src/paf.c src/wav_gsm610.c + Removed two printf()s which had escaped notice for some time (thanks + Sigbjørn Skjæret). + +2001-07-19 Erik de Castro Lopo + + * src/wav_gsm610.c + Fixed a bug which prevented GSM 6.10 encoded WAV files generated by + libsndfile from being played in Windoze (thanks klay). + +2001-07-18 Erik de Castro Lopo + + * src/common.[ch] + Implemented psf_binheader_readf() which will do for file header reading what + psf_binheader_writef() did for writing headers. Will eventually allow + libsndfile to read and write from pipes, including named pipes. + +2001-07-16 Erik de Castro Lopo + + * MacOS/config.h Win32/config.h + Attempted to bring these two files uptodate with src/config.h. As I don't + have access to either of these systems support for them may be completely + broken. + +2001-06-18 Erik de Castro Lopo + + * src/float32.c + Fixed bug for big endian processors that can't read 32 bit IEEE floats. Now + tested on Intel x86 and UltraSparc processors. + +2001-06-13 Erik de Castro Lopo + + * src/aiff.c + Modified to allow REX files (from Propellorhead's Recycle and Reason + programs) to be read. + REX files are basically an AIFF file with slightly unusual sequence of + chunks (AIFF files are supposed to allow any sequence) and some extra + application specific information. + Not yet able to write a REX file as the details of the application specific + data is unknown. + +2001-06-12 Erik de Castro Lopo + + * src/wav.c + Fixed endian bug when reading PEAK chunk on big endian machines. + + * src/common.c + Fixed endian bug when reading PEAK chunk on big endian machines with + --enable-force-broken-float configure option. + Fix psf_binheader_writef for (FORCE_BROKEN_FLOAT ||______) + +2001-06-07 Erik de Castro Lopo + + * configure.in src/config.h.in + Removed old CAN_READ_WRITE_x86_IEEE configure variable now that float + capabilities are detected at run time. + Added FORCE_BROKEN_FLOAT to allow testing of broken float code on machines + where the processor can in fact handle floats correctly. + + * src/float32.c + Rejigged code reading and writing of floats on broken processors. + + * m4/ + Removed this directory and all its files as they are no longer needed. + +2001-06-05 Erik de Castro Lopo + + * tests/peak_chunk_test.c + New test to validate reading and writing of peak chunk. + + * examples/sfconvert + Added -float32 option. + + * src/*.c + Changed all error return values to negative values (ie the negative of what + they were). + + * src/sndfile.c tests/error_test.c + Modified to take account of the previous change. + +2001-06-04 Erik de Castro Lopo + + * src/float32.c + File renamed from wav_float.c and renamed function to something more + general. + Added runtime detection of floating point capabilities. + Added recording of peaks during write for generation of PEAK chunk. + + * src/wav.c src/aiff.c + Added handing for PEAK chunk for floating point files. PEAK is read when the + file headers are read and generated when the file is closed. Logic is in + place for adding PEAK chunk to end of file when writing to a pipe (reading + and writing from/to pipe to be implemented soon). + + * src/sndfile.c + Modified sf_signal_max () to use PEAK values if present. + +2001-06-03 Erik de Castro Lopo + + * src/*.c + Added pcm_read_init () and pcm_write_init () to src/pcm.c and removed all + other calls to functions in this file from the filetype specific files. + + * src/*.c + Added alaw_read_init (), alaw_write_int (), ulaw_read_init () and + ulaw_write_init () and removed all other calls to functions in alaw.c and + ulaw.c from the filetype specific files. + + * tests/write_read_test.c + Added tests to validate sf_seek () on all file types. + + * src/raw.c + Implemented raw_seek () function to fix a bug where + sf_seek (file, 0, SEEK_SET) on a RAW file failed. + + * src/paf.c + Fixed a bug in paf24_seek () found due to added seeks tests in + tests/write_read_test.c + +2001-06-01 Erik de Castro Lopo + + * tests/read_seek_test.c + Fixed a couple of broken binary files. + + * src/aiff.c src/wav.c + Added handling of PEAK chunks on file read. + +2001-05-31 Erik de Castro Lopo + + * check_libsndfile.py + New file for the regression testing of libsndfile. + check_libsndfile.py is a Python script which reads in a file containing + filenames of audio files. Each file is checked by running the examples/sfinfo + program on them and checking for error or warning messages in the libsndfile + log buffer. + + * check_libsndfile.list + This is an example list of audio files for use with check_libsndfile.py + + * tests/lossy_comp_test.c + Changed the defined value of M_PI for math header files which don't have it. + This fixed validation test failures on MetroWerks compilers. Thanks to Lord + Praetor Satanus of Acheron for bringing this to my attention. + +2001-05-30 Erik de Castro Lopo + + * src/common.[ch] + Removed psf_header_setf () which was no longer required after refactoring + and simplification of header writing. + Added 'z' format specifier to psf_binheader_writef () for zero filling header + with N bytes. Used by paf.c and nist.c + + * tests/check_log_buffer.c + New file implementing check_log_buffer () which reads the log buffer of a + SNDFILE* object and searches for error and warning messages. Calls exit () + if any are found. + + * tests/*.c + Added calls to check_log_buffer () after each call to sf_open_XXX (). + +2001-05-29 Erik de Castro Lopo + + * src/wav.c src/wav_ms_adpcm.c src/wav_gsm610.c + Major rehack of header writing using psf_binheader_writef (). + +2001-05-28 Erik de Castro Lopo + + * src/wav.c src/wav_ima_adpcm.c + Major rehack of header writing using psf_binheader_writef (). + +2001-05-27 Erik de Castro Lopo + + * src/wav.c + Changed return type of get_encoding_str () to prevent compiler warnings on + Mac OSX. + + * src/aiff.c src/au.c + Major rehack of header writing using psf_binheader_writef (). + +2001-05-25 Erik de Castro Lopo + + * src/common.h src/common.c + Added comments. + Name of log buffer changed from strbuffer to logbuffer. + Name of log buffer index variable changed from strindex to logindex. + + * src/*.[ch] + Changed name of internal logging function from psf_sprintf () to + psf_log_printf (). + Changed name of internal header generation functions from + psf_[ab]h_printf () to psf_asciiheader_printf () and + psf_binheader_writef (). + Changed name of internal header manipulation function psf_hsetf () to + psf_header_setf (). + +2001-05-24 Erik de Castro Lopo + + * src/nist.c + Fixed reading and writing of sample_byte_format header. "01" means little + endian and "10" means big endian regardless of bit width. + + * configure.in + Detect Mac OSX and disable -Wall and -pedantic gcc options. Mac OSX is + way screwed up and spews out buckets of warning messages from the system + headers. + Added --disable-gcc-opt configure option (sets gcc optimisation to -O0 ) for + easier debugging. + Made decision to harmonise source code version number and .so library + version number. Future releases will stick to this rule. + + * doc/new_file_type.HOWTO + New file to document the addition of new file types to libsndfile. + +2001-05-23 Erik de Castro Lopo + + * src/nist.c + New file for reading/writing Sphere NIST audio file format. + Originally requested by Elis Pomales in 1999. + Retrieved from unstable (and untouched for 18 months) branch of libsndfile. + Some vital information gleaned from the source code to Bill Schottstaedt's + sndlib library : ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz + Currently reading and writing 16, 24 and 32 bit, big-endian and little + endian, stereo and mono files. + + * src/common.h src/common.c + Added psf_ah_printf () function to help construction of ASCII headers (ie NIST). + + * configure.in + Added test for vsnprintf () required by psf_ah_printf (). + + * tests/write_read_test.c + Added tests for supported NIST files. + +2001-05-22 Erik de Castro Lopo + + * tests/write_read_test.c + Added tests for little endian AIFC files. + + * src/aiff.c + Minor re-working of aiff_open_write (). + Added write support for little endian PCM encoded AIFC files. + +2001-05-13 Erik de Castro Lopo + + * src/aiff.c + Minor re-working of aiff_open_read (). + Added read support for little endian PCM encoded AIFC files from the Mac + OSX CD ripper program. Guillaume Lessard provided a couple of sample files + and a working patch. + The patch was not used as is but gave a good guide as to what to do. + +2001-05-11 Erik de Castro Lopo + + * src/sndfile.h + Fixed comments about endian-ness of WAV and AIFF files. Guillaume Lessard + pointed out the error. + +2001-04-23 Erik de Castro Lopo + + * examples/make_sine.c + Re-write of this example using sample rate and required frequency in Hz. + +2001-02-11 Erik de Castro Lopo + + * src/sndfile.c + Fixed bug that prevented known file types from being read as RAW PCM data. + +2000-12-16 Erik de Castro Lopo + + * src/aiff.c + Added handing of COMT chunk. + +2000-11-16 Erik de Castro Lopo + + * examples/sfconvert.c + Fixed bug in normalisatio code. Pointed out by Johnny Wu. + +2000-11-08 Erik de Castro Lopo + + * Win32/config.h + Fixed the incorrect setting of HAVE_ENDIAN_H parameter. Win32 only issue. + +2000-10-27 Erik de Castro Lopo + + * tests/Makefile.am + Added -lm for write_read_test_LDADD. + +2000-10-16 Erik de Castro Lopo + + * src/sndfile.c src/au.c + Fixed bug which prevented writing of G723 24kbps AU files. + + * tests/lossy_comp_test.c + Corrrection to options for G723 tests. + + * configure.in + Added --disable-gcc-pipe option for DJGPP compiler (gcc on MS-DOS) which + doesn't allow gcc -pipe option. + +2000-09-03 Erik de Castro Lopo + + * src/ulaw.c src/alaw.c src/wav_imaadpcm.c src/msadpcm.c src/wav_gsm610.c + Fixed normailsation bugs shown up by new double_test program. + +2000-08-31 Erik de Castro Lopo + + * src/pcm.c + Fixed bug in normalisation code (spotted by Steve Lhomme). + + * tests/double_test.c + New file to test scaled and unscaled sf_read_double() and sf_write_double() + functions. + +2000-08-28 Erik de Castro Lopo + + * COPYING + Changed to the LGPL COPYING file (spotted by H. S. Teoh). + +2000-08-21 Erik de Castro Lopo + + * src/sndfile.h + Removed prototype of unimplemented function sf_get_info(). Added prototype + for sf_error_number() Thanks to Sigbjørn Skjæret for spotting these. + +2000-08-18 Erik de Castro Lopo + + * src/newpcm.h + New file to contain a complete rewrite of the PCM data handling. + +2000-08-15 Erik de Castro Lopo + + * src/sndfile.c + Fixed a leak of FILE* pointers in sf_open_write(). Thanks to Sigbjørn + Skjæret for spotting this one. + +2000-08-13 Erik de Castro Lopo + + * src/au_g72x.c src/G72x/g72x.c + Added G723 encoded AU file support. + + * tests/lossy_comp_test.c + Added tests for G721 and G723 encoded AU files. + +2000-08-06 Erik de Castro Lopo + + * all files + Changed the license to LGPL. Albert Faber who had copyright on + Win32/unistd.h gave his permission to change the license on that file. All + other files were either copyright erikd AT mega-nerd DOT com or copyright + under a GPL/LGPL compatible license. + +2000-08-06 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Fixed incorrect error message. + + * src/au_g72x.c src/G72x/* + G721 encoded AU files now working. + + * Win32/README-Win32.txt + Replaced this file with a new one which gives a full explanation + of how to build libsndfile under Win32. Thanks to Mike Ricos. + +2000-08-05 Erik de Castro Lopo + + * src/*.[ch] + Removed double leading underscores from the start of all variable and + function names. Identifiers with a leading underscores are reserved + for use by the compiler. + + * src/au_g72x.c src/G72x/* + Continued work on G721 encoded AU files. + +2000-07-12 Erik de Castro Lopo + + * src/G72x/* + New files for reading/writing G721 and G723 ADPCM audio. These files + are from a Sun Microsystems reference implementation released under a + free software licence. + Extensive changes to this code to make it fit in with libsndfile. + See the ChangeLog in this directory for details. + + * src/au_g72x.c + New file for G721 encoded AU files. + +2000-07-08 Erik de Castro Lopo + + * libsndfile.spec.in + Added a spec file for making RPMs. Thanks to Josh Green for supplying this. + +2000-06-28 Erik de Castro Lopo + + * src/sndfile.c src/sndfile.h + Add checking for and handling of header-less u-law encoded AU/SND files. + Any file with a ".au" or ".snd" file extension and without the normal + AU file header is treated as an 8kHz, u-law encoded file. + + * src/au.h + New function for opening a headerless u-law encoded file for read. + +2000-06-04 Erik de Castro Lopo + + * src/paf.c + Add checking for files shorter than minimal PAF file header length. + +2000-06-02 Erik de Castro Lopo + + * tests/write_read_test.c + Added extra sf_perror() calls when sf_write_XXXX fails. + +2000-05-29 Erik de Castro Lopo + + * src/common.c + Modified usage of va_arg() macro to work correctly on PowerPC + Linux. Thanks to Kyle Wheeler for giving me ssh access to his + machine while I was trying to track this down. + + * configure.in src/*.[ch] + Sorted out some endian-ness issues brought up by PowerPC Linux. + + * tests/read_seek_test.c + Added extra debugging for when tests fail. + +2000-05-18 Erik de Castro Lopo + + * src/wav.c + Fixed bug in GSM 6.10 handling for big-endian machines. Thanks + to Sigbjørn Skjæret for reporting this. + +2000-04-25 Erik de Castro Lopo + + * src/sndfile.c src/wav.c src/wav_gsm610.c + Finallised writing of GSM 6.10 WAV files. + + * tests/lossy_comp_test.c + Wrote new test code for GSM 6.10 files. + + * examples/sfinfo.c + Fixed incorrect format in printf() statement. + +2000-04-06 Erik de Castro Lopo + + * src/sndfile.h.in + Fixed comments about sf_perror () and sf_error_str (). + +2000-03-14 Erik de Castro Lopo + + * configure.in + Fixed --enable-justsrc option. + +2000-03-07 Erik de Castro Lopo + + * wav.c + Fixed checking of bytespersec field of header. Still some weirdness + with some files. + +2000-03-05 Erik de Castro Lopo + + * tests/lossy_comp_test.c + Added option to test PCM WAV files (sanity check). + Fixed bug in sf_seek() tests. + +2000-02-29 Erik de Castro Lopo + + * src/sndfile.c src/wav.c + Minor changes to allow writing of GSM 6.10 WAV files. + +2000-02-28 Erik de Castro Lopo + + * configure.in Makefile.am src/Makefile.am + Finally got around to figuring out how to build a single library from + multiple source directories. + Reading GSM 6.10 files now seems to work. + +2000-01-03 Erik de Castro Lopo + + * src/wav.c + Added more error reporting in read_fmt_chunk(). + +1999-12-21 Erik de Castro Lopo + + * examples/sfinfo.c + Modified program to accept multiple filenames from the command line. + +1999-11-27 Erik de Castro Lopo + + * src/wav_ima_adpcm.c + Moved code around in preparation to adding ability to read/write IMA ADPCM + encoded AIFF files. + +1999-11-16 Erik de Castro Lopo + + * src/common.c + Fixed put_int() and put_short() macros used by _psf_hprintf() which were + causing seg. faults on Sparc Solaris. + +1999-11-15 Erik de Castro Lopo + + * src/common.c + Added string.h to includes. Thanks to Sigbjxrn Skjfret. + + * src/svx.c + Fixed __svx_close() function to ensure FORM and BODY chunks are correctly + set. + +1999-10-01 Erik de Castro Lopo + + * src/au.c + Fixed handling of incorrect size field in AU header on read. Thanks to + Christoph Lauer for finding this problem. + +1999-09-28 Erik de Castro Lopo + + * src/aiff.c + Fixed a bug with incorrect SSND chunk length being written. This also lead + to finding an minor error in AIFF header parsing. Thanks to Dan Timis for + pointing this out. + +1999-09-24 Erik de Castro Lopo + + * src/paf.c + Fixed a bug with reading and writing 24 bit stereo PAF files. This problem + came to light when implementing tests for the new functions which operate + in terms of frames rather than items. + +1999-09-23 Erik de Castro Lopo + + * src/sndfile.c + Modified file type detection to use first 12 bytes of file rather than + file name extension. Required this because NIST files use the same + filename extension as Microsoft WAV files. + + * src/sndfile.c src/sndfile.h + Added short, int and double read/write functions which work in frames + rather than items. This was originally suggested by Maurizio Umberto + Puxeddu. + +1999-09-22 Erik de Castro Lopo + + * src/svx.c + Finished off implementation of write using __psf_hprintf(). + +1999-09-21 Erik de Castro Lopo + + * src/common.h + Added a buffer to SF_PRIVATE for writing the header. This is required + to make generating headers for IFF/SVX files easier as well as making + it easier to do re-write the headers which will be required when + sf_rewrite_header() is implemented. + + * src/common.c + Implemented __psf_hprintf() function. This is an internal function + which is documented briefly just above the code. + +1999-09-05 Erik de Castro Lopo + + * src/sndfile.c + Fixed a bug in sf_write_raw() where it was returning incorrect values + (thanks to Richard Dobson for finding this one). Must put in a test + routine for sf_read_raw and sf_write_raw. + + * src/aiff.c + Fixed default FORMsize in __aiff_open_write (). + + * src/sndfile.c + Added copy of filename to internal data structure. IFF/SVX files + contain a NAME header chunk. Both sf_open_read() and sf_open_write() + copy the file name (less the leading path information) to the + filename field. + + * src/svx.c + Started implementing writing of files. + +1999-08-04 Erik de Castro Lopo + + * src/svx.c + New file for reading/writing 8SVX and 16SVX files. + + * src/sndfile.[ch] src/common.h + Changes for SVX files. + + * src/aiff.c + Fixed header parsing when unknown chunk is found. + +1999-08-01 Erik de Castro Lopo + + * src/paf.c + New file for reading/writing Ensoniq PARIS audio file format. + + * src/sndfile.[ch] src/common.h + Changes for PAF files. + + * src/sndfile.[ch] + Added stuff for sf_get_lib_version() function. + + +1999-07-31 Erik de Castro Lopo + + * src/sndfile.h MacOS/config.h + Fixed minor MacOS configuration issues. + +1999-07-30 Erik de Castro Lopo + + * MacOS/ + Added a new directory for the MacOS config.h file and the + readme file. + + * src/aiff.c + Fixed calculation of datalength when reading SSND chunk. Thanks to + Sigbjørn Skjæret for pointing out this error. + +1999-07-29 Erik de Castro Lopo + + * src/sndfile.c src/sndfile.h src/raw.c + Further fixing of #includes for MacOS. + +1999-07-25 Erik de Castro Lopo + + * src/wav.c src/aiff.c + Added call to ferror () in main header parsing loop of __XXX_open_read + functions. This should fix problems on platforms (MacOS, AmigaOS) where + fseek()ing or fread()ing beyond the end of the file puts the FILE* + stream in an error state until clearerr() is called. + + * tests/write_read_test.c + Added tests for RAW header-less PCM files. + + * src/common.h + Moved definition of struct tribyte to pcm.c which is the only place + which needs it. + + * src/pcm.c + Modified all code which assumed sizeof (struct tribyte) == 3. This code + did not work on MacOS. Thanks to Ben "Jacobs" for pointing this out. + + * src/au.c + Removed from list of #includes (not being used). + + * src/sndfile.c + Added MacOS specific #ifdef to replace . + + * src/sndfile.h + Added MacOS specific #ifdef to replace . + + * src/sndfile.h + Added MacOS specific typedef for off_t. + + * MacOS-readme.txt + New file with instructions for building libsndfile under MacOS. Thanks + to Ben "Jacobs" for supplying these instructions. + +1999-07-24 Erik de Castro Lopo + + * configure.in + Removed sndfile.h from generated file list as there were no longer + any autoconf substitutions being made. + + * src/raw.c + New file for handling raw header-less PCM files. In order to open these + for read, the user must specify format, pcmbitwidth and channels in the + SF_INFO struct when calling sf_open_read (). + + * src/sndfile.c + Added support for raw header-less PCM files. + +1999-07-22 Erik de Castro Lopo + + * examples/sfinfo.c + Removed options so the sfinfo program always prints out all the information. + +1999-07-19 Erik de Castro Lopo + + * src/alaw.c + New file for A-law encoding (similar to u-law). + + * tests/alaw_test.c + New test program to test the A-law encode/decode lookup tables. + + * tests/lossy_comp_test.c + Added tests for a-law encoded WAV, AU and AULE files. + +1999-07-18 Erik de Castro Lopo + + * src/sndfile.c src/au.c + Removed second "#include ". Thanks to Ben "Jacobs" for pointing + this out. + +1999-07-18 Erik de Castro Lopo + + * tests/ulaw_test.c + New test program to test the u-law encode/decode lookup tables. + +1999-07-16 Erik de Castro Lopo + + * src/sndfile.h + Made corrections to comments on the return values from sf_seek (). + + * src/sndfile.c + Fixed boundary condition checking bug and accounting bug in sf_read_raw (). + +1999-07-15 Erik de Castro Lopo + + * src/au.c src/ulaw.c + Finished implementation of u-law encoded AU files. + + * src/wav.c + Implemented reading and writing of u-law encoded WAV files. + + * tests/ + Changed name of adpcm_test.c to lossy_comp_test.c. This test program + will now be used to test Ulaw and Alaw encoding as well as APDCM. + Added tests for Ulaw encoded WAV files. + +1999-07-14 Erik de Castro Lopo + + * tests/adpcm_test.c + Initialised amp variable in gen_signal() to remove compiler warning. + +1999-07-12 Erik de Castro Lopo + + * src/aiff.c + In __aiff_open_read () prevented fseek()ing beyond end of file which + was causing trouble on MacOS with the MetroWerks compiler. Thanks to + Ben "Jacobs" for pointing this out. + + *src/wav.c + Fixed as above in __wav_open_read (). + +1999-07-01 Erik de Castro Lopo + + * src/wav_ms_adpcm.c + Implemented MS ADPCM encoding. Code cleanup of decoder. + + * tests/adpcm_test.c + Added tests for MS ADPCM WAV files. + + * src/wav_ima_adpcm.c + Fixed incorrect parameter in call to srate2blocksize () from + __ima_writer_init (). + +1999-06-23 Erik de Castro Lopo + + * tests/read_seek_test.c + Added test for 8 bit AIFF files. + +1999-06-18 Erik de Castro Lopo + + * tests/write_read_test.c + Removed test for IMA ADPCM WAV files which is now done in adpcm_test.c + + * configure.in + Added -Wconversion to CFLAGS. + + * src/*.c tests/*.c examples/*.c + Fixed all warnings resulting from use of -Wconversion. + +1999-06-17 Erik de Castro Lopo + + * src/wav.c + Added fact chunk handling on read and write for all non WAVE_FORMAT_PCM + WAV files. + + * src/wav_ima.c + Changed block alignment to be dependant on sample rate. This should make + WAV files created with libsndfile compatible with the MS Windows media + players. + + * tests/adpcm_test.c + Reimplemented adpcm_test_short and implemented adpcm_test_int and + adpcm_test_double. + Now have full testing of IMA ADPCM WAV file read, write and seek. + +1999-06-15 Erik de Castro Lopo + + * src/wav_float.c + Fixed function prototype for x86f2d_array () which was causing ocassional + seg. faults on Sparc Solaris machines. + +1999-06-14 Erik de Castro Lopo + + * src/aiff.c + Fixed bug in __aiff_close where the length fields in the header were + not being correctly calculated before writing. + + * tests/write_read_test.c + Modified to detect the above bug in WAV, AIFF and AU files. + +1999-06-12 Erik de Castro Lopo + + * Win32/* + Added a contribution from Albert Faber to allow libsndfile to compile + under Win32 systems. libsndfile will now be used as part of LAME the + the MPEG 1 Layer 3 encoder (http://internet.roadrunner.com/~mt/mp3/). + +1999-06-11 Erik de Castro Lopo + + * configure.in + Changed to reflect previous changes. + + * src/wav_ima_adpcm.c + Fixed incorrect calculation of bytespersec header field (IMA ADPCM only). + + Fixed bug when writing from int or double data to IMA ADPCM file. Will need + to write test code for this. + + Fixed bug in __ima_write () whereby the length of the current block was + calculated incorrectly. Thanks to Jongcheon Park for pointing this out. + +1999-03-27 Erik de Castro Lopo + + * src/*.c + Changed all read/write/lseek function calls to fread/fwrite/ + fseek/ftell and added error checking of return values from + fread and fwrite in critical areas of the code. + + * src/au.c + Fixed incorrect datasize element in AU header on write. + + * tests/error_test.c + Add new test to check all error values have an associated error + string. This will avoid embarrassing real world core dumps. + +1999-03-23 Erik de Castro Lopo + + * src/wav.c src/aiff.c + Added handling for unknown chunk markers in the file. + +1999-03-22 Erik de Castro Lopo + + * src/sndfile.c + Filled in missing error strings in SndfileErrors array. Missing entries + can cause core dumps when calling sf_error-str (). Thanks to Sam + for finding this problem. + +1999-03-21 Erik de Castro Lopo + + * src/wav_ima_adpcm.c + Work on wav_ms_adpcm.c uncovered a bug in __ima_read () when reading + stereo files. Caused by not adjusting offset into buffer of decoded + samples for 2 channels. A similar bug existed in __ima_write (). + Need a test for stereo ADPCM files. + + * src/wav_ms_adpcm.c + Decoder working correctly. + +1999-03-18 Erik de Castro Lopo + + * configure.in Makefile.am + Added --enable-justsrc configuration variable sent by Sam + . + + * src/wav_ima_adpcm.c + Fixed bug when reading beyond end of data section due to not + checking pima->blockcount. + This uncovered __ima_seek () bug due to pima->blockcount being set + before calling __ima_init_block (). + +1999-03-17 Erik de Castro Lopo + + * src/wav.c + Started implementing MS ADPCM decoder. + If file is WAVE_FORMAT_ADPCM and length of data chunk is odd, this + encoder seems to add an extra byte. Why not just give an even data + length? + +1999-03-16 Erik de Castro Lopo + + * src/wav.c + Split code out of wav.c to create wav_float.c and wav_ima_adpcm.c. + This will make it easier to add and debug other kinds of WAV files + in future. + +1999-03-14 Erik de Castro Lopo + + * tests/ + Added adpcm_test.c which implements test functions for + IMA ADPCM reading/writing/seeking etc. + + * src/wav.c + Fixed many bugs in IMA ADPCM encoder and decoder. + +1999-03-11 Erik de Castro Lopo + + * src/wav.c + Finished implementing IMA ADPCM encoder and decoder (what a bitch!). + +1999-03-03 Erik de Castro Lopo + + * src/wav.c + Started implementing IMA ADPCM decoder. + +1999-03-02 Erik de Castro Lopo + + * src/sndfile.c + Fixed bug where the sf_read_XXX functions were returning a + incorrect read count when reading past end of file. + Fixed bug in sf_seek () when seeking backwards from end of file. + + * tests/read_seek_test.c + Added multiple read test to short_test(), int_test () and + double_test (). + Added extra chunk to all test WAV files to test that reading + stops at end of 'data' chunk. + +1999-02-21 Erik de Castro Lopo + + * tests/write_read_test.c + Added tests for little DEC endian AU files. + + * src/au.c + Add handling for DEC format little endian AU files. + +1999-02-20 Erik de Castro Lopo + + * src/aiff.c src/au.c src/wav.c + Add __psf_sprintf calls during header parsing. + + * src/sndfile.c src/common.c + Implement sf_header_info (sndfile.c) function and __psf_sprintf (common.c). + + * tests/write_read_test.c + Added tests for 8 bit PCM files (WAV, AIFF and AU). + + * src/au.c src/aiff.c + Add handling of 8 bit PCM data format. + + * src/aiff.c + On write, set blocksize in SSND chunk to zero like everybody else. + +1999-02-16 Erik de Castro Lopo + + * src/pcm.c: + Fixed bug in let2s_array (cptr was not being initialised). + + * src/sndfile.c: + Fixed bug in sf_read_raw and sf_write_raw. sf_seek should + now work when using these functions. + +1999-02-15 Erik de Castro Lopo + + * tests/write_read_test.c: + Force test_buffer array to be double aligned. Sparc Solaris + requires this. + +1999-02-14 Erik de Castro Lopo + + * src/pcm.c: + Fixed a bug which was causing errors in the reading + and writing of 24 bit PCM files. + + * doc/api.html + Finished of preliminary documentaion. + +1999-02-13 Erik de Castro Lopo + + * src/aiff.c: + Changed reading of 'COMM' chunk to avoid reading an int + which overlaps an int (4 byte) boundary. diff --git a/libsndfile.64/NEWS b/libsndfile.64/NEWS new file mode 100644 index 00000000..d8f549f4 --- /dev/null +++ b/libsndfile.64/NEWS @@ -0,0 +1,199 @@ +Version 1.0.28 (2017-04-02) + * Fix buffer overruns in FLAC and ID3 handling code. + * Move to variable length header storage. + * Fix detection of Large File Support for 32 bit systems. + * Remove large stack allocations in ALAC handling code. + * Remove all use of Variable Length Arrays. + * Minor bug fixes and improvements. + +Version 1.0.27 (2016-06-19) + * Fix an SF_INFO seekable flag regression introduced in 1.0.26. + * Fix potential infinite loops on malformed input files. + * Add string metadata read/write for CAF and RF64. + * Add handling of CUE chunks. + * Fix endian-ness issues in PAF files. + * Minor bug fixes and improvements. + +Version 1.0.26 (2015-11-22) + * Fix for CVE-2014-9496, SD2 buffer read overflow. + * Fix for CVE-2014-9756, file_io.c divide by zero. + * Fix for CVE-2015-7805, AIFF heap write overflow. + * Add support for ALAC encoder in a CAF container. + * Add support for Cart chunks in WAV files. + * Minor bug fixes and improvements. + +Version 1.0.25 (2011-07-13) + * Fix for Secunia Advisory SA45125, heap overflow in PAF file handler. + * Accept broken WAV files with blockalign == 0. + * Minor bug fixes and improvements. + +Version 1.0.24 (2011-03-23) + * WAV files now have an 18 byte u-law and A-law fmt chunk. + * Document virtual I/O functionality. + * Two new methods rawHandle() and takeOwnership() in sndfile.hh. + * AIFF fix for non-zero offset value in SSND chunk. + * Minor bug fixes and improvements. + +Version 1.0.23 (2010-10-10) + * Add version metadata to Windows DLL. + * Add a missing 'inline' to sndfile.hh. + * Update docs. + * Minor bug fixes and improvements. + +Version 1.0.22 (2010-10-04) + * Couple of fixes for SDS file writer. + * Fixes arising from static analysis. + * Handle FLAC files with ID3 meta data at start of file. + * Handle FLAC files which report zero length. + * Other minor bug fixes and improvements. + +Version 1.0.21 (2009-12-13) + * Add a couple of new binary programs to programs/ dir. + * Remove sndfile-jackplay (now in sndfile-tools package). + * Add windows only function sf_wchar_open(). + * Bunch of minor bug fixes. + +Version 1.0.20 (2009-05-14) + * Fix potential heap overflow in VOC file parser (Tobias Klein, http://www.trapkit.de/). + +Version 1.0.19 (2009-03-02) + * Fix for CVE-2009-0186 (Alin Rad Pop, Secunia Research). + * Huge number of minor bug fixes as a result of static analysis. + +Version 1.0.18 (2009-02-07) + * Add Ogg/Vorbis support (thanks to John ffitch). + * Remove captive FLAC library. + * Many new features and bug fixes. + * Generate Win32 and Win64 pre-compiled binaries. + +Version 1.0.17 (2006-08-31) + * Add sndfile.hh C++ wrapper. + * Update Win32 MinGW build instructions. + * Minor bug fixes and cleanups. + +Version 1.0.16 (2006-04-30) + * Add support for Broadcast (BEXT) chunks in WAV files. + * Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS. + * Add support for RIFX (big endian WAV variant). + * Fix configure script bugs. + * Fix bug in INST and MARK chunk writing for AIFF files. + +Version 1.0.15 (2006-03-16) + * Fix some ia64 issues. + * Fix precompiled DLL. + * Minor bug fixes. + +Version 1.0.14 (2006-02-19) + * Really fix MinGW compile problems. + * Minor bug fixes. + +Version 1.0.13 (2006-01-21) + * Fix for MinGW compiler problems. + * Allow readin/write of instrument chunks from WAV and AIFF files. + * Compile problem fix for Solaris compiler. + * Minor cleanups and bug fixes. + +Version 1.0.12 (2005-09-30) + * Add support for FLAC and Apple's Core Audio Format (CAF). + * Add virtual I/O interface (still needs docs). + * Cygwin and other Win32 fixes. + * Minor bug fixes and cleanups. + +Version 1.0.11 (2004-11-15) + * Add support for SD2 files. + * Add read support for loop info in WAV and AIFF files. + * Add more tests. + * Improve type safety. + * Minor optimisations and bug fixes. + +Version 1.0.10 (2004-06-15) + * Fix AIFF read/write mode bugs. + * Add support for compiling Win32 DLLS using MinGW. + * Fix problems resulting in failed compiles with gcc-2.95. + * Improve test suite. + * Minor bug fixes. + +Version 1.0.9 (2004-03-30) + * Add handling of AVR (Audio Visual Research) files. + * Improve handling of WAVEFORMATEXTENSIBLE WAV files. + * Fix for using pipes on Win32. + +Version 1.0.8 (2004-03-14) + * Correct peak chunk handing for files with > 16 tracks. + * Fix for WAV files with huge number of CUE chunks. + +Version 1.0.7 (2004-02-25) + * Fix clip mode detection on ia64, MIPS and other CPUs. + * Fix two MacOSX build problems. + +Version 1.0.6 (2004-02-08) + * Added support for native Win32 file access API (Ross Bencina). + * New mode to add clippling then a converting from float/double to integer + would otherwise wrap around. + * Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others. + * Many minor bug fixes. + * Other random fixes for Win32. + +Version 1.0.5 (2003-05-03) + * Added support for HTK files. + * Added new function sf_open_fd() to allow for secure opening of temporary + files as well as reading/writing sound files embedded within larger + container files. + * Added string support for AIFF files. + * Minor bug fixes and code cleanups. + +Version 1.0.4 (2003-02-02) + * Added suport of PVF and XI files. + * Added functionality for setting and retreiving strings from sound files. + * Minor code cleanups and bug fixes. + +Version 1.0.3 (2002-12-09) + * Minor bug fixes. + +Version 1.0.2 (2002-11-24) + * Added support for VOX ADPCM. + * Improved error reporting. + * Added version scripting on Linux and Solaris. + * Minor bug fixes. + +Version 1.0.1 (2002-09-14) + * Added MAT and MAT5 file formats. + * Minor bug fixes. + +Version 1.0.0 (2002-08-16) + * Final release for 1.0.0. + +Version 1.0.0rc6 (2002-08-14) + * Release candidate 6 for the 1.0.0 series. + * MacOS9 fixes. + +Version 1.0.0rc5 (2002-08-10) + * Release candidate 5 for the 1.0.0 series. + * Changed the definition of sf_count_t which was causing problems when + libsndfile was compiled with other libraries (ie WxWindows). + * Minor bug fixes. + * Documentation cleanup. + +Version 1.0.0rc4 (2002-08-03) + * Release candidate 4 for the 1.0.0 series. + * Minor bug fixes. + * Fix broken Win32 "make check". + +Version 1.0.0rc3 (2002-08-02) + * Release candidate 3 for the 1.0.0 series. + * Fix bug where libsndfile was reading beyond the end of the data chunk. + * Added on-the-fly header updates on write. + * Fix a couple of documentation issues. + +Version 1.0.0rc2 (2002-06-24) + * Release candidate 2 for the 1.0.0 series. + * Fix compile problem for Win32. + +Version 1.0.0rc1 (2002-06-24) + * Release candidate 1 for the 1.0.0 series. + +Version 0.0.28 (2002-04-27) + * Last offical release of 0.0.X series of the library. + +Version 0.0.8 (1999-02-16) + * First offical release. diff --git a/libsndfile.64/dist/libsndfile-1.dll b/libsndfile.64/dist/libsndfile-1.dll new file mode 100644 index 0000000000000000000000000000000000000000..9817e8b0b9cb55f715f92f17f59c7372a38cc5a2 GIT binary patch literal 1748992 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%0A)9iO-kt4qouO(_l-%kaLW}zRGlvJQ}h(`Eg;9 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 #Y1d2H5}z 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

mKnrgF%#*@aM?W}E=uXRZ2>_-USa&xNT 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 gMOXZ +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** sndfile.h -- system-wide definitions +** +** API documentation is in the doc/ directory of the source code tarball +** and at http://www.mega-nerd.com/libsndfile/api.html. +*/ + +#ifndef SNDFILE_H +#define SNDFILE_H + +/* This is the version 1.0.X header file. */ +#define SNDFILE_1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* The following file types can be read and written. +** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise +** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and +** SF_FORMAT_SUBMASK can be used to separate the major and minor file +** types. +*/ + +enum +{ /* Major formats. */ + SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ + SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ + SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ + SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ + SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ + SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ + SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ + SF_FORMAT_VOC = 0x080000, /* VOC files. */ + SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ + SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ + SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ + SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ + SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ + SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ + SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ + SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ + SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ + SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ + SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ + SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ + SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ + SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ + SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ + SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ + SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ + + /* Subtypes from here on. */ + + SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ + SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ + SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ + SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ + + SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ + + SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ + SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ + + SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ + SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ + SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ + SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ + + SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ + SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ + + SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ + SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ + SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ + + SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ + + SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ + SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ + + SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ + + SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */ + SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */ + SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */ + SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */ + + /* Endian-ness options. */ + + SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ + SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ + SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ + SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ + + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 +} ; + +/* +** The following are the valid command numbers for the sf_command() +** interface. The use of these commands is documented in the file +** command.html in the doc directory of the source code distribution. +*/ + +enum +{ SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, + SFC_GET_CURRENT_SF_INFO = 0x1002, + + + SFC_GET_NORM_DOUBLE = 0x1010, + SFC_GET_NORM_FLOAT = 0x1011, + SFC_SET_NORM_DOUBLE = 0x1012, + SFC_SET_NORM_FLOAT = 0x1013, + SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, + SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, + + SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, + SFC_GET_SIMPLE_FORMAT = 0x1021, + + SFC_GET_FORMAT_INFO = 0x1028, + + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, + + SFC_CALC_SIGNAL_MAX = 0x1040, + SFC_CALC_NORM_SIGNAL_MAX = 0x1041, + SFC_CALC_MAX_ALL_CHANNELS = 0x1042, + SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, + SFC_GET_SIGNAL_MAX = 0x1044, + SFC_GET_MAX_ALL_CHANNELS = 0x1045, + + SFC_SET_ADD_PEAK_CHUNK = 0x1050, + SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, + + SFC_UPDATE_HEADER_NOW = 0x1060, + SFC_SET_UPDATE_HEADER_AUTO = 0x1061, + + SFC_FILE_TRUNCATE = 0x1080, + + SFC_SET_RAW_START_OFFSET = 0x1090, + + SFC_SET_DITHER_ON_WRITE = 0x10A0, + SFC_SET_DITHER_ON_READ = 0x10A1, + + SFC_GET_DITHER_INFO_COUNT = 0x10A2, + SFC_GET_DITHER_INFO = 0x10A3, + + SFC_GET_EMBED_FILE_INFO = 0x10B0, + + SFC_SET_CLIPPING = 0x10C0, + SFC_GET_CLIPPING = 0x10C1, + + SFC_GET_CUE_COUNT = 0x10CD, + SFC_GET_CUE = 0x10CE, + SFC_SET_CUE = 0x10CF, + + SFC_GET_INSTRUMENT = 0x10D0, + SFC_SET_INSTRUMENT = 0x10D1, + + SFC_GET_LOOP_INFO = 0x10E0, + + SFC_GET_BROADCAST_INFO = 0x10F0, + SFC_SET_BROADCAST_INFO = 0x10F1, + + SFC_GET_CHANNEL_MAP_INFO = 0x1100, + SFC_SET_CHANNEL_MAP_INFO = 0x1101, + + SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, + + /* Support for Wavex Ambisonics Format */ + SFC_WAVEX_SET_AMBISONIC = 0x1200, + SFC_WAVEX_GET_AMBISONIC = 0x1201, + + /* + ** RF64 files can be set so that on-close, writable files that have less + ** than 4GB of data in them are converted to RIFF/WAV, as per EBU + ** recommendations. + */ + SFC_RF64_AUTO_DOWNGRADE = 0x1210, + + SFC_SET_VBR_ENCODING_QUALITY = 0x1300, + SFC_SET_COMPRESSION_LEVEL = 0x1301, + + /* Cart Chunk support */ + SFC_SET_CART_INFO = 0x1400, + SFC_GET_CART_INFO = 0x1401, + + /* Following commands for testing only. */ + SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + + /* + ** SFC_SET_ADD_* values are deprecated and will disappear at some + ** time in the future. They are guaranteed to be here up to and + ** including version 1.0.8 to avoid breakage of existing software. + ** They currently do nothing and will continue to do nothing. + */ + SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, + SFC_SET_ADD_DITHER_ON_READ = 0x1071 +} ; + + +/* +** String types that can be set and read from files. Not all file types +** support this and even the file types which support one, may not support +** all string types. +*/ + +enum +{ SF_STR_TITLE = 0x01, + SF_STR_COPYRIGHT = 0x02, + SF_STR_SOFTWARE = 0x03, + SF_STR_ARTIST = 0x04, + SF_STR_COMMENT = 0x05, + SF_STR_DATE = 0x06, + SF_STR_ALBUM = 0x07, + SF_STR_LICENSE = 0x08, + SF_STR_TRACKNUMBER = 0x09, + SF_STR_GENRE = 0x10 +} ; + +/* +** Use the following as the start and end index when doing metadata +** transcoding. +*/ + +#define SF_STR_FIRST SF_STR_TITLE +#define SF_STR_LAST SF_STR_GENRE + +enum +{ /* True and false */ + SF_FALSE = 0, + SF_TRUE = 1, + + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30, + + SF_AMBISONIC_NONE = 0x40, + SF_AMBISONIC_B_FORMAT = 0x41 +} ; + +/* Public error values. These are guaranteed to remain unchanged for the duration +** of the library major version number. +** There are also a large number of private error numbers which are internal to +** the library which can change at any time. +*/ + +enum +{ SF_ERR_NO_ERROR = 0, + SF_ERR_UNRECOGNISED_FORMAT = 1, + SF_ERR_SYSTEM = 2, + SF_ERR_MALFORMED_FILE = 3, + SF_ERR_UNSUPPORTED_ENCODING = 4 +} ; + + +/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP). +*/ + +enum +{ SF_CHANNEL_MAP_INVALID = 0, + SF_CHANNEL_MAP_MONO = 1, + SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */ + SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */ + SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */ + SF_CHANNEL_MAP_FRONT_LEFT, + SF_CHANNEL_MAP_FRONT_RIGHT, + SF_CHANNEL_MAP_FRONT_CENTER, + SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */ + SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */ + SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */ + SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */ + SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */ + SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */ + SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */ + SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */ + SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */ + SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */ + SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */ + SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */ + SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */ + SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */ + SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */ + + SF_CHANNEL_MAP_AMBISONIC_B_W, + SF_CHANNEL_MAP_AMBISONIC_B_X, + SF_CHANNEL_MAP_AMBISONIC_B_Y, + SF_CHANNEL_MAP_AMBISONIC_B_Z, + + SF_CHANNEL_MAP_MAX +} ; + + +/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ + +typedef struct SNDFILE_tag SNDFILE ; + +/* The following typedef is system specific and is defined when libsndfile is +** compiled. sf_count_t will be a 64 bit value when the underlying OS allows +** 64 bit file offsets. +** On windows, we need to allow the same header file to be compiler by both GCC +** and the Microsoft compiler. +*/ + +#if (defined (_MSCVER) || defined (_MSC_VER) && (_MSC_VER < 1310)) +typedef __int64 sf_count_t ; +#define SF_COUNT_MAX 0x7fffffffffffffffi64 +#else +typedef __int64 sf_count_t ; +#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL +#endif + + +/* A pointer to a SF_INFO structure is passed to sf_open () and filled in. +** On write, the SF_INFO structure is filled in by the user and passed into +** sf_open (). +*/ + +struct SF_INFO +{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; +} ; + +typedef struct SF_INFO SF_INFO ; + +/* The SF_FORMAT_INFO struct is used to retrieve information about the sound +** file formats libsndfile supports using the sf_command () interface. +** +** Using this interface will allow applications to support new file formats +** and encoding types when libsndfile is upgraded, without requiring +** re-compilation of the application. +** +** Please consult the libsndfile documentation (particularly the information +** on the sf_command () interface) for examples of its use. +*/ + +typedef struct +{ int format ; + const char *name ; + const char *extension ; +} SF_FORMAT_INFO ; + +/* +** Enums and typedefs for adding dither on read and write. +** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE +** and SFC_SET_DITHER_ON_READ. +*/ + +enum +{ SFD_DEFAULT_LEVEL = 0, + SFD_CUSTOM_LEVEL = 0x40000000, + + SFD_NO_DITHER = 500, + SFD_WHITE = 501, + SFD_TRIANGULAR_PDF = 502 +} ; + +typedef struct +{ int type ; + double level ; + const char *name ; +} SF_DITHER_INFO ; + +/* Struct used to retrieve information about a file embedded within a +** larger file. See SFC_GET_EMBED_FILE_INFO. +*/ + +typedef struct +{ sf_count_t offset ; + sf_count_t length ; +} SF_EMBED_FILE_INFO ; + +/* +** Struct used to retrieve cue marker information from a file +*/ + +typedef struct +{ int32_t indx ; + uint32_t position ; + int32_t fcc_chunk ; + int32_t chunk_start ; + int32_t block_start ; + uint32_t sample_offset ; + char name [256] ; +} SF_CUE_POINT ; + +#define SF_CUES_VAR(count) \ + struct \ + { uint32_t cue_count ; \ + SF_CUE_POINT cue_points [count] ; \ + } + +typedef SF_CUES_VAR (100) SF_CUES ; + +/* +** Structs used to retrieve music sample information from a file. +*/ + +enum +{ /* + ** The loop mode field in SF_INSTRUMENT will be one of the following. + */ + SF_LOOP_NONE = 800, + SF_LOOP_FORWARD, + SF_LOOP_BACKWARD, + SF_LOOP_ALTERNATING +} ; + +typedef struct +{ int gain ; + char basenote, detune ; + char velocity_lo, velocity_hi ; + char key_lo, key_hi ; + int loop_count ; + + struct + { int mode ; + uint32_t start ; + uint32_t end ; + uint32_t count ; + } loops [16] ; /* make variable in a sensible way */ +} SF_INSTRUMENT ; + + + +/* Struct used to retrieve loop information from a file.*/ +typedef struct +{ + short time_sig_num ; /* any positive integer > 0 */ + short time_sig_den ; /* any positive power of 2 > 0 */ + int loop_mode ; /* see SF_LOOP enum */ + + int num_beats ; /* this is NOT the amount of quarter notes !!!*/ + /* a full bar of 4/4 is 4 beats */ + /* a full bar of 7/8 is 7 beats */ + + float bpm ; /* suggestion, as it can be calculated using other fields:*/ + /* file's length, file's sampleRate and our time_sig_den*/ + /* -> bpms are always the amount of _quarter notes_ per minute */ + + int root_key ; /* MIDI note, or -1 for None */ + int future [6] ; +} SF_LOOP_INFO ; + + +/* Struct used to retrieve broadcast (EBU) information from a file. +** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. +*/ +#define SF_BROADCAST_INFO_VAR(coding_hist_size) \ + struct \ + { char description [256] ; \ + char originator [32] ; \ + char originator_reference [32] ; \ + char origination_date [10] ; \ + char origination_time [8] ; \ + uint32_t time_reference_low ; \ + uint32_t time_reference_high ; \ + short version ; \ + char umid [64] ; \ + char reserved [190] ; \ + uint32_t coding_history_size ; \ + char coding_history [coding_hist_size] ; \ + } + +/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */ +typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ; + +struct SF_CART_TIMER +{ char usage [4] ; + int32_t value ; +} ; + +typedef struct SF_CART_TIMER SF_CART_TIMER ; + +#define SF_CART_INFO_VAR(p_tag_text_size) \ + struct \ + { char version [4] ; \ + char title [64] ; \ + char artist [64] ; \ + char cut_id [64] ; \ + char client_id [64] ; \ + char category [64] ; \ + char classification [64] ; \ + char out_cue [64] ; \ + char start_date [10] ; \ + char start_time [8] ; \ + char end_date [10] ; \ + char end_time [8] ; \ + char producer_app_id [64] ; \ + char producer_app_version [64] ; \ + char user_def [64] ; \ + int32_t level_reference ; \ + SF_CART_TIMER post_timers [8] ; \ + char reserved [276] ; \ + char url [1024] ; \ + uint32_t tag_text_size ; \ + char tag_text [p_tag_text_size] ; \ + } + +typedef SF_CART_INFO_VAR (256) SF_CART_INFO ; + +/* Virtual I/O functionality. */ + +typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; +typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; +typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_tell) (void *user_data) ; + +struct SF_VIRTUAL_IO +{ sf_vio_get_filelen get_filelen ; + sf_vio_seek seek ; + sf_vio_read read ; + sf_vio_write write ; + sf_vio_tell tell ; +} ; + +typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; + + +/* Open the specified file for read, write or both. On error, this will +** return a NULL pointer. To find the error number, pass a NULL SNDFILE +** to sf_strerror (). +** All calls to sf_open() should be matched with a call to sf_close(). +*/ + +SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; + + +/* Use the existing file descriptor to create a SNDFILE object. If close_desc +** is TRUE, the file descriptor will be closed when sf_close() is called. If +** it is FALSE, the descriptor will not be closed. +** When passed a descriptor like this, the library will assume that the start +** of file header is at the current file offset. This allows sound files within +** larger container files to be read and/or written. +** On error, this will return a NULL pointer. To find the error number, pass a +** NULL SNDFILE to sf_strerror (). +** All calls to sf_open_fd() should be matched with a call to sf_close(). + +*/ + +SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; + +SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; + + +/* sf_error () returns a error number which can be translated to a text +** string using sf_error_number(). +*/ + +int sf_error (SNDFILE *sndfile) ; + + +/* sf_strerror () returns to the caller a pointer to the current error message for +** the given SNDFILE. +*/ + +const char* sf_strerror (SNDFILE *sndfile) ; + + +/* sf_error_number () allows the retrieval of the error string for each internal +** error number. +** +*/ + +const char* sf_error_number (int errnum) ; + + +/* The following two error functions are deprecated but they will remain in the +** library for the foreseeable future. The function sf_strerror() should be used +** in their place. +*/ + +int sf_perror (SNDFILE *sndfile) ; +int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; + + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; + + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_format_check (const SF_INFO *info) ; + + +/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses +** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as +** stdio.h function fseek (). +** An offset of zero with whence set to SEEK_SET will position the +** read / write pointer to the first data sample. +** On success sf_seek returns the current position in (multi-channel) +** samples from the start of the file. +** Please see the libsndfile documentation for moving the read pointer +** separately from the write pointer on files open in mode SFM_RDWR. +** On error all of these functions return -1. +*/ + +enum +{ SF_SEEK_SET = SEEK_SET, + SF_SEEK_CUR = SEEK_CUR, + SF_SEEK_END = SEEK_END +} ; + +sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; + + +/* Functions for retrieving and setting string data within sound files. +** Not all file types support this features; AIFF and WAV do. For both +** functions, the str_type parameter must be one of the SF_STR_* values +** defined above. +** On error, sf_set_string() returns non-zero while sf_get_string() +** returns NULL. +*/ + +int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; + +const char* sf_get_string (SNDFILE *sndfile, int str_type) ; + + +/* Return the library version string. */ + +const char * sf_version_string (void) ; + +/* Return the current byterate at this point in the file. The byte rate in this +** case is the number of bytes per second of audio data. For instance, for a +** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate +** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec. +** For some file formats the returned value will be accurate and exact, for some +** it will be a close approximation, for some it will be the average bitrate for +** the whole file and for some it will be a time varying value that was accurate +** when the file was most recently read or written. +** To get the bitrate, multiple this value by 8. +** Returns -1 for unknown. +*/ +int sf_current_byterate (SNDFILE *sndfile) ; + +/* Functions for reading/writing the waveform data of a sound file. +*/ + +sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; + + +/* Functions for reading and writing the data chunk in terms of frames. +** The number of items actually read/written = frames * number of channels. +** sf_xxxx_raw read/writes the raw data bytes from/to the file +** sf_xxxx_short passes data in the native short format +** sf_xxxx_int passes data in the native int format +** sf_xxxx_float passes data in the native float format +** sf_xxxx_double passes data in the native double format +** All of these read/write function return number of frames read/written. +*/ + +sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; +sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; + + +/* Functions for reading and writing the data chunk in terms of items. +** Otherwise similar to above. +** All of these read/write function return number of items read/written. +*/ + +sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; + +sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; + +sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; + +sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; + + +/* Close the SNDFILE and clean up all memory allocations associated with this +** file. +** Returns 0 on success, or an error number. +*/ + +int sf_close (SNDFILE *sndfile) ; + + +/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file +** to force the writing of data to disk. If the file is opened SFM_READ +** no action is taken. +*/ + +void sf_write_sync (SNDFILE *sndfile) ; + + + +/* The function sf_wchar_open() is Windows Only! +** Open a file passing in a Windows Unicode filename. Otherwise, this is +** the same as sf_open(). +** +** In order for this to work, you need to do the following: +** +** #include +** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 +** #including +*/ + +#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES) +SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; +#endif + + + + +/* Getting and setting of chunks from within a sound file. +** +** These functions allow the getting and setting of chunks within a sound file +** (for those formats which allow it). +** +** These functions fail safely. Specifically, they will not allow you to overwrite +** existing chunks or add extra versions of format specific reserved chunks but +** should allow you to retrieve any and all chunks (may not be implemented for +** all chunks or all file formats). +*/ + +struct SF_CHUNK_INFO +{ char id [64] ; /* The chunk identifier. */ + unsigned id_size ; /* The size of the chunk identifier. */ + unsigned datalen ; /* The size of that data. */ + void *data ; /* Pointer to the data. */ +} ; + +typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ; + +/* Set the specified chunk info (must be done before any audio data is written +** to the file). This will fail for format specific reserved chunks. +** The chunk_info->data pointer must be valid until the file is closed. +** Returns SF_ERR_NO_ERROR on success or non-zero on failure. +*/ +int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; + +/* +** An opaque structure to an iterator over the all chunks of a given id +*/ +typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ; + +/* Get an iterator for all chunks matching chunk_info. +** The iterator will point to the first chunk matching chunk_info. +** Chunks are matching, if (chunk_info->id) matches the first +** (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle. +** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle +** is returned. +** The values of chunk_info->datalen and chunk_info->data are ignored. +** If no matching chunks are found in the sndfile, NULL is returned. +** The returned iterator will stay valid until one of the following occurs: +** a) The sndfile is closed. +** b) A new chunk is added using sf_set_chunk(). +** c) Another chunk iterator function is called on the same SNDFILE* handle +** that causes the iterator to be modified. +** The memory for the iterator belongs to the SNDFILE* handle and is freed when +** sf_close() is called. +*/ +SF_CHUNK_ITERATOR * +sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ; + +/* Iterate through chunks by incrementing the iterator. +** Increments the iterator and returns a handle to the new one. +** After this call, iterator will no longer be valid, and you must use the +** newly returned handle from now on. +** The returned handle can be used to access the next chunk matching +** the criteria as defined in sf_get_chunk_iterator(). +** If iterator points to the last chunk, this will free all resources +** associated with iterator and return NULL. +** The returned iterator will stay valid until sf_get_chunk_iterator_next +** is called again, the sndfile is closed or a new chunk us added. +*/ +SF_CHUNK_ITERATOR * +sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ; + + +/* Get the size of the specified chunk. +** If the specified chunk exists, the size will be returned in the +** datalen field of the SF_CHUNK_INFO struct. +** Additionally, the id of the chunk will be copied to the id +** field of the SF_CHUNK_INFO struct and it's id_size field will +** be updated accordingly. +** If the chunk doesn't exist chunk_info->datalen will be zero, and the +** id and id_size fields will be undefined. +** The function will return SF_ERR_NO_ERROR on success or non-zero on +** failure. +*/ +int +sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; + +/* Get the specified chunk data. +** If the specified chunk exists, up to chunk_info->datalen bytes of +** the chunk data will be copied into the chunk_info->data buffer +** (allocated by the caller) and the chunk_info->datalen field +** updated to reflect the size of the data. The id and id_size +** field will be updated according to the retrieved chunk +** If the chunk doesn't exist chunk_info->datalen will be zero, and the +** id and id_size fields will be undefined. +** The function will return SF_ERR_NO_ERROR on success or non-zero on +** failure. +*/ +int +sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SNDFILE_H */ + diff --git a/libsndfile.64/include/sndfile.hh b/libsndfile.64/include/sndfile.hh new file mode 100644 index 00000000..0e1c1c20 --- /dev/null +++ b/libsndfile.64/include/sndfile.hh @@ -0,0 +1,446 @@ +/* +** Copyright (C) 2005-2012 Erik de Castro Lopo +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the author nor the names of any contributors may be used +** to endorse or promote products derived from this software without +** specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +** The above modified BSD style license (GPL and LGPL compatible) applies to +** this file. It does not apply to libsndfile itself which is released under +** the GNU LGPL or the libsndfile test suite which is released under the GNU +** GPL. +** This means that this header file can be used under this modified BSD style +** license, but the LGPL still holds for the libsndfile library itself. +*/ + +/* +** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API. +** +** All the methods are inlines and all functionality is contained in this +** file. There is no separate implementation file. +** +** API documentation is in the doc/ directory of the source code tarball +** and at http://www.mega-nerd.com/libsndfile/api.html. +*/ + +#ifndef SNDFILE_HH +#define SNDFILE_HH + +#include + +#include +#include // for std::nothrow + +class SndfileHandle +{ private : + struct SNDFILE_ref + { SNDFILE_ref (void) ; + ~SNDFILE_ref (void) ; + + SNDFILE *sf ; + SF_INFO sfinfo ; + int ref ; + } ; + + SNDFILE_ref *p ; + + public : + /* Default constructor */ + SndfileHandle (void) : p (NULL) {} ; + SndfileHandle (const char *path, int mode = SFM_READ, + int format = 0, int channels = 0, int samplerate = 0) ; + SndfileHandle (std::string const & path, int mode = SFM_READ, + int format = 0, int channels = 0, int samplerate = 0) ; + SndfileHandle (int fd, bool close_desc, int mode = SFM_READ, + int format = 0, int channels = 0, int samplerate = 0) ; + SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ, + int format = 0, int channels = 0, int samplerate = 0) ; + +#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES + SndfileHandle (LPCWSTR wpath, int mode = SFM_READ, + int format = 0, int channels = 0, int samplerate = 0) ; +#endif + + ~SndfileHandle (void) ; + + SndfileHandle (const SndfileHandle &orig) ; + SndfileHandle & operator = (const SndfileHandle &rhs) ; + + /* Mainly for debugging/testing. */ + int refCount (void) const { return (p == NULL) ? 0 : p->ref ; } + + operator bool () const { return (p != NULL) ; } + + bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; } + + sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; } + int format (void) const { return p ? p->sfinfo.format : 0 ; } + int channels (void) const { return p ? p->sfinfo.channels : 0 ; } + int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; } + + int error (void) const ; + const char * strError (void) const ; + + int command (int cmd, void *data, int datasize) ; + + sf_count_t seek (sf_count_t frames, int whence) ; + + void writeSync (void) ; + + int setString (int str_type, const char* str) ; + + const char* getString (int str_type) const ; + + static int formatCheck (int format, int channels, int samplerate) ; + + sf_count_t read (short *ptr, sf_count_t items) ; + sf_count_t read (int *ptr, sf_count_t items) ; + sf_count_t read (float *ptr, sf_count_t items) ; + sf_count_t read (double *ptr, sf_count_t items) ; + + sf_count_t write (const short *ptr, sf_count_t items) ; + sf_count_t write (const int *ptr, sf_count_t items) ; + sf_count_t write (const float *ptr, sf_count_t items) ; + sf_count_t write (const double *ptr, sf_count_t items) ; + + sf_count_t readf (short *ptr, sf_count_t frames) ; + sf_count_t readf (int *ptr, sf_count_t frames) ; + sf_count_t readf (float *ptr, sf_count_t frames) ; + sf_count_t readf (double *ptr, sf_count_t frames) ; + + sf_count_t writef (const short *ptr, sf_count_t frames) ; + sf_count_t writef (const int *ptr, sf_count_t frames) ; + sf_count_t writef (const float *ptr, sf_count_t frames) ; + sf_count_t writef (const double *ptr, sf_count_t frames) ; + + sf_count_t readRaw (void *ptr, sf_count_t bytes) ; + sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ; + + /**< Raw access to the handle. SndfileHandle keeps ownership. */ + SNDFILE * rawHandle (void) ; + + /**< Take ownership of handle, if reference count is 1. */ + SNDFILE * takeOwnership (void) ; +} ; + +/*============================================================================== +** Nothing but implementation below. +*/ + +inline +SndfileHandle::SNDFILE_ref::SNDFILE_ref (void) +: sf (NULL), sfinfo (), ref (1) +{} + +inline +SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void) +{ if (sf != NULL) sf_close (sf) ; } + +inline +SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate) +: p (NULL) +{ + p = new (std::nothrow) SNDFILE_ref () ; + + if (p != NULL) + { p->ref = 1 ; + + p->sfinfo.frames = 0 ; + p->sfinfo.channels = chans ; + p->sfinfo.format = fmt ; + p->sfinfo.samplerate = srate ; + p->sfinfo.sections = 0 ; + p->sfinfo.seekable = 0 ; + + p->sf = sf_open (path, mode, &p->sfinfo) ; + } ; + + return ; +} /* SndfileHandle const char * constructor */ + +inline +SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate) +: p (NULL) +{ + p = new (std::nothrow) SNDFILE_ref () ; + + if (p != NULL) + { p->ref = 1 ; + + p->sfinfo.frames = 0 ; + p->sfinfo.channels = chans ; + p->sfinfo.format = fmt ; + p->sfinfo.samplerate = srate ; + p->sfinfo.sections = 0 ; + p->sfinfo.seekable = 0 ; + + p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ; + } ; + + return ; +} /* SndfileHandle std::string constructor */ + +inline +SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate) +: p (NULL) +{ + if (fd < 0) + return ; + + p = new (std::nothrow) SNDFILE_ref () ; + + if (p != NULL) + { p->ref = 1 ; + + p->sfinfo.frames = 0 ; + p->sfinfo.channels = chans ; + p->sfinfo.format = fmt ; + p->sfinfo.samplerate = srate ; + p->sfinfo.sections = 0 ; + p->sfinfo.seekable = 0 ; + + p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ; + } ; + + return ; +} /* SndfileHandle fd constructor */ + +inline +SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate) +: p (NULL) +{ + p = new (std::nothrow) SNDFILE_ref () ; + + if (p != NULL) + { p->ref = 1 ; + + p->sfinfo.frames = 0 ; + p->sfinfo.channels = chans ; + p->sfinfo.format = fmt ; + p->sfinfo.samplerate = srate ; + p->sfinfo.sections = 0 ; + p->sfinfo.seekable = 0 ; + + p->sf = sf_open_virtual (&sfvirtual, mode, &p->sfinfo, user_data) ; + } ; + + return ; +} /* SndfileHandle std::string constructor */ + +inline +SndfileHandle::~SndfileHandle (void) +{ if (p != NULL && --p->ref == 0) + delete p ; +} /* SndfileHandle destructor */ + + +inline +SndfileHandle::SndfileHandle (const SndfileHandle &orig) +: p (orig.p) +{ if (p != NULL) + ++p->ref ; +} /* SndfileHandle copy constructor */ + +inline SndfileHandle & +SndfileHandle::operator = (const SndfileHandle &rhs) +{ + if (&rhs == this) + return *this ; + if (p != NULL && --p->ref == 0) + delete p ; + + p = rhs.p ; + if (p != NULL) + ++p->ref ; + + return *this ; +} /* SndfileHandle assignment operator */ + +inline int +SndfileHandle::error (void) const +{ return sf_error (p->sf) ; } + +inline const char * +SndfileHandle::strError (void) const +{ return sf_strerror (p->sf) ; } + +inline int +SndfileHandle::command (int cmd, void *data, int datasize) +{ return sf_command (p->sf, cmd, data, datasize) ; } + +inline sf_count_t +SndfileHandle::seek (sf_count_t frame_count, int whence) +{ return sf_seek (p->sf, frame_count, whence) ; } + +inline void +SndfileHandle::writeSync (void) +{ sf_write_sync (p->sf) ; } + +inline int +SndfileHandle::setString (int str_type, const char* str) +{ return sf_set_string (p->sf, str_type, str) ; } + +inline const char* +SndfileHandle::getString (int str_type) const +{ return sf_get_string (p->sf, str_type) ; } + +inline int +SndfileHandle::formatCheck (int fmt, int chans, int srate) +{ + SF_INFO sfinfo ; + + sfinfo.frames = 0 ; + sfinfo.channels = chans ; + sfinfo.format = fmt ; + sfinfo.samplerate = srate ; + sfinfo.sections = 0 ; + sfinfo.seekable = 0 ; + + return sf_format_check (&sfinfo) ; +} + +/*---------------------------------------------------------------------*/ + +inline sf_count_t +SndfileHandle::read (short *ptr, sf_count_t items) +{ return sf_read_short (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::read (int *ptr, sf_count_t items) +{ return sf_read_int (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::read (float *ptr, sf_count_t items) +{ return sf_read_float (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::read (double *ptr, sf_count_t items) +{ return sf_read_double (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::write (const short *ptr, sf_count_t items) +{ return sf_write_short (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::write (const int *ptr, sf_count_t items) +{ return sf_write_int (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::write (const float *ptr, sf_count_t items) +{ return sf_write_float (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::write (const double *ptr, sf_count_t items) +{ return sf_write_double (p->sf, ptr, items) ; } + +inline sf_count_t +SndfileHandle::readf (short *ptr, sf_count_t frame_count) +{ return sf_readf_short (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::readf (int *ptr, sf_count_t frame_count) +{ return sf_readf_int (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::readf (float *ptr, sf_count_t frame_count) +{ return sf_readf_float (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::readf (double *ptr, sf_count_t frame_count) +{ return sf_readf_double (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::writef (const short *ptr, sf_count_t frame_count) +{ return sf_writef_short (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::writef (const int *ptr, sf_count_t frame_count) +{ return sf_writef_int (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::writef (const float *ptr, sf_count_t frame_count) +{ return sf_writef_float (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::writef (const double *ptr, sf_count_t frame_count) +{ return sf_writef_double (p->sf, ptr, frame_count) ; } + +inline sf_count_t +SndfileHandle::readRaw (void *ptr, sf_count_t bytes) +{ return sf_read_raw (p->sf, ptr, bytes) ; } + +inline sf_count_t +SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes) +{ return sf_write_raw (p->sf, ptr, bytes) ; } + +inline SNDFILE * +SndfileHandle::rawHandle (void) +{ return (p ? p->sf : NULL) ; } + +inline SNDFILE * +SndfileHandle::takeOwnership (void) +{ + if (p == NULL || (p->ref != 1)) + return NULL ; + + SNDFILE * sf = p->sf ; + p->sf = NULL ; + delete p ; + p = NULL ; + return sf ; +} + +#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES + +inline +SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate) +: p (NULL) +{ + p = new (std::nothrow) SNDFILE_ref () ; + + if (p != NULL) + { p->ref = 1 ; + + p->sfinfo.frames = 0 ; + p->sfinfo.channels = chans ; + p->sfinfo.format = fmt ; + p->sfinfo.samplerate = srate ; + p->sfinfo.sections = 0 ; + p->sfinfo.seekable = 0 ; + + p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ; + } ; + + return ; +} /* SndfileHandle const wchar_t * constructor */ + +#endif + +#endif /* SNDFILE_HH */ + diff --git a/libsndfile.64/lib/libsndfile-1.def b/libsndfile.64/lib/libsndfile-1.def new file mode 100644 index 00000000..4194ff3e --- /dev/null +++ b/libsndfile.64/lib/libsndfile-1.def @@ -0,0 +1,47 @@ +; Auto-generated by create_symbols_file.py + +LIBRARY libsndfile-1.dll +EXPORTS + +sf_command @1 +sf_open @2 +sf_close @3 +sf_seek @4 +sf_error @7 +sf_perror @8 +sf_error_str @9 +sf_error_number @10 +sf_format_check @11 +sf_read_raw @16 +sf_readf_short @17 +sf_readf_int @18 +sf_readf_float @19 +sf_readf_double @20 +sf_read_short @21 +sf_read_int @22 +sf_read_float @23 +sf_read_double @24 +sf_write_raw @32 +sf_writef_short @33 +sf_writef_int @34 +sf_writef_float @35 +sf_writef_double @36 +sf_write_short @37 +sf_write_int @38 +sf_write_float @39 +sf_write_double @40 +sf_strerror @50 +sf_get_string @60 +sf_set_string @61 +sf_version_string @68 +sf_open_fd @70 +sf_wchar_open @71 +sf_open_virtual @80 +sf_write_sync @90 +sf_set_chunk @100 +sf_get_chunk_size @101 +sf_get_chunk_data @102 +sf_get_chunk_iterator @103 +sf_next_chunk_iterator @104 +sf_current_byterate @110 + diff --git a/libsndfile.64/lib/libsndfile-1.lib b/libsndfile.64/lib/libsndfile-1.lib new file mode 100644 index 0000000000000000000000000000000000000000..56546a20b5b4705901d4dd6a8be724d5fa56ac26 GIT binary patch literal 9760 zcmcgwO>7fa5FY+YYSI!y{t1cmLx7eB66_QZMWIb;5#dK6NC;J09DALZI(D>npm3lP zLYz3!8$uj8^uU2LtvDitP*qV0^;GpxA;gIz7drF)_Pw|34cj=iG})bb^Y(i)nKv`< z^&QN3*||fB-AVH|lG;BqGP-wcY`-brBiNCB=@frGp8$X}02`+PHr)bfeg@EThg0V@ z0HT&rPQCpAM6Fjjbv*$fYCFfN^(D%Y+8%T2z79at^FYu9K9ROQ7c_%Ur0zF@+VF|A z<({B1d?F1ra@uwufYBj*A`Lzjg!qF<16Mfp-vwYaj8CM#hn$iZ0EjwnbLxGI_8=u+ zaO!-G_9FF7a_TyZ_8|?t;?#Q+^^rP;IJF-DV1(;xN9s&)YHdJ2G&s)D78uWGEk;Ff5BJ(Vs1QnlJ*@-qBLo5J9)PM z<*ORIl%30XeD{+}d`@YwDHjV~bum+<)f&9g67IfS%94)8DGjnAJGWR82}Ck#oV>us zol4;f+as1FL^GGEW~2xCTqX(8#EAAXRi38&?<%R9QF4Ef%TR-8P?%WF$u4@HTdF!U zml+68oVF}}5TxlHUT_q2DsA#aIF(y6rcUQ09RW9o^%16!9)Jm?=UV}0klvuI4e8z%fH9=T0f77401hEN9mM%aS5S5rYxgkH!#;ouNr2lO z0B;fJ1-`#V+)0$5MZ8z2dlThDIDViVzlD^*@djK2whFKcR>KFd7Ir}cY=8tb!cO=E zc0dw7g>^6h+u%cJg%;QhA3-y0f+pAqAH#as4t>xI{V)hUuob$Y4Yt4#bU`O{K>G@O zaSi73|5}6nC@@QdS}9rqG~4a@B$xJM8k`3-p=;CP8(&5i+IbRykd4ley-CL zRLb{dvPdXNtrQ-Xn2kcDzQCoHqqxwpf{UmxvZh*walHy9c2hCvK&Be-ppXW^wGP7X zH?>yP-Y=MjRY^7Wh#Zg&rLiw?(2wq5z0i}qucucazfOlmK7O9Xym;zmR;!tQC(HuW zZyp${`VGdBqws6&U2j{h9@YGY^tzasmpu-BMf0=YzsvHA6SU@nI2n`pZbc(Xv^XS= zHH!X9IIqm%tgweO!XVBliv+7T4=TDOjAkKIS0)OMe=Pb$wA(7eOP+o|m#5YKfJSe#1F;W^s1#H0J=0;0qoi zjo&yleK}m9FdoFSHveH00KX&sBltD=9EUxRgdU!Y`41ZhSc`a4kEG*}e6$*$?O2KF z*JPWy9X2PKJ4 zPDt^D^&N8my)#%M7Gp-wXgV$8jG|{Xi=JO`eSF>F(Ua4xp;s+>_R1lOo}VQno)kUw z-Ia-o_xUelvx=UtaqSU%=Z)?k(|pHw-rtB2<-3TTmlkefJC}Bz{u_sJx${y|PCNWh z$%rTEt&ES~$G`o!iu%T9O1c=c8?fD*yFnQaj|pu5V;<*KKCtcM=F!wXKP&4W1VCfQYm_f38KZ@~6AD1Z^<{c*xG(z<1^RM+2V%`}ys&dY061>s zrfT>WuUA;z!hOOH9s!`(5gV0Hk8lg+K|TN$*Q%&|b4tUKXQu#QeCujtaJ>Fv^&9;t zPG`%djYTF6dpg31>oZQvPPbvZVj&-6&@Y=Ru+v; z5%`}|hvem>r6YWa*O>~9pEK)#7g2esCl}VKb8sCHBcgM&j#wjHVn=6<%t@7=&Z5e~ z&~S;37GWJ;oBL=r{(*7vqVhAHbkRC?+fs-BTZA9!gvXHNeNF%_u3b_4;0qtEZuK=4 zkyAzmp1hI@7#BN(sY7%~cQ(P%tV^#tU`Aw?Z#brQtyTxTh|EG=3&sn-aH~~@;(Ik> z?@vmz#lqU+n!C;Y&JoDqq$qk45eGa|Rw=&j!qkA1m?_ z)Y^e`BQdDq)h>LoJsPne=u{>>DsPzUU}MCNCp&$_&;X6^(+CUcB=6(Z2%5yda>oJJ literal 0 HcmV?d00001 diff --git a/libsndfile.64/lib/pkgconfig/sndfile.pc b/libsndfile.64/lib/pkgconfig/sndfile.pc new file mode 100644 index 00000000..428d708a --- /dev/null +++ b/libsndfile.64/lib/pkgconfig/sndfile.pc @@ -0,0 +1,12 @@ +prefix=c:/devel/target/libsndfile +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: sndfile +Description: A library for reading and writing audio files +Requires: +Version: 1.0.28 +Libs: -L${libdir} -lsndfile +Libs.private: Ext/libflac.la Ext/libvorbis.la Ext/libogg.la +Cflags: -I${includedir} diff --git a/mpg123/dist/libmpg123.dll b/mpg123.32/dist/libmpg123.dll similarity index 100% rename from mpg123/dist/libmpg123.dll rename to mpg123.32/dist/libmpg123.dll diff --git a/mpg123/include/mpg123.h b/mpg123.32/include/mpg123.h similarity index 100% rename from mpg123/include/mpg123.h rename to mpg123.32/include/mpg123.h diff --git a/mpg123/lib/libmpg123.lib b/mpg123.32/lib/libmpg123.lib similarity index 100% rename from mpg123/lib/libmpg123.lib rename to mpg123.32/lib/libmpg123.lib diff --git a/mpg123.64/dist/libmpg123.dll b/mpg123.64/dist/libmpg123.dll new file mode 100644 index 0000000000000000000000000000000000000000..545c9de36a0e9ea70fb00cfb0f816c06c4739da2 GIT binary patch literal 345088 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�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%0Ay|xspW) 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

|=0eS(t6E?`yE1!9xrVGC0KG2!mq` zjyHI$!N~?^7@TeJM1v<8Jk4N{!MMRQ4JHlN8eD1cJcAb*Ty5}5gV!4Tp23?8-eT|$ zgFiOdXz)RUj~IN?;L`?omVeLQsPp}GgX6!ik8=#}%%69@Wy~+!cGhaJ&0zLeeO?`- zF=~$U4Hg(|o1m{3nd5BZ-U~l>hQ6N4)7UynW5H;RjRp&*>*H*5|J-T%xNW?~d~-fM zRUhvx{M^%IGmv08!j@Is)%yBsWQIk*M{K-D5^YFiF{`^mc z-&F9TTYnl1)*D=HFm2E)ug*{gnaGqE^_kDJ!ZGOlPCAjTX@~W`R`BvEbq1C z_wuF=Da`x3b7UYVB)&4&@nIU-&vGgAyZCUGcX^qWciN|syz)=F=Z#;pTi%3Y_RXt0 z{gAw4n}+3mbmMV(H@|sO-Z7uA$UCy}`n&`G^?2UB_eb(4?{{kc^j?Qfy7Fd~w_-!L zyu3sA%sc3Y!FlPYXXVX$`a5}tt$ZWzrir)Ze|CYL_xRrq$oqY1S>A852IaqUd9S>> zWAF6Gdpwcxb0%(DNY5bp8767d{fwLELLBlR2wUzG`gMdY_wk1xzUF6aLUO#NNE&nd~eXjw8@K?nq1n@mQNWwr6D z5z+bavbvf?)e;GKNnO0A#*GVZ!*MB$Er}(n3f)`oI$cv@RTArpWOAv5&nXF)x@@@mgH6r&XG}l_cw` zYTa8%=6ea2T#Z)`ix$^W5V3^hmoHse@$LkozR)(R!<@&PNHrJQ!>%mGICRj zSn^JnOQTfy+VXg`IKCuNRVDQ>CwIl*-0>AFhGg8$rV`aeD-uho9?|);rcaOR zQX(WB(1N9jREnGXu5~pZXC#)%P3uz8ns}_bq+AY`#VQh|(K!XvW|$jAW3-j(s3fC! zWo^8Mwi7**$nOw=SyRU>8x^gME#b2jsiCO>wMbshbd;%vsc- zC9#U=q`J~Xa=65A_)NFDMopGUW+uzZYT~ug!L!DVO-NR|Kka`?vaW)lB^M{pDWFFw zuB(j3s%taJSXjN%^aR!Mnw3>0BSx4IwEvlj+Gv~}iPYz0igQSm${dT9)>VsFMH3m6D4sX7tN`Rtt35(suC)l+l!e{DiW1MmL^Vu z%i|TPAvz(uj*o;MtF4V!rfNIMie39J(fyv3BPF+M_x^Iv6!(|;TOO;HW-=jae7dcz zD!!uD)YV~>ZnBEOM0Y%H@0k~!T34PaOlrhei`STNbu`UxG4U8Vn?7;mEa}5^ql}iu zYvUz!LsAEHy_vP7D(Th^@t}t{I;VI^tga?5m1$1F3`WPoSu^I&n?J2^!NU2|Ce4{W zZSIVPGra~b9_f!N7{er4HD3MdEPUNUyBNG~9=`N=70n%f<%XpR8HkAQ%IM&-!GnoF zveHdsb!DO|UOI9~Vp+T@TE4%xcjIoT^DH^q7g(<3^~Q-Z2YR@2eSXfSH<;9=3S zy0gz_IH1x<4pFJ4mBuAt*P*`bI>&Emye6@viW}+FcjS$m^5E&S>gdaAS4NMO%=0cu zX-$aA2*^-JwvwH*C(W6r2G@-kTsOF;qug9~^JqeHIa9F1qI$wGKc1?Ht(?K6Aexdf zIwfT}xGY*aIn?jy`Rchc#JaBdf$HytP=MhS^j!-K9kg$&(kE5K*hl}7e+yFPh zt*{u1qHsQ3B=LY7;3nAnMG1Sh{J z{AGUYx!wRb!cA~1Eb;JuvXGYz_l2YIuHxc_hg0|W_53&Gzxcun$HHum@qTT_=5dPb zmy+N4-W82~^EGB0Y=(~74*-w%oB4GRf*aJ(=etQ zOqYikHNmZ!yAH2Bwv3*A1$|%@L1-;U`b|CFFlnnB7OjfY#HAs7-AEVWIT@9(G`YO0 zu!fG9t_p=>NK~dsHRbLksET7~9Te>3wqcd9C()Re?1IFye% z(ZOUO<3A%S(*UNj6{tAk%2lYSkBJgG=+dY=>XpSx&?oiqo4L1Ar{sTopP$Zn>+Dsg z-lu%^Kkbvf_SE*|_ivQnU3vR0dhpTvmfHDc70Fobu&5f3E(a)vlj?X9sWMq55Kf3+&PN5PV*F+9L}}#Z<+&}*n^|?#9Q1vY#F|WHnI>5wWf;6jKcwdgC&wsg zGAgdK%$Q4v<4Ck=F`{_4tr3N91>sId^{SWq>daY%ud{K`MgNJS`$mDy0j|2@LZWBFZo!!>;u4o&CPdzj)kL7&1P4W3`Oi-WV?9 zd1h?aLu+TZS5xNAQ41%{RtqN=sD)FIr_6)rtA$f1!KbK&)8?v$(-*3Rv$%G`G_`Ox z=Vya+I5!V@-gFrM^YAl|a|NT|(eM~}ER36i$!g*JDewtu;euK40<~}TEY&1UP**hqIWN6E)7wo`gH}B4Rgf zD$(HyS>ngxJn=DazWkH47EF^!PLo*j;$r?uJm(Rqf<@eSfg4px|NJR#gin^S#Vn$gHxa!tHp()G>O*XswXZaNRD;t2-Hu4-?x?y_5`wbY%;* zzeMSnU?(!GO50=>Eu21TT(qVR+vyUSYNuj}YB74qOwqL)jm2(6yVz-XnO^tgc%mB9 zUW{&6Y+jgL{0)p5d~|peH6lSXrV$m>a92ias}q%OBg0a}Aq}#IP5}jjCN1{DS)y!U z(h_^toPsf8tSGKdG7C4o*$(Y*hjeCidN)$Fv1%-BGVF1OVbXC*7hf4iFIdSWoZn8< zX{^hOOn+4?_5rW=AaTPat}*Osn4U!oppzIzVydfGb~-QEA)a-aPQ4^qh34QzQYryu zG<jXAS}kBN#Ueu-F_qQ&?o&Ta_h46K=I;@M5yCPv@ys>2D_ov7Ge zqPI{$wr7%~b{Z`}kER6b|;T>$(s<2p8Bx-6CB~d+Odc{~S`AcIElQMa#L)PQ7dyX56(~=500m*YS zqh3i`CAdr}h~D0%`a`8*{llv?BgOh&Aq{_sDR0-D>&`tzZ9owbi>546Oc1MYN6iv> zm-%4&g=xW%d^3j}Qg4i>a6ok7t~lLe`E@C+m70lRi_6y_}WS=$YSSsB)FMjxu&@cy+vzNhsMWeXJKn zU;H!vIJ_RbTo&cjO#dSJkmTvt6J%fux_Q?Rea|%oFywOMPYJ>ypd)t2a{<@ zbpn%qvdSGeb-6A;X_9K@d2t&V)x#SocbyL3kW^b6qa9SmmwUm2^vhMZYg}bGp!N_`19#3w_3L_d2G7MAb;q&O7ldr*{ldeE840rS~QG z(d&1e-$(lm-$$Qy@6!=;*McB6i;h#`0{cV89Nuwhbd)9Qs@g=Em>+0O(Sd_&2KG{J zz$(^J$=nLI>wK3P5V_}$;Z&V!tlOeoWA1u=lL>xhLh7(A& z<#2ty-Y!FStMe}7O}q0F?XF7@T`{XAOI#x;dC_UCcU=!UZGYxYfqrz^=%|~~UMzI+ z$cRn$b?jKsi8>lo zezBVsGOX5?7nadJq}5?5TPPbm0;V)kH%nd1B{M|YFQX>C@4t~NQI>6+NsiB%~ZoZLM|OX5}W>O_fJ zF@D_eabu%7lTKPZBy)iMWk}cKKh+JBoKLX4sn;aR+$3?ssXD{-qV5juuJih(w}rR` zNoQo-xV?KOUrqMz0O?=o{pPv-f9bY^q8oqZVt$Fn^dHUj9DO}^tv=tB(%AN)zFss^ zUvIrzpKn>IF+WS6j~=bD?IC?Wda=g(LE8WS7PhtM`=8oTN94dXQyne;WR(*9ff>GSzBHKw05;jhscHTQ2EV8Z#KKA%2Qqx!()&v1Rc zb)7z+y+UJ~qtCY;W&A&A&R?W4_W*sqX}ZD3_4%e7H0GPBCt~OYO1wtw&4Xu#Zh=2pupAyhYzEn$u&A|-BWhO zUtPw=$5sU~>|rQORIxFDRnY1xdKmUC=y7(IEX`}X8}^A#^wdt{g$+zE3=TLJ?Fd6L zQR_;)^j=!A$}V9qP$dexr&O{4D!V>PlhIjIPGObK-B2Svu~|8kl^Ff&%6$?g?7|^l zr7?DDN(#CdKa@h_UK+_Nk9^Z6T&RXNsGej4&RFfm&~5)u7qRCvmjHRhhw0TncD=KK-#-s;*PthHTB-*j1p*EKh4^4QcYF^kfa$f&NQZ;CFTWXjtnHrQS0l;REhXWAf} z3xe$z|5WNs@nW&2Esm$jxQ2JCe`d1L#qeB@Y(AGo53|KLl#Wj0;jJZ%myNv{8wtHa zQZ{3{$hUFdAe}rF$e-Hl_{tf&q_*wWV_%Zll z_&)f@@a^!A;5G0y@a6DD@HucDTnU%Kh49I60Xz$y3{Ql|!Sc<5BjCf}f$$;lL2!S= zB1hpv;UTcN9}iD~=fP*dRqzGy4e(Fk=U_>b=p=*SnXn8H@=}3k;7{ShP*hHXuYu)r zblq`04ZawD4(=Uc4-))6_)R#6b=b4uN8m^|rDns|!LP%IWGPh)-wMA8AJAQ?x$yb$ z-SA6r8{Crx-~-{o@ZoS2-UI#z*IM8PI1V2S|B7%b;C8~l1Xl1;?)^*R(hoj^I9^M< zf6gT-t5zz>o7>vkU*5`_wW$!-Q6WmH5JRa9?@|$Nq#{h^yIt>55x(=c_Vxi(hKE1m zlL}OZH$P}^ui+IMJ>P3@zwIyNEtTRuUOsXonYe&gkMyH*eEep6`>TIyZ-4QR)R8x+ zgMXkL;H#-H7JTh%gbyD8?*)&7SHkbZtGT`aw{!5f0{^cNPAP96$sz24+-E-b`#F_y zG4U8lobrj^rNp&2aetPyJVN^3CC$f^S8wy0#0Obte}p$Lf5HRtrw>r-v%{2na+p#N zj8^IuHjo{dr_^_*@fq;hlsBug*PNo%vLdCbm+&sOD)PCG{5^-fy@*9|-g0u*wMwm{ za%^l+YWtl^?Rzg}_>fXr?529HS*a_3NtwK))MdXX|Np4eAOEb>6YnXN_*khos7!l* zu2e5H;V1aE?r^@Ewy=+-M)Dr^C-%0~*8ME?-T{`nsK2G2JJ?bWL@hOIprtN3)KcYx zEY$`dJeY#ycV6YnKM(ll$HZQK-hPwTyq5=zIscs32IhZj{GuUepE)wW?#@Twdvx28 z`H$ZJ!V?pwPs~?ue)NmeXH3dpTe^JgO-rZdPk+Dt=099LBme#6>YfKaaD4t1|H!UA zb>p1;HIL8!c=mY(`3ZH++KTM?`NvFo^^_}aU69}Bk^}a*XY8WL zzl_V*^CP_o?5&hnB-rnZ9YVBdw!`QLBwWk)+41V6EW~OPmz?r?)m}QFDY9?I-Pf(R zESaetGacq#?z)7#-CG6-?LhBi{XXvNVp$7;P+eGd%}N1e&AKjuOXkxxg+6O@E#n$z_l;n$C0mq&x0S{xV60z zz6-ttPQj-DYeec?uA;lq)S_8nItUj*L> z-wxjoKZLtY;6Gsd57?yOGI%z83VaXeL*sVlNweS#LfbbA^%7gokZ5@f!%&>*2pi7i z0jJ_Pc1M}Sxf+7I8m71Lx*LPt3diD=JS-)97QKnL)L(bzO+DJn-qyaw+Sc9#mm3}r z3U7qxuwskOH6iLws<3vtTbtc2y{_IsSLgm_5jV^}>`K7Q9Ag!k4f2^iSMtCd)1K1! z0F?=EmOLKEw4XIId6dkx54rYtHuv(&xGTVZ9}`n8L9ih0ZhYn$Ix$$wxk~ns}Momtd-omwHheZG3p{ z%?`PkvrLc@{!5*)^#+I+On$`Q!^$_tZLhHK7eLY=ZG>$*3Wj z+sHza7*@R)kMhdPwf4HUTq=9KM&fUbu9+>WZWL*g8NU>t=;sU#$+{)wUN+aHV$9aP zds9RvowBb2o1ZAlR30%^YK30x>NOenl$#V8drH_m!EnVE78HIjGz!H0=GMu+DN}&D zWS5H_)GWu=u$)475Jf?gy&Ud_=Z;D`ih?q~X>ObMcT9Q=%G}bFlhLu}ZMYWKX1b{pnoF{isl;5U4G10%-!I41c_ zc8#WJr^|CAu@c#ZX_~r;!)Phn1@gFGRltPK=o(DpXbO^k!VJEmMs{S?Xj6c}b{6c0 zMpI~BIy>5;$@)0DHVsVgZ^yF3Gn_02XA1+*O#!AhEJ-FawRVgYth*;mMjnQySaj~9*|SZ1VSBIJVU3|E z`MIUZy?6kC=n)#*3gYrqc3o;%lwIsGEbHOY!P=~ktPO(0%#raWRP#?e%D zLV8}g-*B(BaC#YoU+D<9r7exGG^_J&E7GHyQVZS2JUA?q`-8L-m*bpH9;P9(7P__8?Z}gA2JP$*UCPpnmlTEJm#)|N)-+)IhlyMo2HBD zG4u|D%*3N3k-DMJPA(r_!A5r;88FYliBlarGLOMW=Cl=ZF=vQ8e@6dPv65t&-;_GK zl*;I=k@KR-;$?{>8!cA4^^v_|GVYU`?r$Dj*4Wd&Tp~Mr`hsYVyYt38y{A{Ph8W9= z`&612zTcmWN=xYav;ijI%yXW>=sNwrk?{u04X!cRWKi9u-9-%+8LT(hWU%#4?QXL< zKKyQdJkwy>;5vi9HMqrK{*Sf$a)S*9TMXLwn0OeRX|UYjYJ<-k%>IdXzt~{f;5vgX z2K)Y0yF1q4VuP0%TxYP=pt@JP&oNkTu-@SF22DmAy|Ohwlku(~&-+-+xgu;e@5a2V zJNwjos$QzM>Z5j3yQ@8Tu4zxTm)cwHqxMz%sr`Az=>XMF9jN-NgVe$55EW(9`#^Ol zwwA%_Fm*W3J`GVr)e&l#8m>mDkvvy5N{v=y)L3<-8mErp8Ly+&1a*v>sE$>~@yZvz zkfJ85DZK4|nwqX=V6T~_j#nqB*=mlOtLE`6*okVsVr#Zqq)t*NtHtURb*ef|ovzMM z-%^FDNX1mKDp92>uFBLBRjv~1Otn;1s7h6Z`nEcU z4f5xy^HEMOQkSSp)#d6cb&a}CeGf~~P3mTKi@HtSq1LG%tDma-)C1~a^@w_0HK}H- zNYATZsu$I7)XVA>^*gmuy{_I+e^RY#lX_ddt2V3m)raaM)uukd+VoGgMSZTes_kU7 zZ8=t!)x+v#^|5xhvaP+WeXRYgzE(f0zjd$`wFX*)ti!AvYp6BM8e!#Hqph*lIBUE$ z!J23tXXRUyt*O>@Yo>L)HQSnN67cEstH)xAg0UcLM5 zw)-C0d+xROKKt&sf8PW89oYY%gAa)g7^XDi6`VMK!NNr+oxJ#zQ%^hnjBgbd#fnQx<7G?A z6K5{1sH{q+&f@9Fx@F5(tUUYM=bU@q`I|1h=i?_I-<1CTv)67)-@GY($EI|{rt~ep zx@1$j@foC_KXWbDpLv{ruDdmx(l>5O-?SJP3DSh3qZrZf!)@N?nlz!xy z?~2{-4VZ$vOZryO(hP4}R-*Crf7pC;^N*Sv znr~^owfVN@wavFT-_d+$^Sb7{n(uD@aq~URKWYAH^S#ZD&G$9m-~6-Y2bv#jeyI83 z=Jm}#Z+@it(dNgRA8&r5*=LQJg*9A1RGTq(v+z_=I{Y~PVH^qRzf}wZLDhF|ZE{YB zshkxB^9lvgcz9T0m;NhbD@H^|@tO-?ckkNbWzcsQRhHGrhGB0{d*&TK`6uvRpl7Lj zGXnK*7uQ4a`P%Q<2!-c9+B+(kLu}r5U(}&DX6q-TGB0=V>`z??XO_uXnU)!4QDzwK zz@J$i=t4M?ig}5N*cRN#@|=RF*qAp%u#KN*$g1>;!~d`FYL_Q7arBp0DEzNo9t-sj zH%Xp;l&)iik@=0h4n`CzJpq;oh3@ZW$>?DD>4!yiAr8~#6L%HPO-2{|YfF#LRW_x% zua)s-x}Jl5Sv?5Fr!wI_Z>B4iOy+fnvn0W(C>iaA<q06|Klk{adH(S=554nw{hvFFzYm|(_=dq3JT%we zF!-UFkLYLPx-tLg&io^ywzcQdw2Czdk=L%drxI?&D!2uSzG%k zYs+rRYTI2|tt^YUKL4-!kND!>S=#@vUl)6xSH6?8`9jDFLxn6yji%= zH44hZ@8(qpCN*73PmR1Kix*xM%8mth_kelB8PCzn20E7Zur#sc$V#O=qR`cRn#@y- zOWlVsk3BY;>%P!JvYv&>8kVK?i-EZ^N-uNkmvLuohFwWFQPNp8oGnf6Qwf;-1R8>1Qo4Stq(y|71zm+d3jI za(3&F^0qPeRX<&bXQ^x!;fdk1{VUF1fp@{bR5+GU5+!0+c3;D6Lexd;u%_1s z8{R&w-5tz2-7wbTj$@7ORMy8XQMan6S*wb&j&!S)Z#(WUE2~G3UVXCn>Dzzc(9z>& z->mT87oWMT)Sb!-+D&{YeXBaoT4Q`<;d=MI_B)vEx6F5fcN@y;-$YjR7PBgs#^)2P zknO_?R@!$r@t?ide*FjLj2Jhr$$z(ntlizfs#}{H#wwPMUse`(%igEodri-m_blCszwE6FLZ6ttxsqHJ$gum?Aw13?x?((U&C+pegN-8QRq0mJ#;;EtU|{P+k)=H{_{iE zo3;ksH+&H~{ycR2ui$a|v*2;VKZ3_ie-9qFeh@qk$4|YjuY1eet$)zRGM|#4cP#TS z`FY1OUzVSDoTU#l$2^AM{=DnDkL_^3Tj+WwJX0P#%Ax(6<4pMGSoXcjuhkr9?q`mB z>dTqyy+g;D`y2Ov+TOUm zVSD}d^!C*DqU{Ax{`TDM(e2sW)%Lb+t=n3*HEnC$*08O9TY6h+TM<;SEq`0?w&=F( zZE9QF*4C{pTbs5vZf)3F-3fsm@?$ zzOye!Cq_<;jCH0sgCc_>lc6!tKF}n{aq^u*BZo#tLwnnrM%kM9FjOQL8fa_Ui(Mmr z8ej!U`VaX<4eenC>7&R;kv~Cyg?lUy0{Q@Y5qbmqDfB+{IP?eT1?XnzJ?JOU z>(FD+ub``-&Cm~_*P!#Dzd-juzl0uzu7oy1yF0DUZjs$0@7kKGB2|%_pkLUUzGZ8A z#MbnVt?9>+A4krGes61f+tzf2t?7AN)7;41$Oz~-`d6V!L%*{%{n^&^16$M2ZB2LE znl{;*4z@MDWotUa*7T~a=^R_rbGD{Awx-K%P3vt{C)>L6@de+u-tgY#{ zwx;2>rk8C^2icmwZEJei*7TCC>2zDuGq$G7Y)$KIO*h(_X4{&cwlyuaH9cf&YKgQ& z`alyIp@fQ(3GD9j(`{CePO*Y?y%nUP>=yIWt<2;7 zbc+?Fa`uP$=@NE?`DwWoq*+#wu4B)bpN_VI^j#}Ri`k#%r;Dv14Y7i>#0t_fcCh*B zT6V4Z=>RK8*H}TC$$mLMtzr+HpH8-dRA&WgJp1qbbdeRLGIregDTn=ge!7rdcYf;2 zem_6Wu!2;}Y|l>@SV8JxYf9UiPC|3@Q``#D{#KB>+nQ3grlYJN9c~3Fiye!8Dq^3Z zpSoE=DqxoDCq4c*>G3|29bs}1AU!W=cl6BQ6Q`*C5a(}BL1x_E`N*BW{X{3%jNSV< zlN`1EP-nEWcVzF#C@A9OIs+pEBYWAJ2H2Y1!O=H9ejNEYvK@L8+6Mgw+6p}heF5ET zYm#}%kD$!F#J<|4^KDI^*_x8JrhnR+3T;jQureDdD(f%IfiowMGlHQ z?JRYgojaXjkztVy&V$ZVP9Nt4=K<$T=MLv*k)K6Qb#8Z#h#V2QA36}a59;kSItk|n z=XhtWv%>j~b6e!L$OPvUXJ}+-T*_swuK{}GptqV;xG}sE#e0ClC zX>KVTho=crj53yDqGXLSO)xblNF>N+nU1jX>T4qm!0H( z(zEKf&8+$g`*|x!$FURLPnA}Xym|J{=GSjoL3+gsk~eSm=E>i-g5=G6TWn3cvyF`>M?|hV#F;2AjYn%=(KF7Jx>FZqJc-s8oPBj|*{;m$+ zx;3c9x1htvBC&|8$43T7=0p2JqRV%43Y@W#v5_f|U#FjBYZBewfey7bjkY!ANAe@` z3+ws0wx)qR1>z^at}pU{5ZOFc;-@Ijk@!i*^^Z(yzi?W&{?WPD`P_NJ`M`P6c|+_h z&il^e&L5nsoh{A_&dttyVsCMN;=JxW<|J`1`u#tltDMbFq4PsWY%k|^qTj#fTGga7S4v8G%+Gt#zpT6^3km&Z0K<_~3ijEJ>h2Dm)fS!krgDRolL4SsR z0R0>iUH@)K<|_w7Z$V;XI3sdK*+})M#tU=-2iQ zE@>_Lczdm(6`nqAf5)W>*wlrB+VgE8?fI0D_I!OncNRU`uRDv}FGN9Y`W99+VugfU$-q$EqZoPyS^x(TZ^6@)Rt!ibY;<-dxR*> zN~53ry0XYYZ8;v&hL5spLNuKx@ch)>3Q~&a?)>D}okjNR&LX#m=wmBL+pQqIX$5JU z6{O!-LE35s=}%UW{%Qs3Nh?Udwt^HM&wpwKDXf2bLquwg1k>`W9oczrg9R z+3)L|$gEzh_UQed{oJqnGrqbu^DgNBJD)kEwuvQzl>~PUV3U)-?O^9EqbKW?fM=a! z86ibKKFE34k#&J)r*Z2E&P$P(BD*;)&SlOzXSO36^Fz+W$V4<|bY|!@=t1XFr+=h> zTJ+~QR0D6tx0Ry)wbx~ zqHFtYZzB6`ZzB6`Zz6koyr;MCNxKFP~>?`qb7W>s>PE{kyFx&kB;(;;%GX{6;%yy&K6Ie~_w-o_~|ADcrw?*Uf%x z1?gN{)6VpLZ{6&7W_`@B+l&135P5pNw_f&$6{L5pAiZq`=?Zqc_$g>TsI>kZq7gg^ z?mFS1|P7dfcypApjbUk&K`qW1^2{pUj3{+y7uf4Q|jL_zDtD3eE=pYTX;6_pBg! zCw-uyOR*?LtNE|YY5laT`E7W<8lImnvVs(xopuk*O=X@M96ho^t2x~)uYC7%8r%Kl zs%%Xib{i?%qV}^QXGQjRQtp0;B1*iVeP2h)^)M&P*)Ou6TfQecW3is(w-0hAJF;@~ zRrWu8Rr|*dX|KW6Ic2r9>lHfP zj-}n|S-R|TDROe%-8E8%>|kLA9?7h~b#?x|JhGfw(Tr=sWXaJ!CJK0zh#?W)a=jl>Z@0;f~#>0EU%vZ zPtD)|z5YSc-_Tyb=x3jB$A#BeM=a131y!`RjKfQK#q!lE8Un%le?Jt9? zm19G_=akUuqt|~*4T-vas8>&9?j!9(>b?994b4lu`n#+8zN`8z^)oOoTfrWDjO0K2 z3P+j!gnP3;LVjKCpCx=riJ?>kffa(v&D@9>VFeDRp`%WiJ?r#bfC1K#%Jj&bnLq|N)2n%LL-<|NKO z=UrhJG2x`;*tl`8q&u#=l03Gt-ghqTlhwLYe{jE2O@x!5FXz_{DS!OZM9p!8&AqOe z%qg&F@`>-gvfyW*^ly6Xz52Y!x%)Pq5qaxdhwnG0>Bh!aZ#r)6l%{zDviH5}hqIa{ z4jq>B=})FL-JN&d-X&9xYP#mL>kj^T-8-4|g`amRt0`Pw9ZLn@=(B*gukr>%z8%eH z0_8QS!}XVf=jqR2nO7HzKi=c0pQPzhxaK9PoqmWy63_2+C=Xu5+v%nR&hX8ESZ(-Cs=JJlvpxyN__@VKiTd&XW z=plG!4sTLgK72VJ)Z)cT^7>WxosoQpZi3#qKFPdbmPha8g_2b~9ac$>4zG#3-%(T1 z=t+s{T3#l3qWkV=^TJ7a)G71K8*hg8UQ;_b<=s8wub?_vOIYr0Pg4d%B!Q<>71&_V&%6b0ttAf`HlELGair{gR z`7WF1Kl_bfeCuBe9;Y{kj?MS%JpZ}oyLR5OdOPUe``(>*-TUsHckF%t&O7$LgXbM* ze-RAN`#zp`-TO|SckF#H&pYq}~0@VI677v28db00od zR`9w~`a77O`>~<$8&3=N^Xo##Dl`uC2pwmKj-#RDHZz`h_n$Fk%7kdnjJb=3M2{LV zc0{gs-b3H@qeqPX=DL?J9)6QQnfmih{rKN)AG>P5-(3Il{_Q`VKf7ul|LOaG6aLpL z|4z%#8wb9@F6KZsZz+IPZa0+;w)1^A2bmWws3Z2~NqFR3@O(H2ISpP7=OWjGH^F0( z8^BxO@yLzfD!valQQUx${^;h&+2B<8bmRiC7%oCifj8#!DQe^fFo{KDm7E8^3)jne z@LBjewR_WjflLoCkNCqtw&L+2H>0E67oB8N3lW z4bGa&H|~%Nz!=&7kc+?{EkLhEZU8S? zsMIjzdT@_LooETIUD>DT#noT z=AEuoEpk5iCY(lY1kx7p#2tPb zS#UGz_4CMW;P=sEUlI4<@k_aeTmagYN^M2X1}}yCj3&L{?Qk}7Blsu2`?n8rEBN;d zNGGzo5QK*zN5P43E^rQ0T_qZBB#J!e2Z`$ayEG050ttGISpP7HzL=Acf$`L zH-f)}*CV%pAHt6zw}Ck~QTLE@!BgRg)E3f${0zHf&d1y{UHo`@T8>^rnC zdd>L{5Wuwh@2iM(`@WnfMBFJ@{+54Y>vU9lRB}75o>h z#!|k6E!BOfr5xmJ@YRu)%0_Mlx8z!CkhmFTsXBN(avHo1&PQ$p*TYkho51JcnaC~R zMtC-ID>!|$r3#P>z&qh02m>XM<6=9$9cSd>wK=SOBj<7A%5qLKdus8<5lBWAIw!Ch+@5T526~ z1Nb8R7;+2P{U}R4jhqd>GoCz0ZUcXHw52{2H{h%A7UWj24c;nlz!N8s=SOm1@Xv4$ zAFM2(t{|ttJx;XL+sN7A&_(1IaxS>I z*it#;xEDC7oOB@Jq+>3Xeyw z2lu#?vK04V`Q_vZatd4q7a^y?JK$2}M({^h;10O~w63HMAZLRYUB&&7>%qv?40;jPFm;7vD@KjVof_|Xrj_sDHv)=id*B4>lYfCnMBfP-%)e~@#*;~OkB7P$a? z`ZoF~aRc_go%})02LA?^BC9(rwL4rZ=fUIP70CJEJ8&Ag4J^EqJV7o3AA{?Wo51Jb z>yTT(ci=VR9_)S>X+X{fQ}8-u!586s#639iZt@K|A6ySVhTH@`13xWpz`P%mFX9F~ z5q<%=2>cz~g4_yb-$VUF7L36gkyGHlKPAtRqu{IelIP+coZU#CBNu=PxX01B2YcN| zJw(n1XTbfD3&3)CkhlTwgmaJ^!3FnICySvbv2|QKYfU_Q;&qXc(FL;o$ zN3I8-eu%yZxdp6!n7W6Y2K%iipOK^B!;g}O$W7pZkJEnTJh%j2i<|;i!1o}h!CT=* zSpo~xgPx1)3jgYB5?jQ4) zL*z#AykF3kk<;KlE#xP16#NT3egbs>T>cX61UU_!wUN3fGI+sj)EVS@aQo}TA6fl@ z_V@<*f}9PW_ebI;?!iz042zq$skiS_w~s;oz*5~lB=3;3!9T-k6FLFLO=l~cw7ksIottKM3f&=^8YPOsQZy8{##mJ3d`9NE( zKu&>e@M>fi2ifX6nK}oMQ#JXKi*dR97{g{9(c5^qR3J3iRrc)hTH^>n`x`5$ob$8XW43@xCi6M+o}jT z1um$uRRwYpIJnkUS0LwtpDnl58f3M?R-eL+BCoX7)o0tP3ArA;_*`3U6d7E53-Ls5 z1TVXT{5+2H;GOr7hscd!-A~9j{0H z4RQ-Oq;EuRM9u|2iAL0BWHlh7CYD50-#pR_e*4S_UnSvQ;89B>%mp|PJ_4tao4}_k zBI*j{7Vx;Lh*~Rdz)8u7dJMS$d?FQ5uZVlF$BKyh5IGy{zA~bQSm@coM- zY9?|Uc+IMaT8-QQ?tO7YU56Y6@4F$Q8jzd7yfqQ^G;%&zbR+jd7QE(%5!H&^09M`{ zQCpEyp#7tW>NAP^f_pZQUgRiv!!4v2xdFW8R^ou%2p+bUaFKJtm)1qp3glL>{jP|r zM^<-7)NkPiIS*d*U_{-6+yE|mh`1pafq#ZuklVlqACIUvkek4oCnM@pBC}4|#>04gLVG zM{WRbhi^h|1RsPOkek3~;I+st;H&UDp^vf7vM;Rlej!F}QN$Wd@G z{1|dBcqH6}oDWWepGGbK7s1aX7lCp31>_W12e%-n!HeNnkn6$g;f=@*;O+1m$c^BG za4T{X_ze6uatrt>ycxL_d}&?I1^0AZLRwMjiAF z!Uy*mKpjSof(H(CRD;N1A>4>uB=Vu;v&dlKAo5UT@b~aWZF_p*XKBDqR8OK@NDEZuw)47LQa7-a1nAETzQ0} zQX+%LjBr#MIUj5t>8Lfxf-mGcssXtLe0VhJLT&^0!C2CTEI9N? z!V)*&TzIpb2aDkkkyGFUa2s+HIAemsA-hWzz(RL{}fawU|E z+e3F(hpyRyo5w{U7b*MvBM-FP>7_JSz>z+IReRn2% zZVUHQg ztQ~~wmYePcJEnX09%}c|q53K3=7-Kn{Cjkhx{ynqN?8TI^!Dnmg08vNSs2nb=XaEh z6|Nr#_MxrqP5BJjF`oW<<>jTn?sS%p&hka-^_J)it6>XvfH>~Q-PcV4`_e2}&> z+8y`xI4og|_Jy&-^-!7l!}RBi7bg!TPrW+q_v6LGL(jb*GjaCKE&TWDES=$T)gQhW zo`-=l=wyyiM81XZ5iXnXaoD|=9)CaO-QPoL8}n&LGT#c13!Z-uz4j@`g$FZE?#4LT zhjFqu<76+!$)1dpJs2mut3y|3se@K@Q+>;s$6E*OIF3k}Tl;qO5B~f({a|(amOg61 z=HBY~jlI;Q=XwBn?>$($m7GZZIZ02?J4SQP$?ijZ8pOZW3Gj=v#_^R%|ZrZ%hewb->@g`t8=y|KHk4SxVjC;Op=G`LJhCwWqbu zj&q@KoeLlDES?gtuaYit@68kZ@!DDVZak)So)7*$%+-UAVs18$dVkiA_1^E+oo9BU zD~0=v{d=kXS37D?#_T@y^WCpC<+ro*?%eP+?*H>0?=R`=tgOcFrN(aTu0}Ba=P>>c zT!%e`@qa(Y|7^zp-i-g<(FI(c#p|!#`0v~KJ&HT24_<%f^>s@RR!g_+sfsset5Y`a zp$eYgUCmg(n>ub?A9duK-fGzDUg(rP$;%$3W$=#o3FlM6eyV^zX$F1Lar8+?(kBh0 zPdb!7=^*-~{ppkTq)+NYpVXZ`N$WS4?ilXZZKG~o8Qf7@4qg=Kjm_ z>xBK)30r!p$(wtsqc`?YxzBf3L)T}iLF>AygV!)-ua2m_SjXCpJrX^v{q%hQ`2E!J z_?d*C@%R~upCR};6h8;yXMg5ly;GxrR)d9Uq<(VK@!eJeJ0BERf~vn%{E zKQiaOFl5V;eDcq0C7-?iHGD6bQ^|F&-i7-g|2!?M!}#?ZzwFK1{uAieb#`WBsP@?y z`g9W;p|RMJ);)TtJ?8h$?N!t><(EYAq!uR#+g3NXO z@e3b!rbBi0oLB$+{hOpIJiqSMty`~`vv`;rtD)F&cIMAt?<9Ur)XJbQS&Kh}<)R{-33sO;YCFum_;m zm$N3cLGp`rN3OZH0SSK~=MLSC`F~I5hCS3?<=xe8j3*tb3xy|PGbTH?a$fuwgL2Ps zTK(zq(kt%8pNTK<&2J|;P(3f3-N5W~j%T^~#r9YwoKuvg&MD4PEu~rR{u_8ZB*Ia$9} zuNXH*i1M^RCFpY>5l~j;wdLa$ffF z$$Gb}-O4^b*}E=#r)0mL>}!&}YqBPv&vn_mChPD;$g&4c*3VmzWe=RJz1JhlelppI zF8iirA63I7@|Jv&{b90yO7`W-K7ef8%D%f4Vdo;tUb|f6sGLWZHU1Q`?9*!@4B0;} z`^kHiWvTw~D0mutBK$4*EO<411AI696uc4s3;Y?}ZAq5u3lE1U!Smr5yc9kgz68D= zz8$^~ehPjC{tNsGydB<+e(4}M7d{T20~f;8@M`!r_$l~JcnjP!L0sX{@Jx6yyc9kU zz6|~$d^h|k{384Z_yhP0xX+nc>JWG+JOQ2tFN9<8S?~q$mGF)5J@6y&ui!V}kKlHA zucgEn9uDWhv*E??5_lPWG5kIFF8C4n1^6xapK#9#?hhXcPlF5KGvKB01@JZSTKHl3 zX}AS`7v2i*TbZRsz$d^<;mhG4z>RP-{5yCP{1Lnj?o*Ye4u;3TGvU+W8u&8!2k^ac zGyHq_J$O6ZGnu6hgpYuah8Mtva20$mTo2y?KL)=DzXksT&Prvee((tRXm|!JJ-)5j zKciT?Qr-CqUQfQY*PCzS$#?Vi;5)2)@@UK6e2sNqwV&FbFFhWh`l$m|e{~RFXFWtk z)c`e69jXSY!Rjz|xXMvOcz47Re6@AB8lgt=UC2>6jRkSHJ#Uf%v7`Z*6Rsswwl8mE9UXV(i8bU>H@WpH&~pcPUgF; zr|?bJ(|DuB89bg*sESlf6{`|es^UC~u|$=t1Yd4l%C{&h`Ce>NrPNt`leLDgp4O>l zYB^tnU8&Ai-&W_SbNQa>`6{h0pli5Dtx^}OOVoGxTIr?gGIcrMNWD^BrLI=>>Kb*e z`mVZ8RV0clQ%gpT9y2_5L}>-#y9b55N}`aDIrG|zz?r(@;K`D5K5iUxSW=Nld7ert zk~Q(nK{B;6?6$7DI$l*_^q!xf2I zPcDncYI!wC=rEJUvUt3-<66A5CLUiJKK5maI2R{{9obP<*>SJR+KzxLYYSr?RRC9o zRmrN3cyL@(mr5n8JA5arD`TOfj^Nyjfe`hXK%n|mINa)3WxRN$TjHi}WKy`}C4XW& zx#~-||7ulyMMuo#g8N1iQ~ljL>n~OZZmds*Z)nbjZj|DkCjQ_!4ttbSeqZs9%&v~d zL-mbMaK|&%hXdaJ;>-NZiA?@;hC1v;K_A5`eaAJmv5s2L^<~M5y2?xpmQ*K~hhmT@ zS?PI499>siHa>IQ(FSM^h1Id;nJZPL@fCpsUoPjGi7A7cgM=)vT&wX#WM*(40H-|9E?&`GSSi7$?J=} zfJOGD+CA(jclWR?)27W~*nL^4FQ2p6>ba0-Jt81l74UUq)H zBUh{AHSyZQjt0*$<4CB&)x^reiL0R}3%e?bWir%1Sh%A?$JiMfB;3QmnA>s2mpi_b z9g&x)mnACPD0@ZeKNs-d;nbJ6;@a&T{N8nM;g7L#6!KV^td9G85(zBWQr$D*$xKbE zEOWP7f++NNaN(NDF)nphxe7-(%*S&tpe^1&0oOL}weTS`ue2{>|^dJqHTXqBH5= z#LNC)J7*K(Ru#qZJ2P)e7Da+|5h`dvk+`q~-GqXgX*y$uPKVG*+kjw_$-Fda^YO@6 z(_I{?jkaps$SkDX`#$eesG)9x3yHPV&_&HcN|r$@L>CgoML-vx`*PB1i?|WBI0KpA zedoP*?|t`wGn{iKIS~78LtOdVJ=@P<8@vwj9@u9;doM!VeE#0?%q|!~dj{D+UP4|* zUO`?%4v;@0r8lPi??d{K2a!?a7P5idL7K>`$R6?=FK7~AhJcvAmTt}WjzKT4JtRWl7w~+56De^<)Rph70 z>&RQk+sGkug!~ElD{{}9_&mt{$fuA8kOAZ&ud3wyu}(_ygpX`_Av~ zzv)Wt?!W22{HOQdV{?a{EJCOR?rbWV+rT=WFU>6%Dst(5GdVxE0?tjy$(FR7_DZ%? zuB?C$brLF6IF@w?Sf>Wx{L6ABG))tnr5f&<9e-Vio1Bo-`%Jlg_THqMnRay|+^ z!ctlED_Z0UaVDBgoe348<|)+QSXhN9E}P7OAAA1-3>MbpWbFYn`EFsY2+QY`b0y@5 z>CuV^+4f3DtGP<{(7B2nEuPG7$)OAcyJsY)Kx#xTIni+;B|C$Imw!V#R>{GvSE>c4 zq-r#|3E|F{!Wv2{BHt1!f;5m5xFu|B#p0Q&GP@W=E1iR?DdG$kVm)3s3yKj^THKH; z#|u;cervg&k`)oaz$$>wWP5QVC(8U67>{R*oAER}Gl9%vJPv+uwG1WgDdP@X`Br*rSdA0%%m?xjl#hu{q zCQ!rzS>Yef$DQjg%*Vx+BX{N<_dAtWpn{ImE@Z{Q3k&gT!MXd|Li}vnx#uRdPC=%l zP=hKn&~}WVJk%e~LbifDDkV2X2I_GsSt+Ioc~XM?0ewKJ5h;zcUy`PMg`~6sDa=Zm z9Fd$jpPZ1=*w1+>kM~`Y@^app+uKe{0j1v&Es+i&?}`>I8`L$D;9;DhK9b7WQ-x#> zYNJTyGDKG}kI$sL5d!IowulbM7ot@VonN1}p!08~+H6{6BArc@ohyG4E$7M?oeIWS zycph>r=8=~@-aD=tYmBO2cd?RSoVw*yZjD?5@CncLjp* znOB%y{bTqQk;vgWLcG*R{WL&>G)yBjMiVqc6$3qHvJo4z2_vdYb*moL ztNK*G8c>63SdFMLHKAryMXjq1m8x8As~vTyj?}R_QHkc#+?q%8YCg@c1+}mi(PCOc z%V>&L*BV+=YiU&DT3hRAU9G3}wShL&M%q{-x=VNK9^I?^biW?ZgL+tx=rKK^XLLoc z>kYlBxAYyI>RfN@9lfjf^u9jOhx$k#>l2+AF2ikj46orc{6@eC8eU7W>Q=*QS+IsJ z_&z^iI@UxRnj>>;PE2CCEVt#cyq3@MTLCL*g{_Dcvl3PY?{32VI~KLL)wViT*Xmh) zYhVqnku|m^7U3@L<{s|lKJMoM9^_#j;W3`z8Lsd;Z}28>@f}V%=WX8MUEbq;KHx(> z;$uGH#CF+k+hcoepY68;cF+#n5j$ol?2N70b-Q81q}%X$4FI7o>ZTs*{oD3Im_=BO zkv@E<8@dleI|I9-2|I$rZs@^I7{M-Z!4B|&`e9H$1FARG9Zpk*I)9D{~#(9aLrMT~@@ z7!9LkP@`>hjlMB7#s)Fnrq}eFK{H||OvP-NEt8sUvupOvA?Qg!OE2gc1Pv3QU&A6T R_%1EX$K$+npz)CW{02YS>2Lr5 literal 0 HcmV?d00001 diff --git a/mpg123.64/include/fmt123.h b/mpg123.64/include/fmt123.h new file mode 100644 index 00000000..dcabf5e0 --- /dev/null +++ b/mpg123.64/include/fmt123.h @@ -0,0 +1,159 @@ +/* + libmpg123: MPEG Audio Decoder library + + separate header just for audio format definitions not tied to + library code + + copyright 1995-2020 by the mpg123 project + free software under the terms of the LGPL 2.1 + see COPYING and AUTHORS files in distribution or http://mpg123.org +*/ + +#ifndef MPG123_ENC_H +#define MPG123_ENC_H + +/** \file fmt123.h Audio format definitions. */ + +/** \defgroup mpg123_enc mpg123 PCM sample encodings + * These are definitions for audio formats used by libmpg123 and + * libout123. + * + * @{ + */ + +/** An enum over all sample types possibly known to mpg123. + * The values are designed as bit flags to allow bitmasking for encoding + * families. + * This is also why the enum is not used as type for actual encoding variables, + * plain integers (at least 16 bit, 15 bit being used) cover the possible + * combinations of these flags. + * + * Note that (your build of) libmpg123 does not necessarily support all these. + * Usually, you can expect the 8bit encodings and signed 16 bit. + * Also 32bit float will be usual beginning with mpg123-1.7.0 . + * What you should bear in mind is that (SSE, etc) optimized routines may be + * absent for some formats. We do have SSE for 16, 32 bit and float, though. + * 24 bit integer is done via postprocessing of 32 bit output -- just cutting + * the last byte, no rounding, even. If you want better, do it yourself. + * + * All formats are in native byte order. If you need different endinaness, you + * can simply postprocess the output buffers (libmpg123 wouldn't do anything + * else). The macro MPG123_SAMPLESIZE() can be helpful there. + */ +enum mpg123_enc_enum +{ +/* 0000 0000 0000 1111 Some 8 bit integer encoding. */ + MPG123_ENC_8 = 0x00f +/* 0000 0000 0100 0000 Some 16 bit integer encoding. */ +, MPG123_ENC_16 = 0x040 +/* 0100 0000 0000 0000 Some 24 bit integer encoding. */ +, MPG123_ENC_24 = 0x4000 +/* 0000 0001 0000 0000 Some 32 bit integer encoding. */ +, MPG123_ENC_32 = 0x100 +/* 0000 0000 1000 0000 Some signed integer encoding. */ +, MPG123_ENC_SIGNED = 0x080 +/* 0000 1110 0000 0000 Some float encoding. */ +, MPG123_ENC_FLOAT = 0xe00 +/* 0000 0000 1101 0000 signed 16 bit */ +, MPG123_ENC_SIGNED_16 = (MPG123_ENC_16|MPG123_ENC_SIGNED|0x10) +/* 0000 0000 0110 0000 unsigned 16 bit */ +, MPG123_ENC_UNSIGNED_16 = (MPG123_ENC_16|0x20) +/* 0000 0000 0000 0001 unsigned 8 bit */ +, MPG123_ENC_UNSIGNED_8 = 0x01 +/* 0000 0000 1000 0010 signed 8 bit */ +, MPG123_ENC_SIGNED_8 = (MPG123_ENC_SIGNED|0x02) +/* 0000 0000 0000 0100 ulaw 8 bit */ +, MPG123_ENC_ULAW_8 = 0x04 +/* 0000 0000 0000 1000 alaw 8 bit */ +, MPG123_ENC_ALAW_8 = 0x08 +/* 0001 0001 1000 0000 signed 32 bit */ +, MPG123_ENC_SIGNED_32 = MPG123_ENC_32|MPG123_ENC_SIGNED|0x1000 +/* 0010 0001 0000 0000 unsigned 32 bit */ +, MPG123_ENC_UNSIGNED_32 = MPG123_ENC_32|0x2000 +/* 0101 0000 1000 0000 signed 24 bit */ +, MPG123_ENC_SIGNED_24 = MPG123_ENC_24|MPG123_ENC_SIGNED|0x1000 +/* 0110 0000 0000 0000 unsigned 24 bit */ +, MPG123_ENC_UNSIGNED_24 = MPG123_ENC_24|0x2000 +/* 0000 0010 0000 0000 32bit float */ +, MPG123_ENC_FLOAT_32 = 0x200 +/* 0000 0100 0000 0000 64bit float */ +, MPG123_ENC_FLOAT_64 = 0x400 +/* Any possibly known encoding from the list above. */ +, MPG123_ENC_ANY = ( MPG123_ENC_SIGNED_16 | MPG123_ENC_UNSIGNED_16 + | MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8 + | MPG123_ENC_ULAW_8 | MPG123_ENC_ALAW_8 + | MPG123_ENC_SIGNED_32 | MPG123_ENC_UNSIGNED_32 + | MPG123_ENC_SIGNED_24 | MPG123_ENC_UNSIGNED_24 + | MPG123_ENC_FLOAT_32 | MPG123_ENC_FLOAT_64 ) +}; + +/** Get size of one PCM sample with given encoding. + * This is included both in libmpg123 and libout123. Both offer + * an API function to provide the macro results from library + * compile-time, not that of you application. This most likely + * does not matter as I do not expect any fresh PCM sample + * encoding to appear. But who knows? Perhaps the encoding type + * will be abused for funny things in future, not even plain PCM. + * And, by the way: Thomas really likes the ?: operator. + * \param enc the encoding (mpg123_enc_enum value) + * \return size of one sample in bytes + */ +#define MPG123_SAMPLESIZE(enc) ( \ + (enc) < 1 \ + ? 0 \ + : ( (enc) & MPG123_ENC_8 \ + ? 1 \ + : ( (enc) & MPG123_ENC_16 \ + ? 2 \ + : ( (enc) & MPG123_ENC_24 \ + ? 3 \ + : ( ( (enc) & MPG123_ENC_32 \ + || (enc) == MPG123_ENC_FLOAT_32 ) \ + ? 4 \ + : ( (enc) == MPG123_ENC_FLOAT_64 \ + ? 8 \ + : 0 \ +) ) ) ) ) ) + +/** Representation of zero in differing encodings. + * This exists to define proper silence in various encodings without + * having to link to libsyn123 to do actual conversions at runtime. + * You have to handle big/little endian order yourself, though. + * This takes the shortcut that any signed encoding has a zero with + * all-zero bits. Unsigned linear encodings just have the highest bit set + * (2^(n-1) for n bits), while the nonlinear 8-bit ones are special. + * \param enc the encoding (mpg123_enc_enum value) + * \param siz bytes per sample (return value of MPG123_SAMPLESIZE(enc)) + * \param off byte (octet) offset counted from LSB + * \return unsigned byte value for the designated octet + */ +#define MPG123_ZEROSAMPLE(enc, siz, off) ( \ + (enc) == MPG123_ENC_ULAW_8 \ + ? (off == 0 ? 0xff : 0x00) \ + : ( (enc) == MPG123_ENC_ALAW_8 \ + ? (off == 0 ? 0xd5 : 0x00) \ + : ( (((enc) & (MPG123_ENC_SIGNED|MPG123_ENC_FLOAT)) || (siz) != ((off)+1)) \ + ? 0x00 \ + : 0x80 \ + ) ) ) + +/** Structure defining an audio format. + * Providing the members as individual function arguments to define a certain + * output format is easy enough. This struct makes is more comfortable to deal + * with a list of formats. + * Negative values for the members might be used to communicate use of default + * values. + */ +struct mpg123_fmt +{ + long rate; /**< sampling rate in Hz */ + int channels; /**< channel count */ + /** encoding code, can be single value or bitwise or of members of + * mpg123_enc_enum */ + int encoding; +}; + +/* @} */ + +#endif + diff --git a/mpg123.64/include/mpg123.h b/mpg123.64/include/mpg123.h new file mode 100644 index 00000000..7b0a8495 --- /dev/null +++ b/mpg123.64/include/mpg123.h @@ -0,0 +1,1697 @@ +/* + libmpg123: MPEG Audio Decoder library (version 1.26.3) + + copyright 1995-2015 by the mpg123 project + free software under the terms of the LGPL 2.1 + see COPYING and AUTHORS files in distribution or http://mpg123.org +*/ + +#ifndef MPG123_LIB_H +#define MPG123_LIB_H + +#include + +/** \file mpg123.h The header file for the libmpg123 MPEG Audio decoder */ + +/** A macro to check at compile time which set of API functions to expect. + * This should be incremented at least each time a new symbol is added + * to the header. + */ +#define MPG123_API_VERSION 45 + +#ifndef MPG123_EXPORT +/** Defines needed for MS Visual Studio(tm) DLL builds. + * Every public function must be prefixed with MPG123_EXPORT. When building + * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible + * for clients and includes it in the import library which is created together + * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which + * imports the functions from the DLL. + */ +#ifdef BUILD_MPG123_DLL +/* The dll exports. */ +#define MPG123_EXPORT __declspec(dllexport) +#else +#ifdef LINK_MPG123_DLL +/* The exe imports. */ +#define MPG123_EXPORT __declspec(dllimport) +#else +/* Nothing on normal/UNIX builds */ +#define MPG123_EXPORT +#endif +#endif +#endif + +/* This is for Visual Studio, so this header works as distributed in the binary downloads */ +#if defined(_MSC_VER) && !defined(MPG123_DEF_SSIZE_T) +#define MPG123_DEF_SSIZE_T +#include +typedef ptrdiff_t ssize_t; +#endif + +#ifndef MPG123_NO_CONFIGURE /* Enable use of this file without configure. */ +#include +#include + +/* Simplified large file handling. + I used to have a check here that prevents building for a library with conflicting large file setup + (application that uses 32 bit offsets with library that uses 64 bits). + While that was perfectly fine in an environment where there is one incarnation of the library, + it hurt GNU/Linux and Solaris systems with multilib where the distribution fails to provide the + correct header matching the 32 bit library (where large files need explicit support) or + the 64 bit library (where there is no distinction). + + New approach: When the app defines _FILE_OFFSET_BITS, it wants non-default large file support, + and thus functions with added suffix (mpg123_open_64). + Any mismatch will be caught at link time because of the _FILE_OFFSET_BITS setting used when + building libmpg123. Plus, there's dual mode large file support in mpg123 since 1.12 now. + Link failure is not the expected outcome of any half-sane usage anymore. + + More complication: What about client code defining _LARGEFILE64_SOURCE? It might want direct access to the _64 functions, along with the ones without suffix. Well, that's possible now via defining MPG123_NO_LARGENAME and MPG123_LARGESUFFIX, respectively, for disabling or enforcing the suffix names. +*/ + +/* + Now, the renaming of large file aware functions. + By default, it appends underscore _FILE_OFFSET_BITS (so, mpg123_seek_64 for mpg123_seek), if _FILE_OFFSET_BITS is defined. You can force a different suffix via MPG123_LARGESUFFIX (that must include the underscore), or you can just disable the whole mess by defining MPG123_NO_LARGENAME. +*/ +#if (!defined MPG123_NO_LARGENAME) && ((defined _FILE_OFFSET_BITS) || (defined MPG123_LARGESUFFIX)) + +/* Need some trickery to concatenate the value(s) of the given macro(s). */ +#define MPG123_MACROCAT_REALLY(a, b) a ## b +#define MPG123_MACROCAT(a, b) MPG123_MACROCAT_REALLY(a, b) +#ifndef MPG123_LARGESUFFIX +#define MPG123_LARGESUFFIX MPG123_MACROCAT(_, _FILE_OFFSET_BITS) +#endif +#define MPG123_LARGENAME(func) MPG123_MACROCAT(func, MPG123_LARGESUFFIX) + +#define mpg123_open_fixed MPG123_LARGENAME(mpg123_open_fixed) +#define mpg123_open MPG123_LARGENAME(mpg123_open) +#define mpg123_open_fd MPG123_LARGENAME(mpg123_open_fd) +#define mpg123_open_handle MPG123_LARGENAME(mpg123_open_handle) +#define mpg123_framebyframe_decode MPG123_LARGENAME(mpg123_framebyframe_decode) +#define mpg123_decode_frame MPG123_LARGENAME(mpg123_decode_frame) +#define mpg123_tell MPG123_LARGENAME(mpg123_tell) +#define mpg123_tellframe MPG123_LARGENAME(mpg123_tellframe) +#define mpg123_tell_stream MPG123_LARGENAME(mpg123_tell_stream) +#define mpg123_seek MPG123_LARGENAME(mpg123_seek) +#define mpg123_feedseek MPG123_LARGENAME(mpg123_feedseek) +#define mpg123_seek_frame MPG123_LARGENAME(mpg123_seek_frame) +#define mpg123_timeframe MPG123_LARGENAME(mpg123_timeframe) +#define mpg123_index MPG123_LARGENAME(mpg123_index) +#define mpg123_set_index MPG123_LARGENAME(mpg123_set_index) +#define mpg123_position MPG123_LARGENAME(mpg123_position) +#define mpg123_length MPG123_LARGENAME(mpg123_length) +#define mpg123_framelength MPG123_LARGENAME(mpg123_framelength) +#define mpg123_set_filesize MPG123_LARGENAME(mpg123_set_filesize) +#define mpg123_replace_reader MPG123_LARGENAME(mpg123_replace_reader) +#define mpg123_replace_reader_handle MPG123_LARGENAME(mpg123_replace_reader_handle) +#define mpg123_framepos MPG123_LARGENAME(mpg123_framepos) + +#endif /* largefile hackery */ + +#endif /* MPG123_NO_CONFIGURE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup mpg123_init mpg123 library and handle setup + * + * Functions to initialise and shutdown the mpg123 library and handles. + * The parameters of handles have workable defaults, you only have to tune them when you want to tune something;-) + * Tip: Use a RVA setting... + * + * @{ + */ + +/** Opaque structure for the libmpg123 decoder handle. */ +struct mpg123_handle_struct; + +/** Opaque structure for the libmpg123 decoder handle. + * Most functions take a pointer to a mpg123_handle as first argument and operate on its data in an object-oriented manner. + */ +typedef struct mpg123_handle_struct mpg123_handle; + +/** Function to initialise the mpg123 library. + * This should be called once in a non-parallel context. It is not explicitly + * thread-safe, but repeated/concurrent calls still _should_ be safe as static + * tables are filled with the same values anyway. + * + * \return MPG123_OK if successful, otherwise an error number. + */ +MPG123_EXPORT int mpg123_init(void); + +/** Superfluous Function to close down the mpg123 library. + * This was created with the thought that there sometime will be cleanup code + * to be run after library use. This never materialized. You can forget about + * this function and it is only here for old programs that do call it. + */ +MPG123_EXPORT void mpg123_exit(void); + +/** Create a handle with optional choice of decoder (named by a string, see mpg123_decoders() or mpg123_supported_decoders()). + * and optional retrieval of an error code to feed to mpg123_plain_strerror(). + * Optional means: Any of or both the parameters may be NULL. + * + * \param decoder optional choice of decoder variant (NULL for default) + * \param error optional address to store error codes + * \return Non-NULL pointer to fresh handle when successful. + */ +MPG123_EXPORT mpg123_handle *mpg123_new(const char* decoder, int *error); + +/** Delete handle, mh is either a valid mpg123 handle or NULL. + * \param mh handle + */ +MPG123_EXPORT void mpg123_delete(mpg123_handle *mh); + +/** Free plain memory allocated within libmpg123. + * This is for library users that are not sure to use the same underlying + * memory allocator as libmpg123. It is just a wrapper over free() in + * the underlying C library. + */ +MPG123_EXPORT void mpg123_free(void *ptr); + +/** Enumeration of the parameters types that it is possible to set/get. */ +enum mpg123_parms +{ + MPG123_VERBOSE = 0, /**< set verbosity value for enabling messages to stderr, >= 0 makes sense (integer) */ + MPG123_FLAGS, /**< set all flags, p.ex val = MPG123_GAPLESS|MPG123_MONO_MIX (integer) */ + MPG123_ADD_FLAGS, /**< add some flags (integer) */ + MPG123_FORCE_RATE, /**< when value > 0, force output rate to that value (integer) */ + MPG123_DOWN_SAMPLE, /**< 0=native rate, 1=half rate, 2=quarter rate (integer) */ + MPG123_RVA, /**< one of the RVA choices above (integer) */ + MPG123_DOWNSPEED, /**< play a frame N times (integer) */ + MPG123_UPSPEED, /**< play every Nth frame (integer) */ + MPG123_START_FRAME, /**< start with this frame (skip frames before that, integer) */ + MPG123_DECODE_FRAMES, /**< decode only this number of frames (integer) */ + MPG123_ICY_INTERVAL, /**< Stream contains ICY metadata with this interval (integer). + Make sure to set this _before_ opening a stream.*/ + MPG123_OUTSCALE, /**< the scale for output samples (amplitude - integer or float according to mpg123 output format, normally integer) */ + MPG123_TIMEOUT, /**< timeout for reading from a stream (not supported on win32, integer) */ + MPG123_REMOVE_FLAGS, /**< remove some flags (inverse of MPG123_ADD_FLAGS, integer) */ + MPG123_RESYNC_LIMIT, /**< Try resync on frame parsing for that many bytes or until end of stream (<0 ... integer). This can enlarge the limit for skipping junk on beginning, too (but not reduce it). */ + MPG123_INDEX_SIZE /**< Set the frame index size (if supported). Values <0 mean that the index is allowed to grow dynamically in these steps (in positive direction, of course) -- Use this when you really want a full index with every individual frame. */ + ,MPG123_PREFRAMES /**< Decode/ignore that many frames in advance for layer 3. This is needed to fill bit reservoir after seeking, for example (but also at least one frame in advance is needed to have all "normal" data for layer 3). Give a positive integer value, please.*/ + ,MPG123_FEEDPOOL /**< For feeder mode, keep that many buffers in a pool to avoid frequent malloc/free. The pool is allocated on mpg123_open_feed(). If you change this parameter afterwards, you can trigger growth and shrinkage during decoding. The default value could change any time. If you care about this, then set it. (integer) */ + ,MPG123_FEEDBUFFER /**< Minimal size of one internal feeder buffer, again, the default value is subject to change. (integer) */ + ,MPG123_FREEFORMAT_SIZE /**< Tell the parser a free-format frame size to + * avoid read-ahead to get it. A value of -1 (default) means that the parser + * will determine it. The parameter value is applied during decoder setup + * for a freshly opened stream only. + */ +}; + +/** Flag bits for MPG123_FLAGS, use the usual binary or to combine. */ +enum mpg123_param_flags +{ + MPG123_FORCE_MONO = 0x7 /**< 0111 Force some mono mode: This is a test bitmask for seeing if any mono forcing is active. */ + ,MPG123_MONO_LEFT = 0x1 /**< 0001 Force playback of left channel only. */ + ,MPG123_MONO_RIGHT = 0x2 /**< 0010 Force playback of right channel only. */ + ,MPG123_MONO_MIX = 0x4 /**< 0100 Force playback of mixed mono. */ + ,MPG123_FORCE_STEREO = 0x8 /**< 1000 Force stereo output. */ + ,MPG123_FORCE_8BIT = 0x10 /**< 00010000 Force 8bit formats. */ + ,MPG123_QUIET = 0x20 /**< 00100000 Suppress any printouts (overrules verbose). */ + ,MPG123_GAPLESS = 0x40 /**< 01000000 Enable gapless decoding (default on if libmpg123 has support). */ + ,MPG123_NO_RESYNC = 0x80 /**< 10000000 Disable resync stream after error. */ + ,MPG123_SEEKBUFFER = 0x100 /**< 000100000000 Enable small buffer on non-seekable streams to allow some peek-ahead (for better MPEG sync). */ + ,MPG123_FUZZY = 0x200 /**< 001000000000 Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC) */ + ,MPG123_FORCE_FLOAT = 0x400 /**< 010000000000 Force floating point output (32 or 64 bits depends on mpg123 internal precision). */ + ,MPG123_PLAIN_ID3TEXT = 0x800 /**< 100000000000 Do not translate ID3 text data to UTF-8. ID3 strings will contain the raw text data, with the first byte containing the ID3 encoding code. */ + ,MPG123_IGNORE_STREAMLENGTH = 0x1000 /**< 1000000000000 Ignore any stream length information contained in the stream, which can be contained in a 'TLEN' frame of an ID3v2 tag or a Xing tag */ + ,MPG123_SKIP_ID3V2 = 0x2000 /**< 10 0000 0000 0000 Do not parse ID3v2 tags, just skip them. */ + ,MPG123_IGNORE_INFOFRAME = 0x4000 /**< 100 0000 0000 0000 Do not parse the LAME/Xing info frame, treat it as normal MPEG data. */ + ,MPG123_AUTO_RESAMPLE = 0x8000 /**< 1000 0000 0000 0000 Allow automatic internal resampling of any kind (default on if supported). Especially when going lowlevel with replacing output buffer, you might want to unset this flag. Setting MPG123_DOWNSAMPLE or MPG123_FORCE_RATE will override this. */ + ,MPG123_PICTURE = 0x10000 /**< 17th bit: Enable storage of pictures from tags (ID3v2 APIC). */ + ,MPG123_NO_PEEK_END = 0x20000 /**< 18th bit: Do not seek to the end of + * the stream in order to probe + * the stream length and search for the id3v1 field. This also means + * the file size is unknown unless set using mpg123_set_filesize() and + * the stream is assumed as non-seekable unless overridden. + */ + ,MPG123_FORCE_SEEKABLE = 0x40000 /**< 19th bit: Force the stream to be seekable. */ + ,MPG123_STORE_RAW_ID3 = 0x80000 /**< store raw ID3 data (even if skipping) */ + ,MPG123_FORCE_ENDIAN = 0x100000 /**< Enforce endianess of output samples. + * This is not reflected in the format codes. If this flag is set along with + * MPG123_BIG_ENDIAN, MPG123_ENC_SIGNED16 means s16be, without + * MPG123_BIG_ENDIAN, it means s16le. Normal operation without + * MPG123_FORCE_ENDIAN produces output in native byte order. + */ + ,MPG123_BIG_ENDIAN = 0x200000 /**< Choose big endian instead of little. */ + ,MPG123_NO_READAHEAD = 0x400000 /**< Disable read-ahead in parser. If + * you know you provide full frames to the feeder API, this enables + * decoder output from the first one on, instead of having to wait for + * the next frame to confirm that the stream is healthy. It also disables + * free format support unless you provide a frame size using + * MPG123_FREEFORMAT_SIZE. + */ + ,MPG123_FLOAT_FALLBACK = 0x800000 /**< Consider floating point output encoding only after + * trying other (possibly downsampled) rates and encodings first. This is to + * support efficient playback where floating point output is only configured for + * an external resampler, bypassing that resampler when the desired rate can + * be produced directly. This is enabled by default to be closer to older versions + * of libmpg123 which did not enable float automatically at all. If disabled, + * float is considered after the 16 bit default and higher-bit integer encodings + * for any rate. */ + ,MPG123_NO_FRANKENSTEIN = 0x1000000 /**< Disable support for Frankenstein streams + * (different MPEG streams stiched together). Do not accept serious change of MPEG + * header inside a single stream. With this flag, the audio output format cannot + * change during decoding unless you open a new stream. This also stops decoding + * after an announced end of stream (Info header contained a number of frames + * and this number has been reached). This makes your MP3 files behave more like + * ordinary media files with defined structure, rather than stream dumps with + * some sugar. */ +}; + +/** choices for MPG123_RVA */ +enum mpg123_param_rva +{ + MPG123_RVA_OFF = 0 /**< RVA disabled (default). */ + ,MPG123_RVA_MIX = 1 /**< Use mix/track/radio gain. */ + ,MPG123_RVA_ALBUM = 2 /**< Use album/audiophile gain */ + ,MPG123_RVA_MAX = MPG123_RVA_ALBUM /**< The maximum RVA code, may increase in future. */ +}; + +/** Set a specific parameter, for a specific mpg123_handle, using a parameter + * type key chosen from the mpg123_parms enumeration, to the specified value. + * \param mh handle + * \param type parameter choice + * \param value integer value + * \param fvalue floating point value + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_param( mpg123_handle *mh +, enum mpg123_parms type, long value, double fvalue ); + +/** Get a specific parameter, for a specific mpg123_handle. + * See the mpg123_parms enumeration for a list of available parameters. + * \param mh handle + * \param type parameter choice + * \param value integer value return address + * \param fvalue floating point value return address + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getparam( mpg123_handle *mh +, enum mpg123_parms type, long *value, double *fvalue ); + +/** Feature set available for query with mpg123_feature. */ +enum mpg123_feature_set +{ + MPG123_FEATURE_ABI_UTF8OPEN = 0 /**< mpg123 expects path names to be given in UTF-8 encoding instead of plain native. */ + ,MPG123_FEATURE_OUTPUT_8BIT /**< 8bit output */ + ,MPG123_FEATURE_OUTPUT_16BIT /**< 16bit output */ + ,MPG123_FEATURE_OUTPUT_32BIT /**< 32bit output */ + ,MPG123_FEATURE_INDEX /**< support for building a frame index for accurate seeking */ + ,MPG123_FEATURE_PARSE_ID3V2 /**< id3v2 parsing */ + ,MPG123_FEATURE_DECODE_LAYER1 /**< mpeg layer-1 decoder enabled */ + ,MPG123_FEATURE_DECODE_LAYER2 /**< mpeg layer-2 decoder enabled */ + ,MPG123_FEATURE_DECODE_LAYER3 /**< mpeg layer-3 decoder enabled */ + ,MPG123_FEATURE_DECODE_ACCURATE /**< accurate decoder rounding */ + ,MPG123_FEATURE_DECODE_DOWNSAMPLE /**< downsample (sample omit) */ + ,MPG123_FEATURE_DECODE_NTOM /**< flexible rate decoding */ + ,MPG123_FEATURE_PARSE_ICY /**< ICY support */ + ,MPG123_FEATURE_TIMEOUT_READ /**< Reader with timeout (network). */ + ,MPG123_FEATURE_EQUALIZER /**< tunable equalizer */ + ,MPG123_FEATURE_MOREINFO /**< more info extraction (for frame analyzer) */ + ,MPG123_FEATURE_OUTPUT_FLOAT32 /**< 32 bit float output */ + ,MPG123_FEATURE_OUTPUT_FLOAT64 /**< 64 bit float output (usually never) */ +}; + +/** Query libmpg123 features. + * \param key feature selection + * \return 1 for success, 0 for unimplemented functions + */ +MPG123_EXPORT int mpg123_feature(const enum mpg123_feature_set key); + +/** Query libmpg123 features with better ABI compatibility + * + * This is the same as mpg123_feature(), but this time not using + * the enum as argument. Compilers don't have to agree on the size of + * enums and hence they are not safe in public API. + * + * \param key feature selection + * \return 1 for success, 0 for unimplemented functions + */ +MPG123_EXPORT int mpg123_feature2(int key); + +/* @} */ + + +/** \defgroup mpg123_error mpg123 error handling + * + * Functions to get text version of the error numbers and an enumeration + * of the error codes returned by libmpg123. + * + * Most functions operating on a mpg123_handle simply return MPG123_OK (0) + * on success and MPG123_ERR (-1) on failure, setting the internal error + * variable of the handle to the specific error code. If there was not a valid + * (non-NULL) handle provided to a function operating on one, MPG123_BAD_HANDLE + * may be returned if this can not be confused with a valid positive return + * value. + * Meaning: A function expected to return positive integers on success will + * always indicate error or a special condition by returning a negative one. + * + * Decoding/seek functions may also return message codes MPG123_DONE, + * MPG123_NEW_FORMAT and MPG123_NEED_MORE (all negative, see below on how to + * react). Note that calls to those can be nested, so generally watch out + * for these codes after initial handle setup. + * Especially any function that needs information about the current stream + * to work will try to at least parse the beginning if that did not happen + * yet. + * + * On a function that is supposed to return MPG123_OK on success and + * MPG123_ERR on failure, make sure you check for != MPG123_OK, not + * == MPG123_ERR, as the error code could get more specific in future, + * or there is just a special message from a decoding routine as indicated + * above. + * + * @{ + */ + +/** Enumeration of the message and error codes and returned by libmpg123 functions. */ +enum mpg123_errors +{ + MPG123_DONE=-12, /**< Message: Track ended. Stop decoding. */ + MPG123_NEW_FORMAT=-11, /**< Message: Output format will be different on next call. Note that some libmpg123 versions between 1.4.3 and 1.8.0 insist on you calling mpg123_getformat() after getting this message code. Newer verisons behave like advertised: You have the chance to call mpg123_getformat(), but you can also just continue decoding and get your data. */ + MPG123_NEED_MORE=-10, /**< Message: For feed reader: "Feed me more!" (call mpg123_feed() or mpg123_decode() with some new input data). */ + MPG123_ERR=-1, /**< Generic Error */ + MPG123_OK=0, /**< Success */ + MPG123_BAD_OUTFORMAT, /**< Unable to set up output format! */ + MPG123_BAD_CHANNEL, /**< Invalid channel number specified. */ + MPG123_BAD_RATE, /**< Invalid sample rate specified. */ + MPG123_ERR_16TO8TABLE, /**< Unable to allocate memory for 16 to 8 converter table! */ + MPG123_BAD_PARAM, /**< Bad parameter id! */ + MPG123_BAD_BUFFER, /**< Bad buffer given -- invalid pointer or too small size. */ + MPG123_OUT_OF_MEM, /**< Out of memory -- some malloc() failed. */ + MPG123_NOT_INITIALIZED, /**< You didn't initialize the library! */ + MPG123_BAD_DECODER, /**< Invalid decoder choice. */ + MPG123_BAD_HANDLE, /**< Invalid mpg123 handle. */ + MPG123_NO_BUFFERS, /**< Unable to initialize frame buffers (out of memory?). */ + MPG123_BAD_RVA, /**< Invalid RVA mode. */ + MPG123_NO_GAPLESS, /**< This build doesn't support gapless decoding. */ + MPG123_NO_SPACE, /**< Not enough buffer space. */ + MPG123_BAD_TYPES, /**< Incompatible numeric data types. */ + MPG123_BAD_BAND, /**< Bad equalizer band. */ + MPG123_ERR_NULL, /**< Null pointer given where valid storage address needed. */ + MPG123_ERR_READER, /**< Error reading the stream. */ + MPG123_NO_SEEK_FROM_END,/**< Cannot seek from end (end is not known). */ + MPG123_BAD_WHENCE, /**< Invalid 'whence' for seek function.*/ + MPG123_NO_TIMEOUT, /**< Build does not support stream timeouts. */ + MPG123_BAD_FILE, /**< File access error. */ + MPG123_NO_SEEK, /**< Seek not supported by stream. */ + MPG123_NO_READER, /**< No stream opened. */ + MPG123_BAD_PARS, /**< Bad parameter handle. */ + MPG123_BAD_INDEX_PAR, /**< Bad parameters to mpg123_index() and mpg123_set_index() */ + MPG123_OUT_OF_SYNC, /**< Lost track in bytestream and did not try to resync. */ + MPG123_RESYNC_FAIL, /**< Resync failed to find valid MPEG data. */ + MPG123_NO_8BIT, /**< No 8bit encoding possible. */ + MPG123_BAD_ALIGN, /**< Stack aligmnent error */ + MPG123_NULL_BUFFER, /**< NULL input buffer with non-zero size... */ + MPG123_NO_RELSEEK, /**< Relative seek not possible (screwed up file offset) */ + MPG123_NULL_POINTER, /**< You gave a null pointer somewhere where you shouldn't have. */ + MPG123_BAD_KEY, /**< Bad key value given. */ + MPG123_NO_INDEX, /**< No frame index in this build. */ + MPG123_INDEX_FAIL, /**< Something with frame index went wrong. */ + MPG123_BAD_DECODER_SETUP, /**< Something prevents a proper decoder setup */ + MPG123_MISSING_FEATURE /**< This feature has not been built into libmpg123. */ + ,MPG123_BAD_VALUE /**< A bad value has been given, somewhere. */ + ,MPG123_LSEEK_FAILED /**< Low-level seek failed. */ + ,MPG123_BAD_CUSTOM_IO /**< Custom I/O not prepared. */ + ,MPG123_LFS_OVERFLOW /**< Offset value overflow during translation of large file API calls -- your client program cannot handle that large file. */ + ,MPG123_INT_OVERFLOW /**< Some integer overflow. */ +}; + +/** Look up error strings given integer code. + * \param errcode integer error code + * \return string describing what that error error code means + */ +MPG123_EXPORT const char* mpg123_plain_strerror(int errcode); + +/** Give string describing what error has occured in the context of handle mh. + * When a function operating on an mpg123 handle returns MPG123_ERR, you should check for the actual reason via + * char *errmsg = mpg123_strerror(mh) + * This function will catch mh == NULL and return the message for MPG123_BAD_HANDLE. + * \param mh handle + * \return error message + */ +MPG123_EXPORT const char* mpg123_strerror(mpg123_handle *mh); + +/** Return the plain errcode intead of a string. + * \param mh handle + * \return error code recorded in handle or MPG123_BAD_HANDLE + */ +MPG123_EXPORT int mpg123_errcode(mpg123_handle *mh); + +/*@}*/ + + +/** \defgroup mpg123_decoder mpg123 decoder selection + * + * Functions to list and select the available decoders. + * Perhaps the most prominent feature of mpg123: You have several (optimized) decoders to choose from (on x86 and PPC (MacOS) systems, that is). + * + * @{ + */ + +/** Get available decoder list. + * \return NULL-terminated array of generally available decoder names (plain 8bit ASCII) + */ +MPG123_EXPORT const char **mpg123_decoders(void); + +/** Get supported decoder list. + * \return NULL-terminated array of the decoders supported by the CPU (plain 8bit ASCII) + */ +MPG123_EXPORT const char **mpg123_supported_decoders(void); + +/** Set the active decoder. + * \param mh handle + * \param decoder_name name of decoder + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_decoder(mpg123_handle *mh, const char* decoder_name); + +/** Get the currently active decoder name. + * The active decoder engine can vary depening on output constraints, + * mostly non-resampling, integer output is accelerated via 3DNow & Co. but for + * other modes a fallback engine kicks in. + * Note that this can return a decoder that is only active in the hidden and not + * available as decoder choice from the outside. + * \param mh handle + * \return The decoder name or NULL on error. + */ +MPG123_EXPORT const char* mpg123_current_decoder(mpg123_handle *mh); + +/*@}*/ + + +/** \defgroup mpg123_output mpg123 output audio format + * + * Functions to get and select the format of the decoded audio. + * + * Before you dive in, please be warned that you might get confused by this. + * This seems to happen a lot, therefore I am trying to explain in advance. + * If you do feel confused and just want to decode your normal MPEG audio files that + * don't alter properties in the middle, just use mpg123_open_fixed() with a fixed encoding + * and channel count and forget about a matrix of audio formats. If you want to get funky, + * read ahead ... + * + * The mpg123 library decides what output format to use when encountering the first frame in a stream, or actually any frame that is still valid but differs from the frames before in the prompted output format. At such a deciding point, an internal table of allowed encodings, sampling rates and channel setups is consulted. According to this table, an output format is chosen and the decoding engine set up accordingly (including optimized routines for different output formats). This might seem unusual but it just follows from the non-existence of "MPEG audio files" with defined overall properties. There are streams, streams are concatenations of (semi) independent frames. We store streams on disk and call them "MPEG audio files", but that does not change their nature as the decoder is concerned (the LAME/Xing header for gapless decoding makes things interesting again). + * + * To get to the point: What you do with mpg123_format() and friends is to fill the internal table of allowed formats before it is used. That includes removing support for some formats or adding your forced sample rate (see MPG123_FORCE_RATE) that will be used with the crude internal resampler. Also keep in mind that the sample encoding is just a question of choice -- the MPEG frames do only indicate their native sampling rate and channel count. If you want to decode to integer or float samples, 8 or 16 bit ... that is your decision. In a "clean" world, libmpg123 would always decode to 32 bit float and let you handle any sample conversion. But there are optimized routines that work faster by directly decoding to the desired encoding / accuracy. We prefer efficiency over conceptual tidyness. + * + * People often start out thinking that mpg123_format() should change the actual decoding format on the fly. That is wrong. It only has effect on the next natural change of output format, when libmpg123 will consult its format table again. To make life easier, you might want to call mpg123_format_none() before any thing else and then just allow one desired encoding and a limited set of sample rates / channel choices that you actually intend to deal with. You can force libmpg123 to decode everything to 44100 KHz, stereo, 16 bit integer ... it will duplicate mono channels and even do resampling if needed (unless that feature is disabled in the build, same with some encodings). But I have to stress that the resampling of libmpg123 is very crude and doesn't even contain any kind of "proper" interpolation. + * + * In any case, watch out for MPG123_NEW_FORMAT as return message from decoding routines and call mpg123_getformat() to get the currently active output format. + * + * @{ + */ + +/** They can be combined into one number (3) to indicate mono and stereo... */ +enum mpg123_channelcount +{ + MPG123_MONO = 1 /**< mono */ + ,MPG123_STEREO = 2 /**< stereo */ +}; + +/** An array of supported standard sample rates + * These are possible native sample rates of MPEG audio files. + * You can still force mpg123 to resample to a different one, but by + * default you will only get audio in one of these samplings. + * This list is in ascending order. + * \param list Store a pointer to the sample rates array there. + * \param number Store the number of sample rates there. */ +MPG123_EXPORT void mpg123_rates(const long **list, size_t *number); + +/** An array of supported audio encodings. + * An audio encoding is one of the fully qualified members of mpg123_enc_enum (MPG123_ENC_SIGNED_16, not MPG123_SIGNED). + * \param list Store a pointer to the encodings array there. + * \param number Store the number of encodings there. */ +MPG123_EXPORT void mpg123_encodings(const int **list, size_t *number); + +/** Return the size (in bytes) of one mono sample of the named encoding. + * \param encoding The encoding value to analyze. + * \return positive size of encoding in bytes, 0 on invalid encoding. */ +MPG123_EXPORT int mpg123_encsize(int encoding); + +/** Configure a mpg123 handle to accept no output format at all, + * use before specifying supported formats with mpg123_format + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_format_none(mpg123_handle *mh); + +/** Configure mpg123 handle to accept all formats + * (also any custom rate you may set) -- this is default. + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_format_all(mpg123_handle *mh); + +/** Set the audio format support of a mpg123_handle in detail: + * \param mh handle + * \param rate The sample rate value (in Hertz). + * \param channels A combination of MPG123_STEREO and MPG123_MONO. + * \param encodings A combination of accepted encodings for rate and channels, p.ex MPG123_ENC_SIGNED16 | MPG123_ENC_ULAW_8 (or 0 for no support). Please note that some encodings may not be supported in the library build and thus will be ignored here. + * \return MPG123_OK on success, MPG123_ERR if there was an error. */ +MPG123_EXPORT int mpg123_format( mpg123_handle *mh +, long rate, int channels, int encodings ); + +/** Set the audio format support of a mpg123_handle in detail: + * \param mh handle + * \param rate The sample rate value (in Hertz). Special value 0 means + * all rates (the reason for this variant of mpg123_format()). + * \param channels A combination of MPG123_STEREO and MPG123_MONO. + * \param encodings A combination of accepted encodings for rate and channels, + * p.ex MPG123_ENC_SIGNED16 | MPG123_ENC_ULAW_8 (or 0 for no support). + * Please note that some encodings may not be supported in the library build + * and thus will be ignored here. + * \return MPG123_OK on success, MPG123_ERR if there was an error. */ +MPG123_EXPORT int mpg123_format2( mpg123_handle *mh +, long rate, int channels, int encodings ); + +/** Check to see if a specific format at a specific rate is supported + * by mpg123_handle. + * \param mh handle + * \param rate sampling rate + * \param encoding encoding + * \return 0 for no support (that includes invalid parameters), MPG123_STEREO, + * MPG123_MONO or MPG123_STEREO|MPG123_MONO. */ +MPG123_EXPORT int mpg123_format_support( mpg123_handle *mh +, long rate, int encoding ); + +/** Get the current output format written to the addresses given. + * If the stream is freshly loaded, this will try to parse enough + * of it to give you the format to come. This clears the flag that + * would otherwise make the first decoding call return + * MPG123_NEW_FORMAT. + * \param mh handle + * \param rate sampling rate return address + * \param channels channel count return address + * \param encoding encoding return address + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getformat( mpg123_handle *mh +, long *rate, int *channels, int *encoding ); + +/** Get the current output format written to the addresses given. + * This differs from plain mpg123_getformat() in that you can choose + * _not_ to clear the flag that would trigger the next decoding call + * to return MPG123_NEW_FORMAT in case of a new format arriving. + * \param mh handle + * \param rate sampling rate return address + * \param channels channel count return address + * \param encoding encoding return address + * \param clear_flag if true, clear internal format flag + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getformat2( mpg123_handle *mh +, long *rate, int *channels, int *encoding, int clear_flag ); + +/*@}*/ + + +/** \defgroup mpg123_input mpg123 file input and decoding + * + * Functions for input bitstream and decoding operations. + * Decoding/seek functions may also return message codes MPG123_DONE, MPG123_NEW_FORMAT and MPG123_NEED_MORE (please read up on these on how to react!). + * @{ + */ + +/** Open a simple MPEG file with fixed properties. + * + * This function shall simplify the common use case of a plain MPEG + * file on disk that you want to decode, with one fixed sample + * rate and channel count, and usually a length defined by a Lame/Info/Xing + * tag. It will: + * + * - set the MPG123_NO_FRANKENSTEIN flag + * - set up format support according to given parameters, + * - open the file, + * - query audio format, + * - fix the audio format support table to ensure the format stays the same, + * - call mpg123_scan() if there is no header frame to tell the track length. + * + * From that on, you can call mpg123_getformat() for querying the sample + * rate (and channel count in case you allowed both) and mpg123_length() + * to get a pretty safe number for the duration. + * Only the sample rate is left open as that indeed is a fixed property of + * MPEG files. You could set MPG123_FORCE_RATE beforehand, but that may trigger + * low-quality resampling in the decoder, only do so if in dire need. + * The library will convert mono files to stereo for you, and vice versa. + * If any constraint cannot be satisified (most likely because of a non-default + * build of libmpg123), you get MPG123_ERR returned and can query the detailed + * cause from the handle. Only on MPG123_OK there will an open file that you + * then close using mpg123_close(), or implicitly on mpg123_delete() or the next + * call to open another file. + * + * So, for your usual CD rip collection, you could use + * + * mpg123_open_fixed(mh, path, MPG123_STEREO, MPG123_ENC_SIGNED_16) + * + * and be happy calling mpg123_getformat() to verify 44100 Hz rate, then just + * playing away with mpg123_read(). The occasional mono file, or MP2 file, + * will also be decoded without you really noticing. Just the speed could be + * wrong if you do not care about sample rate at all. + * \param mh handle + * \param path filesystem path + * \param channels allowed channel count, either 1 (MPG123_MONO) or + * 2 (MPG123_STEREO), or bitwise or of them, but then you're halfway back to + * calling mpg123_format() again;-) + * \param encoding a definite encoding from enum mpg123_enc_enum + * or a bitmask like for mpg123_format(), defeating the purpose somewhat + */ +MPG123_EXPORT int mpg123_open_fixed(mpg123_handle *mh, const char *path +, int channels, int encoding); + +/** Open and prepare to decode the specified file by filesystem path. + * This does not open HTTP urls; libmpg123 contains no networking code. + * If you want to decode internet streams, use mpg123_open_fd() or mpg123_open_feed(). + * \param mh handle + * \param path filesystem path + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_open(mpg123_handle *mh, const char *path); + +/** Use an already opened file descriptor as the bitstream input + * mpg123_close() will _not_ close the file descriptor. + * \param mh handle + * \param fd file descriptor + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_open_fd(mpg123_handle *mh, int fd); + +/** Use an opaque handle as bitstream input. This works only with the + * replaced I/O from mpg123_replace_reader_handle()! + * mpg123_close() will call the cleanup callback for your handle (if you gave one). + * \param mh handle + * \param iohandle your handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_open_handle(mpg123_handle *mh, void *iohandle); + +/** Open a new bitstream and prepare for direct feeding + * This works together with mpg123_decode(); you are responsible for reading and feeding the input bitstream. + * Also, you are expected to handle ICY metadata extraction yourself. This + * input method does not handle MPG123_ICY_INTERVAL. It does parse ID3 frames, though. + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_open_feed(mpg123_handle *mh); + +/** Closes the source, if libmpg123 opened it. + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_close(mpg123_handle *mh); + +/** Read from stream and decode up to outmemsize bytes. + * + * Note: The type of outmemory changed to a void pointer in mpg123 1.26.0 + * (API version 45). + * + * \param mh handle + * \param outmemory address of output buffer to write to + * \param outmemsize maximum number of bytes to write + * \param done address to store the number of actually decoded bytes to + * \return MPG123_OK or error/message code + */ +MPG123_EXPORT int mpg123_read(mpg123_handle *mh +, void *outmemory, size_t outmemsize, size_t *done ); + +/** Feed data for a stream that has been opened with mpg123_open_feed(). + * It's give and take: You provide the bytestream, mpg123 gives you the decoded samples. + * \param mh handle + * \param in input buffer + * \param size number of input bytes + * \return MPG123_OK or error/message code. + */ +MPG123_EXPORT int mpg123_feed( mpg123_handle *mh +, const unsigned char *in, size_t size ); + +/** Decode MPEG Audio from inmemory to outmemory. + * This is very close to a drop-in replacement for old mpglib. + * When you give zero-sized output buffer the input will be parsed until + * decoded data is available. This enables you to get MPG123_NEW_FORMAT (and query it) + * without taking decoded data. + * Think of this function being the union of mpg123_read() and mpg123_feed() (which it actually is, sort of;-). + * You can actually always decide if you want those specialized functions in separate steps or one call this one here. + * + * Note: The type of outmemory changed to a void pointer in mpg123 1.26.0 + * (API version 45). + * + * \param mh handle + * \param inmemory input buffer + * \param inmemsize number of input bytes + * \param outmemory output buffer + * \param outmemsize maximum number of output bytes + * \param done address to store the number of actually decoded bytes to + * \return error/message code (watch out especially for MPG123_NEED_MORE) + */ +MPG123_EXPORT int mpg123_decode( mpg123_handle *mh +, const unsigned char *inmemory, size_t inmemsize +, void *outmemory, size_t outmemsize, size_t *done ); + +/** Decode next MPEG frame to internal buffer + * or read a frame and return after setting a new format. + * \param mh handle + * \param num current frame offset gets stored there + * \param audio This pointer is set to the internal buffer to read the decoded audio from. + * \param bytes number of output bytes ready in the buffer + * \return MPG123_OK or error/message code + */ +MPG123_EXPORT int mpg123_decode_frame( mpg123_handle *mh +, off_t *num, unsigned char **audio, size_t *bytes ); + +/** Decode current MPEG frame to internal buffer. + * Warning: This is experimental API that might change in future releases! + * Please watch mpg123 development closely when using it. + * \param mh handle + * \param num last frame offset gets stored there + * \param audio this pointer is set to the internal buffer to read the decoded audio from. + * \param bytes number of output bytes ready in the buffer + * \return MPG123_OK or error/message code + */ +MPG123_EXPORT int mpg123_framebyframe_decode( mpg123_handle *mh +, off_t *num, unsigned char **audio, size_t *bytes ); + +/** Find, read and parse the next mp3 frame + * Warning: This is experimental API that might change in future releases! + * Please watch mpg123 development closely when using it. + * \param mh handle + * \return MPG123_OK or error/message code + */ +MPG123_EXPORT int mpg123_framebyframe_next(mpg123_handle *mh); + +/** Get access to the raw input data for the last parsed frame. + * This gives you a direct look (and write access) to the frame body data. + * Together with the raw header, you can reconstruct the whole raw MPEG stream without junk and meta data, or play games by actually modifying the frame body data before decoding this frame (mpg123_framebyframe_decode()). + * A more sane use would be to use this for CRC checking (see mpg123_info() and MPG123_CRC), the first two bytes of the body make up the CRC16 checksum, if present. + * You can provide NULL for a parameter pointer when you are not interested in the value. + * + * \param mh handle + * \param header the 4-byte MPEG header + * \param bodydata pointer to the frame body stored in the handle (without the header) + * \param bodybytes size of frame body in bytes (without the header) + * \return MPG123_OK if there was a yet un-decoded frame to get the + * data from, MPG123_BAD_HANDLE or MPG123_ERR otherwise (without further + * explanation, the error state of the mpg123_handle is not modified by + * this function). + */ +MPG123_EXPORT int mpg123_framedata( mpg123_handle *mh +, unsigned long *header, unsigned char **bodydata, size_t *bodybytes ); + +/** Get the input position (byte offset in stream) of the last parsed frame. + * This can be used for external seek index building, for example. + * It just returns the internally stored offset, regardless of validity -- + * you ensure that a valid frame has been parsed before! + * \param mh handle + * \return byte offset in stream + */ +MPG123_EXPORT off_t mpg123_framepos(mpg123_handle *mh); + +/*@}*/ + + +/** \defgroup mpg123_seek mpg123 position and seeking + * + * Functions querying and manipulating position in the decoded audio bitstream. + * The position is measured in decoded audio samples, or MPEG frame offset for the specific functions. + * If gapless code is in effect, the positions are adjusted to compensate the skipped padding/delay - meaning, you should not care about that at all and just use the position defined for the samples you get out of the decoder;-) + * The general usage is modelled after stdlib's ftell() and fseek(). + * Especially, the whence parameter for the seek functions has the same meaning as the one for fseek() and needs the same constants from stdlib.h: + * - SEEK_SET: set position to (or near to) specified offset + * - SEEK_CUR: change position by offset from now + * - SEEK_END: set position to offset from end + * + * Note that sample-accurate seek only works when gapless support has been enabled at compile time; seek is frame-accurate otherwise. + * Also, really sample-accurate seeking (meaning that you get the identical sample value after seeking compared to plain decoding up to the position) is only guaranteed when you do not mess with the position code by using MPG123_UPSPEED, MPG123_DOWNSPEED or MPG123_START_FRAME. The first two mainly should cause trouble with NtoM resampling, but in any case with these options in effect, you have to keep in mind that the sample offset is not the same as counting the samples you get from decoding since mpg123 counts the skipped samples, too (or the samples played twice only once)! + * Short: When you care about the sample position, don't mess with those parameters;-) + * Also, seeking is not guaranteed to work for all streams (underlying stream may not support it). + * And yet another caveat: If the stream is concatenated out of differing pieces (Frankenstein stream), seeking may suffer, too. + * + * @{ + */ + +/** Returns the current position in samples. + * On the next successful read, you'd get that sample. + * \param mh handle + * \return sample offset or MPG123_ERR (null handle) + */ +MPG123_EXPORT off_t mpg123_tell(mpg123_handle *mh); + +/** Returns the frame number that the next read will give you data from. + * \param mh handle + * \return frame offset or MPG123_ERR (null handle) + */ +MPG123_EXPORT off_t mpg123_tellframe(mpg123_handle *mh); + +/** Returns the current byte offset in the input stream. + * \param mh handle + * \return byte offset or MPG123_ERR (null handle) + */ +MPG123_EXPORT off_t mpg123_tell_stream(mpg123_handle *mh); + +/** Seek to a desired sample offset. + * Usage is modelled afer the standard lseek(). + * \param mh handle + * \param sampleoff offset in PCM samples + * \param whence one of SEEK_SET, SEEK_CUR or SEEK_END + * \return The resulting offset >= 0 or error/message code + */ +MPG123_EXPORT off_t mpg123_seek( mpg123_handle *mh +, off_t sampleoff, int whence ); + +/** Seek to a desired sample offset in data feeding mode. + * This just prepares things to be right only if you ensure that the next chunk of input data will be from input_offset byte position. + * \param mh handle + * \param sampleoff offset in PCM samples + * \param whence one of SEEK_SET, SEEK_CUR or SEEK_END + * \param input_offset The position it expects to be at the + * next time data is fed to mpg123_decode(). + * \return The resulting offset >= 0 or error/message code */ +MPG123_EXPORT off_t mpg123_feedseek( mpg123_handle *mh +, off_t sampleoff, int whence, off_t *input_offset ); + +/** Seek to a desired MPEG frame offset. + * Usage is modelled afer the standard lseek(). + * \param mh handle + * \param frameoff offset in MPEG frames + * \param whence one of SEEK_SET, SEEK_CUR or SEEK_END + * \return The resulting offset >= 0 or error/message code */ +MPG123_EXPORT off_t mpg123_seek_frame( mpg123_handle *mh +, off_t frameoff, int whence ); + +/** Return a MPEG frame offset corresponding to an offset in seconds. + * This assumes that the samples per frame do not change in the file/stream, which is a good assumption for any sane file/stream only. + * \return frame offset >= 0 or error/message code */ +MPG123_EXPORT off_t mpg123_timeframe(mpg123_handle *mh, double sec); + +/** Give access to the frame index table that is managed for seeking. + * You are asked not to modify the values... Use mpg123_set_index to set the + * seek index + * \param mh handle + * \param offsets pointer to the index array + * \param step one index byte offset advances this many MPEG frames + * \param fill number of recorded index offsets; size of the array + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_index( mpg123_handle *mh +, off_t **offsets, off_t *step, size_t *fill ); + +/** Set the frame index table + * Setting offsets to NULL and fill > 0 will allocate fill entries. Setting offsets + * to NULL and fill to 0 will clear the index and free the allocated memory used by the index. + * \param mh handle + * \param offsets pointer to the index array + * \param step one index byte offset advances this many MPEG frames + * \param fill number of recorded index offsets; size of the array + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_set_index( mpg123_handle *mh +, off_t *offsets, off_t step, size_t fill ); + +/** An old crutch to keep old mpg123 binaries happy. + * WARNING: This function is there only to avoid runtime linking errors with + * standalone mpg123 before version 1.23.0 (if you strangely update the + * library but not the end-user program) and actually is broken + * for various cases (p.ex. 24 bit output). Do never use. It might eventually + * be purged from the library. + */ +MPG123_EXPORT int mpg123_position( mpg123_handle *mh, off_t frame_offset, off_t buffered_bytes, off_t *current_frame, off_t *frames_left, double *current_seconds, double *seconds_left); + +/*@}*/ + + +/** \defgroup mpg123_voleq mpg123 volume and equalizer + * + * @{ + */ + +/** another channel enumeration, for left/right choice */ +enum mpg123_channels +{ + MPG123_LEFT=0x1 /**< The Left Channel. */ + ,MPG123_RIGHT=0x2 /**< The Right Channel. */ + ,MPG123_LR=0x3 /**< Both left and right channel; same as MPG123_LEFT|MPG123_RIGHT */ +}; + +/** Set the 32 Band Audio Equalizer settings. + * \param mh handle + * \param channel Can be MPG123_LEFT, MPG123_RIGHT or MPG123_LEFT|MPG123_RIGHT for both. + * \param band The equaliser band to change (from 0 to 31) + * \param val The (linear) adjustment factor. + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_eq( mpg123_handle *mh +, enum mpg123_channels channel, int band, double val ); + +/** Get the 32 Band Audio Equalizer settings. + * \param mh handle + * \param channel Can be MPG123_LEFT, MPG123_RIGHT or MPG123_LEFT|MPG123_RIGHT for (arithmetic mean of) both. + * \param band The equaliser band to change (from 0 to 31) + * \return The (linear) adjustment factor (zero for pad parameters) */ +MPG123_EXPORT double mpg123_geteq(mpg123_handle *mh + , enum mpg123_channels channel, int band); + +/** Reset the 32 Band Audio Equalizer settings to flat + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_reset_eq(mpg123_handle *mh); + +/** Set the absolute output volume including the RVA setting, + * vol<0 just applies (a possibly changed) RVA setting. + * \param mh handle + * \param vol volume value (linear factor) + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_volume(mpg123_handle *mh, double vol); + +/** Adjust output volume including the RVA setting by chosen amount + * \param mh handle + * \param change volume value (linear factor increment) + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_volume_change(mpg123_handle *mh, double change); + +/** Return current volume setting, the actual value due to RVA, and the RVA + * adjustment itself. It's all as double float value to abstract the sample + * format. The volume values are linear factors / amplitudes (not percent) + * and the RVA value is in decibels. + * \param mh handle + * \param base return address for base volume (linear factor) + * \param really return address for actual volume (linear factor) + * \param rva_db return address for RVA value (decibels) + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db); + +/* TODO: Set some preamp in addition / to replace internal RVA handling? */ + +/*@}*/ + + +/** \defgroup mpg123_status mpg123 status and information + * + * @{ + */ + +/** Enumeration of the mode types of Variable Bitrate */ +enum mpg123_vbr { + MPG123_CBR=0, /**< Constant Bitrate Mode (default) */ + MPG123_VBR, /**< Variable Bitrate Mode */ + MPG123_ABR /**< Average Bitrate Mode */ +}; + +/** Enumeration of the MPEG Versions */ +enum mpg123_version { + MPG123_1_0=0, /**< MPEG Version 1.0 */ + MPG123_2_0, /**< MPEG Version 2.0 */ + MPG123_2_5 /**< MPEG Version 2.5 */ +}; + + +/** Enumeration of the MPEG Audio mode. + * Only the mono mode has 1 channel, the others have 2 channels. */ +enum mpg123_mode { + MPG123_M_STEREO=0, /**< Standard Stereo. */ + MPG123_M_JOINT, /**< Joint Stereo. */ + MPG123_M_DUAL, /**< Dual Channel. */ + MPG123_M_MONO /**< Single Channel. */ +}; + + +/** Enumeration of the MPEG Audio flag bits */ +enum mpg123_flags { + MPG123_CRC=0x1, /**< The bitstream is error protected using 16-bit CRC. */ + MPG123_COPYRIGHT=0x2, /**< The bitstream is copyrighted. */ + MPG123_PRIVATE=0x4, /**< The private bit has been set. */ + MPG123_ORIGINAL=0x8 /**< The bitstream is an original, not a copy. */ +}; + +/** Data structure for storing information about a frame of MPEG Audio */ +struct mpg123_frameinfo +{ + enum mpg123_version version; /**< The MPEG version (1.0/2.0/2.5). */ + int layer; /**< The MPEG Audio Layer (MP1/MP2/MP3). */ + long rate; /**< The sampling rate in Hz. */ + enum mpg123_mode mode; /**< The audio mode (Mono, Stereo, Joint-stero, Dual Channel). */ + int mode_ext; /**< The mode extension bit flag. */ + int framesize; /**< The size of the frame (in bytes, including header). */ + enum mpg123_flags flags; /**< MPEG Audio flag bits. Just now I realize that it should be declared as int, not enum. It's a bitwise combination of the enum values. */ + int emphasis; /**< The emphasis type. */ + int bitrate; /**< Bitrate of the frame (kbps). */ + int abr_rate; /**< The target average bitrate. */ + enum mpg123_vbr vbr; /**< The VBR mode. */ +}; + +/** Data structure for even more detailed information out of the decoder, + * for MPEG layer III only. + * This was added to support the frame analyzer by the Lame project and + * just follows what was used there before. You know what the fields mean + * if you want use this structure. */ +struct mpg123_moreinfo +{ + double xr[2][2][576]; + double sfb[2][2][22]; /* [2][2][SBMAX_l] */ + double sfb_s[2][2][3*13]; /* [2][2][3*SBMAX_s] */ + int qss[2][2]; + int big_values[2][2]; + int sub_gain[2][2][3]; + int scalefac_scale[2][2]; + int preflag[2][2]; + int blocktype[2][2]; + int mixed[2][2]; + int mainbits[2][2]; + int sfbits[2][2]; + int scfsi[2]; + int maindata; + int padding; +}; + +/** Get frame information about the MPEG audio bitstream and store it in a mpg123_frameinfo structure. + * \param mh handle + * \param mi address of existing frameinfo structure to write to + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi); + +/** Trigger collection of additional decoder information while decoding. + * \param mh handle + * \param mi pointer to data storage (NULL to disable collection) + * \return MPG123_OK if the collection was enabled/disabled as desired, MPG123_ERR + * otherwise (e.g. if the feature is disabled) + */ +MPG123_EXPORT int mpg123_set_moreinfo( mpg123_handle *mh +, struct mpg123_moreinfo *mi ); + +/** Get the safe output buffer size for all cases + * (when you want to replace the internal buffer) + * \return safe buffer size + */ +MPG123_EXPORT size_t mpg123_safe_buffer(void); + +/** Make a full parsing scan of each frame in the file. ID3 tags are found. An + * accurate length value is stored. Seek index will be filled. A seek back to + * current position is performed. At all, this function refuses work when + * stream is not seekable. + * \param mh handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_scan(mpg123_handle *mh); + +/** Return, if possible, the full (expected) length of current track in + * MPEG frames. + * \param mh handle + * \return length >= 0 or MPG123_ERR if there is no length guess possible. + */ +MPG123_EXPORT off_t mpg123_framelength(mpg123_handle *mh); + +/** Return, if possible, the full (expected) length of current + * track in samples (PCM frames). + * + * This relies either on an Info frame at the beginning or a previous + * call to mpg123_scan() to get the real number of MPEG frames in a + * file. It will guess based on file size if neither Info frame nor + * scan data are present. In any case, there is no guarantee that the + * decoder will not give you more data, for example in case the open + * file gets appended to during decoding. + * \param mh handle + * \return length >= 0 or MPG123_ERR if there is no length guess possible. + */ +MPG123_EXPORT off_t mpg123_length(mpg123_handle *mh); + +/** Override the value for file size in bytes. + * Useful for getting sensible track length values in feed mode or for HTTP streams. + * \param mh handle + * \param size file size in bytes + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_set_filesize(mpg123_handle *mh, off_t size); + +/** Get MPEG frame duration in seconds. + * \param mh handle + * \return frame duration in seconds, <0 on error + */ +MPG123_EXPORT double mpg123_tpf(mpg123_handle *mh); + +/** Get MPEG frame duration in samples. + * \param mh handle + * \return samples per frame for the most recently parsed frame; <0 on errors + */ +MPG123_EXPORT int mpg123_spf(mpg123_handle *mh); + +/** Get and reset the clip count. + * \param mh handle + * \return count of clipped samples + */ +MPG123_EXPORT long mpg123_clip(mpg123_handle *mh); + + +/** The key values for state information from mpg123_getstate(). */ +enum mpg123_state +{ + MPG123_ACCURATE = 1 /**< Query if positons are currently accurate (integer value, 0 if false, 1 if true). */ + ,MPG123_BUFFERFILL /**< Get fill of internal (feed) input buffer as integer byte count returned as long and as double. An error is returned on integer overflow while converting to (signed) long, but the returned floating point value shold still be fine. */ + ,MPG123_FRANKENSTEIN /**< Stream consists of carelessly stitched together files. Seeking may yield unexpected results (also with MPG123_ACCURATE, it may be confused). */ + ,MPG123_FRESH_DECODER /**< Decoder structure has been updated, possibly indicating changed stream (integer value, 0 if false, 1 if true). Flag is cleared after retrieval. */ + ,MPG123_ENC_DELAY /** Encoder delay read from Info tag (layer III, -1 if unknown). */ + ,MPG123_ENC_PADDING /** Encoder padding read from Info tag (layer III, -1 if unknown). */ + ,MPG123_DEC_DELAY /** Decoder delay (for layer III only, -1 otherwise). */ +}; + +/** Get various current decoder/stream state information. + * \param mh handle + * \param key the key to identify the information to give. + * \param val the address to return (long) integer values to + * \param fval the address to return floating point values to + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getstate( mpg123_handle *mh +, enum mpg123_state key, long *val, double *fval ); + +/*@}*/ + + +/** \defgroup mpg123_metadata mpg123 metadata handling + * + * Functions to retrieve the metadata from MPEG Audio files and streams. + * Also includes string handling functions. + * + * @{ + */ + +/** Data structure for storing strings in a safer way than a standard C-String. + * Can also hold a number of null-terminated strings. */ +typedef struct +{ + char* p; /**< pointer to the string data */ + size_t size; /**< raw number of bytes allocated */ + size_t fill; /**< number of used bytes (including closing zero byte) */ +} mpg123_string; + +/** Allocate and intialize a new string. + * \param val optional initial string value (can be NULL) + */ +MPG123_EXPORT mpg123_string* mpg123_new_string(const char* val); + +/** Free memory of contents and the string structure itself. + * \param sb string handle + */ +MPG123_EXPORT void mpg123_delete_string(mpg123_string* sb); + +/** Initialize an existing mpg123_string structure to {NULL, 0, 0}. + * If you hand in a NULL pointer here, your program should crash. The other + * string functions are more forgiving, but this one here is too basic. + * \param sb string handle (address of existing structure on your side) + */ +MPG123_EXPORT void mpg123_init_string(mpg123_string* sb); + +/** Free-up memory of the contents of an mpg123_string (not the struct itself). + * This also calls mpg123_init_string() and hence is safe to be called + * repeatedly. + * \param sb string handle + */ +MPG123_EXPORT void mpg123_free_string(mpg123_string* sb); + +/** Change the size of a mpg123_string + * \param sb string handle + * \param news new size in bytes + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_resize_string(mpg123_string* sb, size_t news); + +/** Increase size of a mpg123_string if necessary (it may stay larger). + * Note that the functions for adding and setting in current libmpg123 + * use this instead of mpg123_resize_string(). + * That way, you can preallocate memory and safely work afterwards with + * pieces. + * \param sb string handle + * \param news new minimum size + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_grow_string(mpg123_string* sb, size_t news); + +/** Copy the contents of one mpg123_string string to another. + * Yes the order of arguments is reversed compated to memcpy(). + * \param from string handle + * \param to string handle + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_copy_string(mpg123_string* from, mpg123_string* to); + +/** Move the contents of one mpg123_string string to another. + * This frees any memory associated with the target and moves over the + * pointers from the source, leaving the source without content after + * that. The only possible error is that you hand in NULL pointers. + * If you handed in a valid source, its contents will be gone, even if + * there was no target to move to. If you hand in a valid target, its + * original contents will also always be gone, to be replaced with the + * source's contents if there was some. + * \param from source string handle + * \param to target string handle + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_move_string(mpg123_string* from, mpg123_string* to); + +/** Append a C-String to an mpg123_string + * \param sb string handle + * \param stuff to append + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_add_string(mpg123_string* sb, const char* stuff); + +/** Append a C-substring to an mpg123 string + * \param sb string handle + * \param stuff content to copy + * \param from offset to copy from + * \param count number of characters to copy (a null-byte is always appended) + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_add_substring( mpg123_string *sb +, const char *stuff, size_t from, size_t count ); + +/** Set the content of a mpg123_string to a C-string + * \param sb string handle + * \param stuff content to copy + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_set_string(mpg123_string* sb, const char* stuff); + +/** Set the content of a mpg123_string to a C-substring + * \param sb string handle + * \param stuff the future content + * \param from offset to copy from + * \param count number of characters to copy (a null-byte is always appended) + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_set_substring( mpg123_string *sb +, const char *stuff, size_t from, size_t count ); + +/** Count characters in a mpg123 string (non-null bytes or Unicode points). + * This function is of limited use, as it does just count code points + * encoded in an UTF-8 string, only loosely related to the count of visible + * characters. Get your full Unicode handling support elsewhere. + * \param sb string handle + * \param utf8 a flag to tell if the string is in utf8 encoding + * \return character count +*/ +MPG123_EXPORT size_t mpg123_strlen(mpg123_string *sb, int utf8); + +/** Remove trailing \\r and \\n, if present. + * \param sb string handle + * \return 0 on error, 1 on success + */ +MPG123_EXPORT int mpg123_chomp_string(mpg123_string *sb); + +/** Determine if two strings contain the same data. + * This only returns 1 if both given handles are non-NULL and + * if they are filled with the same bytes. + * \param a first string handle + * \param b second string handle + * \return 0 for different strings, 1 for identical + */ +MPG123_EXPORT int mpg123_same_string(mpg123_string *a, mpg123_string *b); + +/** The mpg123 text encodings. This contains encodings we encounter in ID3 tags or ICY meta info. */ +enum mpg123_text_encoding +{ + mpg123_text_unknown = 0 /**< Unkown encoding... mpg123_id3_encoding can return that on invalid codes. */ + ,mpg123_text_utf8 = 1 /**< UTF-8 */ + ,mpg123_text_latin1 = 2 /**< ISO-8859-1. Note that sometimes latin1 in ID3 is abused for totally different encodings. */ + ,mpg123_text_icy = 3 /**< ICY metadata encoding, usually CP-1252 but we take it as UTF-8 if it qualifies as such. */ + ,mpg123_text_cp1252 = 4 /**< Really CP-1252 without any guessing. */ + ,mpg123_text_utf16 = 5 /**< Some UTF-16 encoding. The last of a set of leading BOMs (byte order mark) rules. + * When there is no BOM, big endian ordering is used. Note that UCS-2 qualifies as UTF-8 when + * you don't mess with the reserved code points. If you want to decode little endian data + * without BOM you need to prepend 0xff 0xfe yourself. */ + ,mpg123_text_utf16bom = 6 /**< Just an alias for UTF-16, ID3v2 has this as distinct code. */ + ,mpg123_text_utf16be = 7 /**< Another alias for UTF16 from ID3v2. Note, that, because of the mess that is reality, + * BOMs are used if encountered. There really is not much distinction between the UTF16 types for mpg123 + * One exception: Since this is seen in ID3v2 tags, leading null bytes are skipped for all other UTF16 + * types (we expect a BOM before real data there), not so for utf16be!*/ + ,mpg123_text_max = 7 /**< Placeholder for the maximum encoding value. */ +}; + +/** The encoding byte values from ID3v2. */ +enum mpg123_id3_enc +{ + mpg123_id3_latin1 = 0 /**< Note: This sometimes can mean anything in practice... */ + ,mpg123_id3_utf16bom = 1 /**< UTF16, UCS-2 ... it's all the same for practical purposes. */ + ,mpg123_id3_utf16be = 2 /**< Big-endian UTF-16, BOM see note for mpg123_text_utf16be. */ + ,mpg123_id3_utf8 = 3 /**< Our lovely overly ASCII-compatible 8 byte encoding for the world. */ + ,mpg123_id3_enc_max = 3 /**< Placeholder to check valid range of encoding byte. */ +}; + +/** Convert ID3 encoding byte to mpg123 encoding index. + * \param id3_enc_byte the ID3 encoding code + * \return the mpg123 encoding index + */ + +MPG123_EXPORT enum mpg123_text_encoding mpg123_enc_from_id3(unsigned char id3_enc_byte); + +/** Store text data in string, after converting to UTF-8 from indicated encoding + * A prominent error can be that you provided an unknown encoding value, or this build of libmpg123 lacks support for certain encodings (ID3 or ICY stuff missing). + * Also, you might want to take a bit of care with preparing the data; for example, strip leading zeroes (I have seen that). + * \param sb target string + * \param enc mpg123 text encoding value + * \param source source buffer with plain unsigned bytes (you might need to cast from signed char) + * \param source_size number of bytes in the source buffer + * \return 0 on error, 1 on success (on error, mpg123_free_string is called on sb) + */ +MPG123_EXPORT int mpg123_store_utf8(mpg123_string *sb, enum mpg123_text_encoding enc, const unsigned char *source, size_t source_size); + +/** Sub data structure for ID3v2, for storing various text fields (including comments). + * This is for ID3v2 COMM, TXXX and all the other text fields. + * Only COMM, TXXX and USLT may have a description, only COMM and USLT + * have a language. + * You should consult the ID3v2 specification for the use of the various text fields + * ("frames" in ID3v2 documentation, I use "fields" here to separate from MPEG frames). */ +typedef struct +{ + char lang[3]; /**< Three-letter language code (not terminated). */ + char id[4]; /**< The ID3v2 text field id, like TALB, TPE2, ... (4 characters, no string termination). */ + mpg123_string description; /**< Empty for the generic comment... */ + mpg123_string text; /**< ... */ +} mpg123_text; + +/** The picture type values from ID3v2. */ +enum mpg123_id3_pic_type +{ + mpg123_id3_pic_other = 0 /**< see ID3v2 docs */ + ,mpg123_id3_pic_icon = 1 /**< see ID3v2 docs */ + ,mpg123_id3_pic_other_icon = 2 /**< see ID3v2 docs */ + ,mpg123_id3_pic_front_cover = 3 /**< see ID3v2 docs */ + ,mpg123_id3_pic_back_cover = 4 /**< see ID3v2 docs */ + ,mpg123_id3_pic_leaflet = 5 /**< see ID3v2 docs */ + ,mpg123_id3_pic_media = 6 /**< see ID3v2 docs */ + ,mpg123_id3_pic_lead = 7 /**< see ID3v2 docs */ + ,mpg123_id3_pic_artist = 8 /**< see ID3v2 docs */ + ,mpg123_id3_pic_conductor = 9 /**< see ID3v2 docs */ + ,mpg123_id3_pic_orchestra = 10 /**< see ID3v2 docs */ + ,mpg123_id3_pic_composer = 11 /**< see ID3v2 docs */ + ,mpg123_id3_pic_lyricist = 12 /**< see ID3v2 docs */ + ,mpg123_id3_pic_location = 13 /**< see ID3v2 docs */ + ,mpg123_id3_pic_recording = 14 /**< see ID3v2 docs */ + ,mpg123_id3_pic_performance = 15 /**< see ID3v2 docs */ + ,mpg123_id3_pic_video = 16 /**< see ID3v2 docs */ + ,mpg123_id3_pic_fish = 17 /**< see ID3v2 docs */ + ,mpg123_id3_pic_illustration = 18 /**< see ID3v2 docs */ + ,mpg123_id3_pic_artist_logo = 19 /**< see ID3v2 docs */ + ,mpg123_id3_pic_publisher_logo = 20 /**< see ID3v2 docs */ +}; + +/** Sub data structure for ID3v2, for storing picture data including comment. + * This is for the ID3v2 APIC field. You should consult the ID3v2 specification + * for the use of the APIC field ("frames" in ID3v2 documentation, I use "fields" + * here to separate from MPEG frames). */ +typedef struct +{ + char type; /**< mpg123_id3_pic_type value */ + mpg123_string description; /**< description string */ + mpg123_string mime_type; /**< MIME type */ + size_t size; /**< size in bytes */ + unsigned char* data; /**< pointer to the image data */ +} mpg123_picture; + +/** Data structure for storing IDV3v2 tags. + * This structure is not a direct binary mapping with the file contents. + * The ID3v2 text frames are allowed to contain multiple strings. + * So check for null bytes until you reach the mpg123_string fill. + * All text is encoded in UTF-8. */ +typedef struct +{ + unsigned char version; /**< 3 or 4 for ID3v2.3 or ID3v2.4. */ + mpg123_string *title; /**< Title string (pointer into text_list). */ + mpg123_string *artist; /**< Artist string (pointer into text_list). */ + mpg123_string *album; /**< Album string (pointer into text_list). */ + mpg123_string *year; /**< The year as a string (pointer into text_list). */ + mpg123_string *genre; /**< Genre String (pointer into text_list). The genre string(s) may very well need postprocessing, esp. for ID3v2.3. */ + mpg123_string *comment; /**< Pointer to last encountered comment text with empty description. */ + /* Encountered ID3v2 fields are appended to these lists. + There can be multiple occurences, the pointers above always point to the last encountered data. */ + mpg123_text *comment_list; /**< Array of comments. */ + size_t comments; /**< Number of comments. */ + mpg123_text *text; /**< Array of ID3v2 text fields (including USLT) */ + size_t texts; /**< Numer of text fields. */ + mpg123_text *extra; /**< The array of extra (TXXX) fields. */ + size_t extras; /**< Number of extra text (TXXX) fields. */ + mpg123_picture *picture; /**< Array of ID3v2 pictures fields (APIC). + Only populated if MPG123_PICTURE flag is set! */ + size_t pictures; /**< Number of picture (APIC) fields. */ +} mpg123_id3v2; + +/** Data structure for ID3v1 tags (the last 128 bytes of a file). + * Don't take anything for granted (like string termination)! + * Also note the change ID3v1.1 did: comment[28] = 0; comment[29] = track_number + * It is your task to support ID3v1 only or ID3v1.1 ...*/ +typedef struct +{ + char tag[3]; /**< Always the string "TAG", the classic intro. */ + char title[30]; /**< Title string. */ + char artist[30]; /**< Artist string. */ + char album[30]; /**< Album string. */ + char year[4]; /**< Year string. */ + char comment[30]; /**< Comment string. */ + unsigned char genre; /**< Genre index. */ +} mpg123_id3v1; + +#define MPG123_ID3 0x3 /**< 0011 There is some ID3 info. Also matches 0010 or NEW_ID3. */ +#define MPG123_NEW_ID3 0x1 /**< 0001 There is ID3 info that changed since last call to mpg123_id3. */ +#define MPG123_ICY 0xc /**< 1100 There is some ICY info. Also matches 0100 or NEW_ICY.*/ +#define MPG123_NEW_ICY 0x4 /**< 0100 There is ICY info that changed since last call to mpg123_icy. */ + +/** Query if there is (new) meta info, be it ID3 or ICY (or something new in future). + * \param mh handle + * \return combination of flags, 0 on error (same as "nothing new") + */ +MPG123_EXPORT int mpg123_meta_check(mpg123_handle *mh); + +/** Clean up meta data storage (ID3v2 and ICY), freeing memory. + * \param mh handle + */ +MPG123_EXPORT void mpg123_meta_free(mpg123_handle *mh); + +/** Point v1 and v2 to existing data structures wich may change on any next read/decode function call. + * v1 and/or v2 can be set to NULL when there is no corresponding data. + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_id3( mpg123_handle *mh +, mpg123_id3v1 **v1, mpg123_id3v2 **v2 ); + +/** Return pointers to and size of stored raw ID3 data if storage has + * been configured with MPG123_RAW_ID3 and stream parsing passed the + * metadata already. Null value with zero size is a possibility! + * The storage can change at any next API call. + * \param v1 address to store pointer to v1 tag + * \param v1_size size of v1 data in bytes + * \param v2 address to store pointer to v2 tag + * \param v2_size size of v2 data in bytes + * \return MPG123_OK or MPG123_ERR. Only on MPG123_OK the output + * values are set. + */ +MPG123_EXPORT int mpg123_id3_raw( mpg123_handle *mh +, unsigned char **v1, size_t *v1_size +, unsigned char **v2, size_t *v2_size ); + +/** Point icy_meta to existing data structure wich may change on any next read/decode function call. + * \param mh handle + * \param icy_meta return address for ICY meta string (set to NULL if nothing there) + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_icy(mpg123_handle *mh, char **icy_meta); + +/** Decode from windows-1252 (the encoding ICY metainfo used) to UTF-8. + * Note that this is very similar to mpg123_store_utf8(&sb, mpg123_text_icy, icy_text, strlen(icy_text+1)) . + * \param icy_text The input data in ICY encoding + * \return pointer to newly allocated buffer with UTF-8 data (You free() it!) */ +MPG123_EXPORT char* mpg123_icy2utf8(const char* icy_text); + + +/* @} */ + + +/** \defgroup mpg123_advpar mpg123 advanced parameter API + * + * Direct access to a parameter set without full handle around it. + * Possible uses: + * - Influence behaviour of library _during_ initialization of handle (MPG123_VERBOSE). + * - Use one set of parameters for multiple handles. + * + * The functions for handling mpg123_pars (mpg123_par() and mpg123_fmt() + * family) directly return a fully qualified mpg123 error code, the ones + * operating on full handles normally MPG123_OK or MPG123_ERR, storing the + * specific error code itseld inside the handle. + * + * @{ + */ + +/** Opaque structure for the libmpg123 decoder parameters. */ +struct mpg123_pars_struct; + +/** Opaque structure for the libmpg123 decoder parameters. */ +typedef struct mpg123_pars_struct mpg123_pars; + +/** Create a handle with preset parameters. + * \param mp parameter handle + * \param decoder decoder choice + * \param error error code return address + * \return mpg123 handle + */ +MPG123_EXPORT mpg123_handle *mpg123_parnew( mpg123_pars *mp +, const char* decoder, int *error ); + +/** Allocate memory for and return a pointer to a new mpg123_pars + * \param error error code return address + * \return new parameter handle + */ +MPG123_EXPORT mpg123_pars *mpg123_new_pars(int *error); + +/** Delete and free up memory used by a mpg123_pars data structure + * \param mp parameter handle + */ +MPG123_EXPORT void mpg123_delete_pars(mpg123_pars* mp); + +/** Configure mpg123 parameters to accept no output format at all, + * use before specifying supported formats with mpg123_format + * \param mp parameter handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_fmt_none(mpg123_pars *mp); + +/** Configure mpg123 parameters to accept all formats + * (also any custom rate you may set) -- this is default. + * \param mp parameter handle + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_fmt_all(mpg123_pars *mp); + +/** Set the audio format support of a mpg123_pars in detail: + * \param mp parameter handle + * \param rate The sample rate value (in Hertz). + * \param channels A combination of MPG123_STEREO and MPG123_MONO. + * \param encodings A combination of accepted encodings for rate and channels, + * p.ex MPG123_ENC_SIGNED16|MPG123_ENC_ULAW_8 (or 0 for no + * support). + * \return MPG123_OK on success +*/ +MPG123_EXPORT int mpg123_fmt(mpg123_pars *mp +, long rate, int channels, int encodings); + +/** Set the audio format support of a mpg123_pars in detail: + * \param mp parameter handle + * \param rate The sample rate value (in Hertz). Special value 0 means + * all rates (reason for this variant of mpg123_fmt). + * \param channels A combination of MPG123_STEREO and MPG123_MONO. + * \param encodings A combination of accepted encodings for rate and channels, + * p.ex MPG123_ENC_SIGNED16|MPG123_ENC_ULAW_8 (or 0 for no + * support). + * \return MPG123_OK on success +*/ +MPG123_EXPORT int mpg123_fmt2(mpg123_pars *mp +, long rate, int channels, int encodings); + +/** Check to see if a specific format at a specific rate is supported + * by mpg123_pars. + * \param mp parameter handle + * \param rate sampling rate + * \param encoding encoding + * \return 0 for no support (that includes invalid parameters), MPG123_STEREO, + * MPG123_MONO or MPG123_STEREO|MPG123_MONO. */ +MPG123_EXPORT int mpg123_fmt_support(mpg123_pars *mp, long rate, int encoding); + +/** Set a specific parameter, for a specific mpg123_pars, using a parameter + * type key chosen from the mpg123_parms enumeration, to the specified value. + * \param mp parameter handle + * \param type parameter choice + * \param value integer value + * \param fvalue floating point value + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_par( mpg123_pars *mp +, enum mpg123_parms type, long value, double fvalue ); + +/** Get a specific parameter, for a specific mpg123_pars. + * See the mpg123_parms enumeration for a list of available parameters. + * \param mp parameter handle + * \param type parameter choice + * \param value integer value return address + * \param fvalue floating point value return address + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_getpar( mpg123_pars *mp +, enum mpg123_parms type, long *value, double *fvalue); + +/* @} */ + + +/** \defgroup mpg123_lowio mpg123 low level I/O + * You may want to do tricky stuff with I/O that does not work with mpg123's default file access or you want to make it decode into your own pocket... + * + * @{ */ + +/** Replace default internal buffer with user-supplied buffer. + * Instead of working on it's own private buffer, mpg123 will directly use the one you provide for storing decoded audio. + * Note that the required buffer size could be bigger than expected from output + * encoding if libmpg123 has to convert from primary decoder output (p.ex. 32 bit + * storage for 24 bit output). + * + * Note: The type of data changed to a void pointer in mpg123 1.26.0 + * (API version 45). + * + * \param mh handle + * \param data pointer to user buffer + * \param size of buffer in bytes + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_replace_buffer(mpg123_handle *mh +, void *data, size_t size); + +/** The max size of one frame's decoded output with current settings. + * Use that to determine an appropriate minimum buffer size for decoding one frame. + * \param mh handle + * \return maximum decoded data size in bytes + */ +MPG123_EXPORT size_t mpg123_outblock(mpg123_handle *mh); + +/** Replace low-level stream access functions; read and lseek as known in POSIX. + * You can use this to make any fancy file opening/closing yourself, + * using mpg123_open_fd() to set the file descriptor for your read/lseek + * (doesn't need to be a "real" file descriptor...). + * Setting a function to NULL means that the default internal read is + * used (active from next mpg123_open call on). + * Note: As it would be troublesome to mess with this while having a file open, + * this implies mpg123_close(). + * \param mh handle + * \param r_read callback for reading (behaviour like POSIX read) + * \param r_lseek callback for seeking (like POSIX lseek) + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_replace_reader( mpg123_handle *mh +, ssize_t (*r_read) (int, void *, size_t) +, off_t (*r_lseek)(int, off_t, int) +); + +/** Replace I/O functions with your own ones operating on some kind of + * handle instead of integer descriptors. + * The handle is a void pointer, so you can pass any data you want... + * mpg123_open_handle() is the call you make to use the I/O defined here. + * There is no fallback to internal read/seek here. + * Note: As it would be troublesome to mess with this while having a file open, + * this mpg123_close() is implied here. + * \param mh handle + * \param r_read callback for reading (behaviour like POSIX read) + * \param r_lseek callback for seeking (like POSIX lseek) + * \param cleanup A callback to clean up an I/O handle on mpg123_close, + * can be NULL for none (you take care of cleaning your handles). + * \return MPG123_OK on success + */ +MPG123_EXPORT int mpg123_replace_reader_handle( mpg123_handle *mh +, ssize_t (*r_read) (void *, void *, size_t) +, off_t (*r_lseek)(void *, off_t, int) +, void (*cleanup)(void*) ); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpg123.64/lib/libmpg123.lib b/mpg123.64/lib/libmpg123.lib new file mode 100644 index 0000000000000000000000000000000000000000..0b778c2b1b51b8c16575960e6eb5c073105756be GIT binary patch literal 33342 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 literal 0 HcmV?d00001 diff --git a/premake5.lua b/premake5.lua index 03610a03..cdf1819e 100644 --- a/premake5.lua +++ b/premake5.lua @@ -6,10 +6,17 @@ newoption { } newoption { - trigger = "glfwdir", + trigger = "glfwdir64", value = "PATH", description = "Directory of glfw", - default = "glfw-3.3.2.bin.WIN32" + default = "glfw-3.3.2.bin.WIN64", +} + +newoption { + trigger = "glfwdir32", + value = "PATH", + description = "Directory of glfw", + default = "glfw-3.3.2.bin.WIN32", } newoption { @@ -54,6 +61,8 @@ workspace "reVC" "win-x86-RW34_d3d8-oal", "win-x86-librw_d3d9-oal", "win-x86-librw_gl3_glfw-oal", + "win-amd64-librw_d3d9-oal", + "win-amd64-librw_gl3_glfw-oal", } filter { "system:linux" } @@ -88,16 +97,21 @@ workspace "reVC" filter { "platforms:*librw_d3d9*" } defines { "RW_D3D9" } if(not _OPTIONS["with-librw"]) then - libdirs { path.join(Librw, "lib/win-x86-d3d9/%{cfg.buildcfg}") } + libdirs { path.join(Librw, "lib/win-%{getarch(cfg.architecture)}-d3d9/%{cfg.buildcfg}") } end filter "platforms:*librw_gl3_glfw*" defines { "RW_GL3" } - includedirs { path.join(_OPTIONS["glfwdir"], "include") } includedirs { path.join(_OPTIONS["glewdir"], "include") } if(not _OPTIONS["with-librw"]) then libdirs { path.join(Librw, "lib/%{getsys(cfg.system)}-%{getarch(cfg.architecture)}-gl3/%{cfg.buildcfg}") } end + + filter "platforms:*x86-librw_gl3_glfw*" + includedirs { path.join(_OPTIONS["glfwdir32"], "include") } + + filter "platforms:*amd64-librw_gl3_glfw*" + includedirs { path.join(_OPTIONS["glfwdir64"], "include") } filter "platforms:win*librw_gl3_glfw*" defines { "GLEW_STATIC" } @@ -206,14 +220,22 @@ project "reVC" linkoptions "/SAFESEH:NO" characterset ("MBCS") targetextension ".exe" - - filter "platforms:win*oal" + + filter "platforms:win-x86*oal" includedirs { "openal-soft/include" } - includedirs { "libsndfile/include" } - includedirs { "mpg123/include" } + includedirs { "libsndfile.32/include" } + includedirs { "mpg123.32/include" } + libdirs { "mpg123.32/lib" } + libdirs { "libsndfile32/lib" } libdirs { "openal-soft/libs/Win32" } - libdirs { "libsndfile/lib" } - libdirs { "mpg123/lib" } + + filter "platforms:win-amd64*oal" + includedirs { "openal-soft/include" } + includedirs { "libsndfile.64/include" } + includedirs { "mpg123.64/include" } + libdirs { "mpg123.64/lib" } + libdirs { "libsndfile.64/lib" } + libdirs { "openal-soft/libs/Win64" } filter "platforms:linux*oal" links { "openal", "mpg123", "sndfile", "pthread" } @@ -236,16 +258,24 @@ project "reVC" end links { "rw" } - filter "platforms:*d3d*" - includedirs { "dxsdk/include" } - libdirs { "dxsdk/lib" } - filter "platforms:*d3d9*" links { "d3d9" } - filter "platforms:win*gl3_glfw*" + filter "platforms:*x86*d3d*" + includedirs { "dxsdk/include" } + libdirs { "dxsdk/lib" } + + filter "platforms:*amd64*d3d9*" + defines { "USE_D3D9" } + + filter "platforms:win-x86*gl3_glfw*" libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/Win32") } - libdirs { path.join(_OPTIONS["glfwdir"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) } + libdirs { path.join(_OPTIONS["glfwdir32"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) } + links { "opengl32", "glew32s", "glfw3" } + + filter "platforms:win-amd64*gl3_glfw*" + libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/x64") } + libdirs { path.join(_OPTIONS["glfwdir64"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) } links { "opengl32", "glew32s", "glfw3" } filter "platforms:linux*gl3_glfw*" diff --git a/src/audio/oal/aldlist.cpp b/src/audio/oal/aldlist.cpp index 3e86b1d7..881418c1 100644 --- a/src/audio/oal/aldlist.cpp +++ b/src/audio/oal/aldlist.cpp @@ -27,6 +27,7 @@ #ifndef _WIN32 #define _stricmp strcasecmp #define _strnicmp strncasecmp +#define _strdup strdup #endif #ifdef AUDIO_OAL @@ -71,7 +72,7 @@ ALDeviceList::ALDeviceList() if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) { ALDEVICEINFO ALDeviceInfo; ALDeviceInfo.bSelected = true; - ALDeviceInfo.strDeviceName = actualDeviceName; + ALDeviceInfo.strDeviceName = _strdup(actualDeviceName); alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion); alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion); diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 0378c07c..40ec57fa 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -5,7 +5,11 @@ #include "sampman.h" #ifdef _WIN32 + +// TODO: This is due to version difference of 32-bit libmpg123 and 64-bit libmpg123, fix it +#ifndef _WIN64 typedef long ssize_t; +#endif #pragma comment( lib, "libsndfile-1.lib" ) #pragma comment( lib, "libmpg123.lib" ) #else @@ -173,8 +177,11 @@ public: size_t size; int err = mpg123_read(m_pMH, (unsigned char *)buffer, GetBufferSize(), &size); +#if defined(__LP64__) || defined(_WIN64) + assert("We can't handle audio files more then 2 GB yet :shrug:" && (size < UINT32_MAX)); +#endif if (err != MPG123_OK && err != MPG123_DONE) return 0; - return size; + return (uint32)size; } }; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 8b34cc3b..1a050bee 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1483,7 +1483,7 @@ void CReplay::StreamAllNecessaryCarsAndPeds(void) for (int slot = 0; slot < NUM_REPLAYBUFFERS; slot++) { if (BufferStatus[slot] == REPLAYBUFFER_UNUSED) continue; - for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { + for (size_t offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { switch (Buffers[slot][offset]) { case REPLAYPACKET_VEHICLE: CStreaming::RequestModel(((tVehicleUpdatePacket*)&Buffers[slot][offset])->mi, 0); @@ -1505,7 +1505,7 @@ void CReplay::FindFirstFocusCoordinate(CVector *coord) for (int slot = 0; slot < NUM_REPLAYBUFFERS; slot++) { if (BufferStatus[slot] == REPLAYBUFFER_UNUSED) continue; - for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { + for (size_t offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { if (Buffers[slot][offset] == REPLAYPACKET_GENERAL) { *coord = ((tGeneralPacket*)&Buffers[slot][offset])->player_pos; return; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index eeb8630a..9f3646e2 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -3376,15 +3376,15 @@ CCamera::LoadTrainCamNodes(char const *name) char token[16] = { 0 }; char filename[16] = { 0 }; uint8 *buf; - int bufpos = 0; + size_t bufpos = 0; int field = 0; int tokpos = 0; char c; int i; - int len; + size_t len; strcpy(filename, name); - len = strlen(filename); + len = (int)strlen(filename); filename[len] = '.'; filename[len+1] = 'd'; filename[len+2] = 'a'; diff --git a/src/core/Directory.cpp b/src/core/Directory.cpp index cc4d65d8..05344065 100644 --- a/src/core/Directory.cpp +++ b/src/core/Directory.cpp @@ -30,7 +30,8 @@ CDirectory::ReadDirFile(const char *filename) bool CDirectory::WriteDirFile(const char *filename) { - int fd, n; + int fd; + size_t n; fd = CFileMgr::OpenFileForWriting(filename); n = CFileMgr::Write(fd, (char*)entries, numEntries*sizeof(DirectoryInfo)); CFileMgr::CloseFile(fd); diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp index 4fab29bc..e5f264c7 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -189,7 +189,7 @@ CEventList::FindClosestEvent(eEventType type, CVector posn, int32 *event) // --MIAMI: Done void -CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCare) +CEventList::ReportCrimeForEvent(eEventType type, size_t crimeId, bool copsDontCare) { eCrimeType crime; switch(type){ @@ -227,10 +227,10 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar if(CWanted::WorkOutPolicePresence(playerCoors, 14.0f) != 0 || CGame::germanGame && (crime == CRIME_SHOOT_PED || crime == CRIME_SHOOT_COP || crime == CRIME_COP_BURNED || crime == CRIME_VEHICLE_BURNED)){ - FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, crimeId, copsDontCare); + FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, (uint32)crimeId, copsDontCare); FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1); }else - FindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, crimeId, copsDontCare); + FindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, (uint32)crimeId, copsDontCare); if(type == EVENT_ASSAULT_POLICE) FindPlayerPed()->SetWantedLevelNoDrop(1); diff --git a/src/core/EventList.h b/src/core/EventList.h index f2c3d7a8..0531aed7 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -61,7 +61,7 @@ public: static bool GetEvent(eEventType type, int32 *event); static void ClearEvent(int32 event); static bool FindClosestEvent(eEventType type, CVector posn, int32 *event); - static void ReportCrimeForEvent(eEventType type, int32, bool); + static void ReportCrimeForEvent(eEventType type, size_t, bool); }; extern CEvent gaEvent[NUMEVENTS]; \ No newline at end of file diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index 1939c861..cdcb80f0 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -163,7 +163,7 @@ myfgets(char *buf, int len, int fd) return buf; } -static int +static size_t myfread(void *buf, size_t elt, size_t n, int fd) { if(myfiles[fd].isText){ @@ -184,7 +184,7 @@ myfread(void *buf, size_t elt, size_t n, int fd) return fread(buf, elt, n, myfiles[fd].file); } -static int +static size_t myfwrite(void *buf, size_t elt, size_t n, int fd) { if(myfiles[fd].isText){ @@ -265,11 +265,11 @@ CFileMgr::SetDirMyDocuments(void) mychdir(_psGetUserFilesFolder()); } -int +size_t CFileMgr::LoadFile(const char *file, uint8 *buf, int unused, const char *mode) { int fd; - int n, len; + size_t n, len; fd = myfopen(file, mode); if(fd == 0) @@ -298,14 +298,14 @@ CFileMgr::OpenFileForWriting(const char *file) return OpenFile(file, "wb"); } -int -CFileMgr::Read(int fd, const char *buf, int len) +size_t +CFileMgr::Read(int fd, const char *buf, size_t len) { return myfread((void*)buf, 1, len, fd); } -int -CFileMgr::Write(int fd, const char *buf, int len) +size_t +CFileMgr::Write(int fd, const char *buf, size_t len) { return myfwrite((void*)buf, 1, len, fd); } diff --git a/src/core/FileMgr.h b/src/core/FileMgr.h index 1d0faf50..51e30694 100644 --- a/src/core/FileMgr.h +++ b/src/core/FileMgr.h @@ -9,12 +9,12 @@ public: static void ChangeDir(const char *dir); static void SetDir(const char *dir); static void SetDirMyDocuments(void); - static int LoadFile(const char *file, uint8 *buf, int unused, const char *mode); + static size_t LoadFile(const char *file, uint8 *buf, int unused, const char *mode); static int OpenFile(const char *file, const char *mode); static int OpenFile(const char *file) { return OpenFile(file, "rb"); } static int OpenFileForWriting(const char *file); - static int Read(int fd, const char *buf, int len); - static int Write(int fd, const char *buf, int len); + static size_t Read(int fd, const char *buf, size_t len); + static size_t Write(int fd, const char *buf, size_t len); static bool Seek(int fd, int offset, int whence); static bool ReadLine(int fd, char *buf, int len); static int CloseFile(int fd); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index a3b15ac1..e5776459 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -2653,7 +2653,7 @@ CMenuManager::DrawPlayerSetupScreen() char nameTemp[256]; for (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin; m_pSelectedSkin = m_pSelectedSkin->nextSkin) { // Drop extension - int oldLength = strlen(m_pSelectedSkin->skinNameDisplayed); + int oldLength = (int)strlen(m_pSelectedSkin->skinNameDisplayed); m_pSelectedSkin->skinNameDisplayed[oldLength - 4] = '\0'; m_pSelectedSkin->skinNameOriginal[oldLength - 4] = '\0'; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index de5881b5..072bc7be 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -362,7 +362,7 @@ bool CGame::Initialise(const char* datFile) CStreaming::LoadInitialPeds(); CStreaming::RequestBigBuildings(LEVEL_GENERIC); CStreaming::LoadAllRequestedModels(false); - printf("Streaming uses %dK of its memory", CStreaming::ms_memoryUsed / 1024); + printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen()); CAnimManager::LoadAnimFiles(); CStreaming::LoadInitialWeapons(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 83930c41..685256e3 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -3028,7 +3028,7 @@ void CPad::ResetCheats(void) char *CPad::EditString(char *pStr, int32 nSize) { - int32 pos = strlen(pStr); + int32 pos = (int32)strlen(pStr); // letters for ( int32 i = 0; i < ('Z' - 'A' + 1); i++ ) diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 484155d6..3c32b856 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -44,7 +44,7 @@ int32 CStreaming::ms_oldSectorX; int32 CStreaming::ms_oldSectorY; int32 CStreaming::ms_streamingBufferSize; int8 *CStreaming::ms_pStreamingBuffer[2]; -int32 CStreaming::ms_memoryUsed; +size_t CStreaming::ms_memoryUsed; CStreamingChannel CStreaming::ms_channel[2]; int32 CStreaming::ms_channelError; int32 CStreaming::ms_numVehiclesLoaded; @@ -61,7 +61,7 @@ uint16 CStreaming::ms_loadedGangCars; int32 CStreaming::ms_imageOffsets[NUMCDIMAGES]; int32 CStreaming::ms_lastImageRead; int32 CStreaming::ms_imageSize; -uint32 CStreaming::ms_memoryAvailable; +size_t CStreaming::ms_memoryAvailable; int32 desiredNumVehiclesLoaded = 12; @@ -200,9 +200,9 @@ CStreaming::Init2(void) debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); #define MB (1024*1024) - ms_memoryAvailable = 65*MB; + ms_memoryAvailable = 65 * MB; desiredNumVehiclesLoaded = 25; - debug("Memory allocated to Streaming is %dMB", ms_memoryAvailable/MB); + debug("Memory allocated to Streaming is %dMB", ms_memoryAvailable / MB); #undef MB // find island LODs @@ -2385,7 +2385,7 @@ CStreaming::DeleteRwObjectsAfterDeath(const CVector &pos) } void -CStreaming::DeleteRwObjectsBehindCamera(int32 mem) +CStreaming::DeleteRwObjectsBehindCamera(size_t mem) { int ix, iy; int x, y; @@ -2560,7 +2560,7 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y) } bool -CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem) +CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, size_t mem) { CPtrNode *node; CEntity *e; @@ -2581,7 +2581,7 @@ CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem) } bool -CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem) +CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem) { CPtrNode *node; CEntity *e; @@ -2608,7 +2608,7 @@ CStreaming::MakeSpaceFor(int32 size) // the code still happens to work in that case because ms_memoryAvailable is unsigned // but it's not nice.... - while((uint32)ms_memoryUsed >= ms_memoryAvailable - size) + while(ms_memoryUsed >= ms_memoryAvailable - size) if(!RemoveLeastUsedModel(STREAMFLAGS_20)){ DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); return; @@ -2699,7 +2699,8 @@ CStreaming::UpdateForAnimViewer(void) if (CStreaming::ms_channelError == -1) { CStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f)); CStreaming::LoadRequestedModels(); - sprintf(gString, "Requested %d, memory size %dK\n", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed); + // original modifier was %d + sprintf(gString, "Requested %d, memory size %zuK\n", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed); } else { CStreaming::RetryLoadFile(CStreaming::ms_channelError); diff --git a/src/core/Streaming.h b/src/core/Streaming.h index 8a92266f..569c06d8 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -89,7 +89,7 @@ public: static int32 ms_oldSectorY; static int32 ms_streamingBufferSize; static int8 *ms_pStreamingBuffer[2]; - static int32 ms_memoryUsed; + static size_t ms_memoryUsed; static CStreamingChannel ms_channel[2]; static int32 ms_channelError; static int32 ms_numVehiclesLoaded; @@ -106,7 +106,7 @@ public: static int32 ms_imageOffsets[NUMCDIMAGES]; static int32 ms_lastImageRead; static int32 ms_imageSize; - static uint32 ms_memoryAvailable; + static size_t ms_memoryAvailable; static void Init(void); static void Init2(void); @@ -193,11 +193,11 @@ public: static void DeleteFarAwayRwObjects(const CVector &pos); static void DeleteAllRwObjects(void); static void DeleteRwObjectsAfterDeath(const CVector &pos); - static void DeleteRwObjectsBehindCamera(int32 mem); + static void DeleteRwObjectsBehindCamera(size_t mem); static void DeleteRwObjectsInSectorList(CPtrList &list); static void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y); - static bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem); - static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem); + static bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, size_t mem); + static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem); static void LoadScene(const CVector &pos); static void LoadSceneCollision(const CVector &pos); diff --git a/src/core/common.h b/src/core/common.h index 3ead4f1d..b3ba757d 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -17,7 +17,11 @@ #if defined _WIN32 && defined WITHD3D #include +#ifndef USE_D3D9 #include +#else +#include +#endif #endif #include diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7db2124d..53c2b2c2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -5637,7 +5637,7 @@ CPed::LoadFightData(void) CAnimBlendAssociation *animAssoc; - int bp, buflen; + size_t bp, buflen; int lp, linelen; buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r"); diff --git a/src/peds/PedAttractor.cpp b/src/peds/PedAttractor.cpp index db5f9e52..d69f2684 100644 --- a/src/peds/PedAttractor.cpp +++ b/src/peds/PedAttractor.cpp @@ -137,8 +137,8 @@ void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect) for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) { if (assoc->GetVehicle() != pVehicle) return; - size_t total = 0; - for (size_t j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { + int total = 0; + for (int j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors)) total++; } @@ -355,13 +355,13 @@ bool CPedAttractor::BroadcastArrival(CPed* pPed) bool CPedAttractor::BroadcastDeparture(CPed* pPed) { int qid = -1; - for (size_t i = 0; i < vWaitingQueue.size(); i++){ + for (int i = 0; i < vWaitingQueue.size(); i++){ if (vWaitingQueue[i] == pPed) qid = i; } if (qid < 0) return false; - for (size_t i = qid + 1; i < vWaitingQueue.size(); i++) { + for (int i = qid + 1; i < vWaitingQueue.size(); i++) { CVector pos; float heading; float time; @@ -401,7 +401,7 @@ bool CPedAttractor::BroadcastDeparture(CPed* pPed) bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed) { int qid = -1; - for (size_t i = 0; i < vWaitingQueue.size(); i++) { + for (int i = 0; i < vWaitingQueue.size(); i++) { if (vWaitingQueue[i] == pPed) qid = i; } diff --git a/src/peds/PedAttractor.h b/src/peds/PedAttractor.h index 563efd3a..85b4327b 100644 --- a/src/peds/PedAttractor.h +++ b/src/peds/PedAttractor.h @@ -108,8 +108,8 @@ public: float ComputeDeltaHeading() const; float ComputeDeltaPos() const; void ComputeAttractTime(int32 id, bool, float& time) const; - int32 GetNoOfRegisteredPeds() const { return vWaitingQueue.size() + vApproachingQueue.size(); } - int32 ComputeFreeSlot() const { return vWaitingQueue.size(); } + int32 GetNoOfRegisteredPeds() const { return (int32)(vWaitingQueue.size() + vApproachingQueue.size()); } + int32 ComputeFreeSlot() const { return (int32)vWaitingQueue.size(); } bool IsInQueue(CPed*) const; bool RegisterPed(CPed*); bool BroadcastArrival(CPed*); diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp index 06e39039..1f7a95b4 100644 --- a/src/peds/PedStats.cpp +++ b/src/peds/PedStats.cpp @@ -47,7 +47,7 @@ CPedStats::LoadPedStats(void) char *buf; char line[256]; char name[32]; - int bp, buflen; + size_t bp, buflen; int lp, linelen; int type; float fleeDist, headingChangeRate, attackStrength, defendWeakness; diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp index 8bf4c6e1..397cd71d 100644 --- a/src/peds/PedType.cpp +++ b/src/peds/PedType.cpp @@ -43,7 +43,7 @@ CPedType::LoadPedData(void) char *buf; char line[256]; char word[32]; - int bp, buflen; + size_t bp, buflen; int lp, linelen; int type; uint32 flags; diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index fc6e6853..4771d8a4 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -922,7 +922,7 @@ void CScrollBar::Update() break; } - m_MessageLength = strlen(m_pMessage); + m_MessageLength = (uint32)strlen(m_pMessage); m_MessageCurrentChar = 0; } diff --git a/src/rw/NodeName.cpp b/src/rw/NodeName.cpp index d62884f7..ad4acffb 100644 --- a/src/rw/NodeName.cpp +++ b/src/rw/NodeName.cpp @@ -51,7 +51,7 @@ RwInt32 NodeNameStreamGetSize(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject) { // game checks for null pointer on node name extension but that really happen - return rwstrlen(NODENAMEEXT(object)); + return (RwInt32)rwstrlen(NODENAMEEXT(object)); } bool diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 25dffb4e..ac80eff0 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -843,12 +843,12 @@ CVisibilityPlugins::FrameCopyConstructor(void *dst, const void *src, int32, int3 } void -CVisibilityPlugins::SetFrameHierarchyId(RwFrame *frame, int32 id) +CVisibilityPlugins::SetFrameHierarchyId(RwFrame *frame, uintptr id) { FRAMEEXT(frame)->id = id; } -int32 +uintptr CVisibilityPlugins::GetFrameHierarchyId(RwFrame *frame) { return FRAMEEXT(frame)->id; diff --git a/src/rw/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h index d426abec..f277565d 100644 --- a/src/rw/VisibilityPlugins.h +++ b/src/rw/VisibilityPlugins.h @@ -112,10 +112,10 @@ public: struct FrameExt { // BUG: this is abused to hold a pointer by SetClumpModelInfo - int32 id; + uintptr id; }; - static void SetFrameHierarchyId(RwFrame *frame, int32 id); - static int32 GetFrameHierarchyId(RwFrame *frame); + static void SetFrameHierarchyId(RwFrame *frame, uintptr id); + static uintptr GetFrameHierarchyId(RwFrame *frame); static void *FrameConstructor(void *object, int32 offset, int32 len); static void *FrameDestructor(void *object, int32 offset, int32 len); diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index a21877c1..678d3ec4 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -4,7 +4,7 @@ // Functions that's different on glfw and win but have same signature, should be located on platform.h. #ifdef _WIN32 -// This only has as Win header. +// This only has as Windows header, which is lighter (as long as WITHWINDOWS isn't defined / isn't included). #include "win.h" extern DWORD _dwOperatingSystemVersion; #else diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 8b479681..a0a5a171 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -63,7 +63,7 @@ static psGlobalType PsGlobal; #undef MAKEPOINTS #define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l))) -unsigned long _dwMemAvailPhys; +size_t _dwMemAvailPhys; RwUInt32 gGameState; #ifdef _WIN32 diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 93f9b8f2..f8e5c38e 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -19,7 +19,12 @@ #pragma warning( push ) #pragma warning( disable : 4005) + +#ifdef USE_D3D9 +#include +#else #include +#endif #include #include #include @@ -27,7 +32,9 @@ #define WM_GRAPHNOTIFY WM_USER+13 +#ifndef USE_D3D9 #pragma comment( lib, "d3d8.lib" ) +#endif #pragma comment( lib, "ddraw.lib" ) #pragma comment( lib, "Winmm.lib" ) #pragma comment( lib, "dxguid.lib" ) @@ -102,7 +109,7 @@ IMediaSeeking *pMS = nil; DWORD dwDXVersion; SIZE_T _dwMemTotalPhys; -SIZE_T _dwMemAvailPhys; +size_t _dwMemAvailPhys; SIZE_T _dwMemTotalVirtual; SIZE_T _dwMemAvailVirtual; DWORD _dwMemTotalVideo; @@ -453,6 +460,16 @@ DWORD GetDXVersion() dwDXVersion = 0x700; pDD7->Release(); +#ifdef USE_D3D9 + HINSTANCE hD3D9DLL = LoadLibrary("D3D9.DLL"); + if (hD3D9DLL != nil) { + FreeLibrary(hDDrawDLL); + FreeLibrary(hD3D9DLL); + + dwDXVersion = 0x900; + return dwDXVersion; + } +#endif //------------------------------------------------------------------------- // DirectX 8.0 Checks @@ -502,6 +519,7 @@ DWORD GetDXVersion() /* ***************************************************************************** */ +#ifndef _WIN64 static char cpuvendor[16] = "UnknownVendr"; __declspec(naked) const char * _psGetCpuVendr() { @@ -575,6 +593,7 @@ void _psPrintCpuInfo() if ( FeaturesEx & 0x80000000 ) debug("with 3DNow"); } +#endif /* ***************************************************************************** @@ -650,9 +669,9 @@ psInitialize(void) gGameState = GS_START_UP; TRACE("gGameState = GS_START_UP"); - +#ifndef _WIN64 _psPrintCpuInfo(); - +#endif OSVERSIONINFO verInfo; verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); @@ -1298,8 +1317,11 @@ RwBool IsForegroundApp() UINT GetBestRefreshRate(UINT width, UINT height, UINT depth) { +#ifdef USE_D3D9 + LPDIRECT3D9 d3d = Direct3DCreate9(D3D_SDK_VERSION); +#else LPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION); - +#endif ASSERT(d3d != nil); UINT refreshRate = INT_MAX; @@ -1312,14 +1334,21 @@ UINT GetBestRefreshRate(UINT width, UINT height, UINT depth) else format = D3DFMT_R5G6B5; +#ifdef USE_D3D9 + UINT modeCount = d3d->GetAdapterModeCount(GcurSel, format); +#else UINT modeCount = d3d->GetAdapterModeCount(GcurSel); - +#endif + for ( UINT i = 0; i < modeCount; i++ ) { D3DDISPLAYMODE mode; +#ifdef USE_D3D9 + d3d->EnumAdapterModes(GcurSel, format, i, &mode); +#else d3d->EnumAdapterModes(GcurSel, i, &mode); - +#endif if ( mode.Width == width && mode.Height == height && mode.Format == format ) { if ( mode.RefreshRate == 0 ) @@ -1612,7 +1641,7 @@ CommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount) RwInt32 i, len; RwChar *res, *str, **aptr; - len = strlen(cmdLine); + len = (int)strlen(cmdLine); /* * Count the number of arguments... @@ -1700,11 +1729,11 @@ void InitialiseLanguage() { WORD primUserLCID = PRIMARYLANGID(GetSystemDefaultLCID()); WORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID()); - WORD primLayout = PRIMARYLANGID((DWORD)GetKeyboardLayout(0)); + WORD primLayout = PRIMARYLANGID((DWORD_PTR)GetKeyboardLayout(0)); WORD subUserLCID = SUBLANGID(GetSystemDefaultLCID()); WORD subSystemLCID = SUBLANGID(GetUserDefaultLCID()); - WORD subLayout = SUBLANGID((DWORD)GetKeyboardLayout(0)); + WORD subLayout = SUBLANGID((DWORD_PTR)GetKeyboardLayout(0)); if ( primUserLCID == LANG_GERMAN || primSystemLCID == LANG_GERMAN diff --git a/src/skel/win/win.h b/src/skel/win/win.h index eb32cb72..9427822d 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -9,8 +9,12 @@ #endif /* (!defined(RSREGSETBREAKALLOC)) */ #ifndef _INC_WINDOWS -#define _X86_ -#include + #ifdef _WIN64 + #define _AMD64_ + #else + #define _X86_ + #endif + #include #endif enum eWinVersion diff --git a/src/text/Text.cpp b/src/text/Text.cpp index d954470f..dab1cae3 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -28,7 +28,7 @@ void CText::Load(void) { char filename[32]; - uint32 offset; + size_t offset; int file; bool tkey_loaded = false, tdat_loaded = false; ChunkHeader m_ChunkHeader; @@ -209,7 +209,7 @@ CText::GetNameOfLoadedMissionText(char *outName) //--MIAMI: DONE void -CText::ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *offset) +CText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset) { // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader)); @@ -281,15 +281,15 @@ CText::LoadMissionText(char *MissionTableName) bool tkey_loaded = false, tdat_loaded = false; ChunkHeader m_ChunkHeader; while (!tkey_loaded || !tdat_loaded) { - uint32 bytes_read = 0; + size_t bytes_read = 0; ReadChunkHeader(&m_ChunkHeader, file, &bytes_read); if (m_ChunkHeader.size != 0) { if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) { - uint32 bytes_read = 0; + size_t bytes_read = 0; mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read); tkey_loaded = true; } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) { - uint32 bytes_read = 0; + size_t bytes_read = 0; mission_data.Load(m_ChunkHeader.size, file, &bytes_read); tdat_loaded = true; } else @@ -308,11 +308,12 @@ CText::LoadMissionText(char *MissionTableName) //--MIAMI: DONE void -CKeyArray::Load(uint32 length, int file, uint32 *offset) +CKeyArray::Load(size_t length, int file, size_t* offset) { char *rawbytes; - numEntries = length / sizeof(CKeyEntry); + // You can make numEntries size_t if you want to exceed 32-bit boundaries, everything else should be ready. + numEntries = (int)(length / sizeof(CKeyEntry)); entries = new CKeyEntry[numEntries]; rawbytes = (char*)entries; @@ -403,11 +404,12 @@ CKeyArray::Search(const char *key, uint8 *result) //--MIAMI: DONE void -CData::Load(uint32 length, int file, uint32 *offset) +CData::Load(size_t length, int file, size_t * offset) { char *rawbytes; - numChars = length / sizeof(wchar); + // You can make numChars size_t if you want to exceed 32-bit boundaries, everything else should be ready. + numChars = (int)(length / sizeof(wchar)); chars = new wchar[numChars]; rawbytes = (char*)chars; @@ -430,10 +432,12 @@ CData::Unload(void) //--MIAMI: DONE void -CMissionTextOffsets::Load(uint32 table_size, int file, uint32 *offset, int) +CMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int) { // not exact VC code but smaller and better :P - size = table_size / sizeof(CMissionTextOffsets::Entry); + + // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. + size = (uint16) (table_size / sizeof(CMissionTextOffsets::Entry)); CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size); *offset += sizeof(CMissionTextOffsets::Entry) * size; } diff --git a/src/text/Text.h b/src/text/Text.h index 5fa3d0dc..d163b9c9 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -26,11 +26,11 @@ class CKeyArray { public: CKeyEntry *entries; - int numEntries; + int numEntries; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. CKeyArray(void) : entries(nil), numEntries(0) {} ~CKeyArray(void) { Unload(); } - void Load(uint32 length, int file, uint32 *offset); + void Load(size_t length, int file, size_t *offset); void Unload(void); void Update(wchar *chars); CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high); @@ -45,11 +45,11 @@ class CData { public: wchar *chars; - int numChars; + int numChars; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. CData(void) : chars(nil), numChars(0) {} ~CData(void) { Unload(); } - void Load(uint32 length, int file, uint32 *offset); + void Load(size_t length, int file, size_t* offset); void Unload(void); }; @@ -65,10 +65,10 @@ public: enum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more Entry data[MAX_MISSION_TEXTS]; - uint16 size; + uint16 size; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. CMissionTextOffsets(void) : size(0) {} - void Load(uint32 table_size, int file, uint32* bytes_read, int); + void Load(size_t table_size, int file, size_t* bytes_read, int); }; struct ChunkHeader @@ -96,7 +96,7 @@ public: wchar GetUpperCase(wchar c); void UpperCase(wchar *s); void GetNameOfLoadedMissionText(char *outName); - void ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *bytes_read); + void ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *bytes_read); void LoadMissionText(char *MissionTableName); }; diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index bd53d8c5..0f71aeda 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -114,7 +114,7 @@ CWeaponInfo::LoadWeaponData(void) char line[256], weaponName[32], fireType[32]; char animToPlay[32]; - int bp, buflen; + size_t bp, buflen; int lp, linelen; CFileMgr::SetDir("DATA"); From ad6094ca1d9b54b32ae8153c771e8e6f9308103a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 24 Jul 2020 20:43:51 +0300 Subject: [PATCH 77/85] 90% fixes, 10% skel refactoring --- src/control/Garages.cpp | 3 +++ src/core/Frontend.cpp | 7 ------- src/core/Pad.cpp | 19 ++++++++++++++++--- src/modelinfo/VehicleModelInfo.cpp | 4 ++++ src/peds/PedAttractor.cpp | 10 +++++----- src/render/Font.cpp | 12 ++++++++++++ src/skel/crossplatform.h | 30 +++++++++++++++++++++++------- src/skel/glfw/glfw.cpp | 21 ++++++++++++++++++++- src/skel/platform.h | 5 +++++ src/skel/win/win.cpp | 7 ++++++- src/skel/win/win.h | 26 ++------------------------ src/vehicles/CarGen.cpp | 10 ++++++++-- 12 files changed, 104 insertions(+), 50 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 6b4ceb80..e7b5ebe6 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -137,6 +137,9 @@ void CGarages::Init(void) MessageStartTime = 0; PlayerInGarage = false; BombsAreFree = false; +#ifdef FIX_BUGS + RespraysAreFree = false; +#endif CarsCollected = 0; BankVansCollected = 0; PoliceCarsCollected = 0; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index e5776459..06744ac2 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5155,13 +5155,10 @@ CMenuManager::SwitchMenuOnAndOff() m_bMenuActive = !m_bMenuActive; if (m_bMenuActive) { -#if defined RW_D3D9 || defined RWLIBS if (_InputMouseNeedsExclusive()) { _InputShutdownMouse(); _InputInitialiseMouse(false); } -#endif - Initialise(); LoadAllTextures(); } else { @@ -5173,12 +5170,10 @@ CMenuManager::SwitchMenuOnAndOff() DoRWStuffEndOfFrame(); DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255); DoRWStuffEndOfFrame(); -#if defined RW_D3D9 || defined RWLIBS if (_InputMouseNeedsExclusive()) { _InputShutdownMouse(); _InputInitialiseMouse(true); } -#endif #ifdef PS2_LIKE_MENU bottomBarActive = false; @@ -5223,12 +5218,10 @@ CMenuManager::SwitchMenuOnAndOff() m_bMenuActive = true; m_OnlySaveMenu = true; -#if defined RW_D3D9 || defined RWLIBS if (_InputMouseNeedsExclusive()) { _InputShutdownMouse(); _InputInitialiseMouse(false); } -#endif Initialise(); LoadAllTextures(); diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 685256e3..8043bb6c 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -722,9 +722,9 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() void CPad::UpdateMouse() { +#if defined RW_D3D9 || defined RWLIBS if ( IsForegroundApp() ) { -#if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) _InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive()); @@ -761,7 +761,10 @@ void CPad::UpdateMouse() OldMouseControllerState = NewMouseControllerState; NewMouseControllerState = PCTempMouseControllerState; } + } #else + if ( IsForegroundApp() && PSGLOBAL(cursorIsInWindow) ) + { double xpos = 1.0f, ypos; glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos); if (xpos == 0.f) @@ -799,8 +802,8 @@ void CPad::UpdateMouse() OldMouseControllerState = NewMouseControllerState; NewMouseControllerState = PCTempMouseControllerState; -#endif } +#endif } CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2) @@ -1451,6 +1454,13 @@ void CPad::UpdatePads(void) #else CapturePad(0); #endif + + // Improve keyboard input latency part 1 +#ifdef FIX_BUGS + OldKeyState = NewKeyState; + NewKeyState = TempKeyState; +#endif + #ifdef DETECT_PAD_INPUT_SWITCH if (GetPad(0)->PCTempJoyState.CheckForInput()) IsAffectedByController = true; @@ -1472,7 +1482,7 @@ void CPad::UpdatePads(void) if ( bUpdate ) { GetPad(0)->Update(0); - GetPad(1)->Update(0); + // GetPad(1)->Update(0); // not in VC } #if defined(MASTER) && !defined(XINPUT) @@ -1480,8 +1490,11 @@ void CPad::UpdatePads(void) GetPad(1)->OldState.Clear(); #endif + // Improve keyboard input latency part 2 +#ifndef FIX_BUGS OldKeyState = NewKeyState; NewKeyState = TempKeyState; +#endif } void CPad::ProcessPCSpecificStuff(void) diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index d5396d12..11f78495 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -689,7 +689,11 @@ ChooseComponent(int32 rule, int32 comps) return COMPRULE_COMPN(comps, n-1); return -1; case 4: +#ifdef FIX_BUGS + return CGeneral::GetRandomNumberInRange(0, 6); +#else return CGeneral::GetRandomNumberInRange(0, 5); +#endif } return -1; } diff --git a/src/peds/PedAttractor.cpp b/src/peds/PedAttractor.cpp index d69f2684..9f77f2a4 100644 --- a/src/peds/PedAttractor.cpp +++ b/src/peds/PedAttractor.cpp @@ -137,8 +137,8 @@ void CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect) for (std::vector::const_iterator assoc = vVehicleToEffect.cbegin(); assoc != vVehicleToEffect.cend();) { if (assoc->GetVehicle() != pVehicle) return; - int total = 0; - for (int j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { + uint32 total = 0; + for (uint32 j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) { if (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors)) total++; } @@ -355,13 +355,13 @@ bool CPedAttractor::BroadcastArrival(CPed* pPed) bool CPedAttractor::BroadcastDeparture(CPed* pPed) { int qid = -1; - for (int i = 0; i < vWaitingQueue.size(); i++){ + for (uint32 i = 0; i < vWaitingQueue.size(); i++){ if (vWaitingQueue[i] == pPed) qid = i; } if (qid < 0) return false; - for (int i = qid + 1; i < vWaitingQueue.size(); i++) { + for (uint32 i = qid + 1; i < vWaitingQueue.size(); i++) { CVector pos; float heading; float time; @@ -401,7 +401,7 @@ bool CPedAttractor::BroadcastDeparture(CPed* pPed) bool CPedShelterAttractor::BroadcastDeparture(CPed* pPed) { int qid = -1; - for (int i = 0; i < vWaitingQueue.size(); i++) { + for (uint32 i = 0; i < vWaitingQueue.size(); i++) { if (vWaitingQueue[i] == pPed) qid = i; } diff --git a/src/render/Font.cpp b/src/render/Font.cpp index a3ead932..1e60083b 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -1133,7 +1133,11 @@ CFont::ParseToken(wchar *s) case 'r': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break; case 't': SetColor(CRGBA(86, 212, 146, 255)); Details.anonymous_23 = true; break; case 'w': SetColor(CRGBA(175, 175, 175, 255)); Details.anonymous_23 = true; break; +#ifdef FIX_BUGS + case 'x': SetColor(CRGBA(0, 255, 255, 255)); Details.anonymous_23 = true; break; +#else case 'x': SetColor(CRGBA(132, 146, 197, 255)); Details.anonymous_23 = true; break; +#endif case 'y': SetColor(CRGBA(255, 227, 79, 255)); Details.anonymous_23 = true; break; } while(*s != '~') s++; @@ -1208,11 +1212,19 @@ CFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold) color.g = 175; color.b = 175; break; +#ifdef FIX_BUGS + case 'x': + color.r = 0; + color.g = 255; + color.b = 255; + break; +#else case 'x': color.r = 132; color.g = 146; color.b = 197; break; +#endif case 'y': color.r = 255; color.g = 227; diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 678d3ec4..066570be 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -3,19 +3,34 @@ // This is the common include for platform/renderer specific skeletons(glfw.cpp, win.cpp etc.) and using cross platform things (like Windows directories wrapper, platform specific global arrays etc.) // Functions that's different on glfw and win but have same signature, should be located on platform.h. +enum eWinVersion +{ + OS_WIN95 = 0, + OS_WIN98, + OS_WINNT, + OS_WIN2000, + OS_WINXP, +}; + #ifdef _WIN32 -// This only has as Windows header, which is lighter (as long as WITHWINDOWS isn't defined / isn't included). + +// As long as WITHWINDOWS isn't defined / isn't included, include , which is lighter. +#ifndef _INC_WINDOWS + #ifdef _WIN64 + #define _ARM64_ + #else + #define _X86_ + #endif + #include +#endif +#if defined RW_D3D9 || defined RWLIBS #include "win.h" +#endif extern DWORD _dwOperatingSystemVersion; + #else char *strupr(char *str); char *strlwr(char *str); -enum { - OS_WIN98, - OS_WIN2000, - OS_WINNT, - OS_WINXP, -}; enum { LANG_OTHER, @@ -42,6 +57,7 @@ typedef struct RwBool fullScreen; RwV2d lastMousePos; double mouseWheel; // glfw doesn't cache it + bool cursorIsInWindow; RwInt8 joy1id; RwInt8 joy2id; } diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index a0a5a171..9a4f2188 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -282,6 +282,7 @@ psInitialize(void) RsGlobal.ps = &PsGlobal; PsGlobal.fullScreen = FALSE; + PsGlobal.cursorIsInWindow = TRUE; PsGlobal.joy1id = -1; PsGlobal.joy2id = -1; @@ -790,6 +791,7 @@ void keypressCB(GLFWwindow* window, int key, int scancode, int action, int mods) void resizeCB(GLFWwindow* window, int width, int height); void scrollCB(GLFWwindow* window, double xoffset, double yoffset); void cursorCB(GLFWwindow* window, double xpos, double ypos); +void cursorEnterCB(GLFWwindow* window, int entered); void joysChangeCB(int jid, int event); bool IsThisJoystickBlacklisted(int i) @@ -831,6 +833,17 @@ long _InputInitialiseMouse(bool exclusive) return 0; } +void _InputShutdownMouse() +{ + // Not needed +} + +bool _InputMouseNeedsExclusive() +{ + // That was the cause of infamous mouse bug on Win. Not supported on glfw anyway + return false; +} + void psPostRWinit(void) { RwVideoMode vm; @@ -840,6 +853,7 @@ void psPostRWinit(void) glfwSetWindowSizeCallback(PSGLOBAL(window), resizeCB); glfwSetScrollCallback(PSGLOBAL(window), scrollCB); glfwSetCursorPosCallback(PSGLOBAL(window), cursorCB); + glfwSetCursorEnterCallback(PSGLOBAL(window), cursorEnterCB); glfwSetJoystickCallback(joysChangeCB); _InputInitialiseJoys(); @@ -1345,13 +1359,18 @@ _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { RsKeyboardEventHandler(rshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsRSHIFT)); } -// TODO this only works in frontend(and luckily only frontend use this), maybe because of glfw knows that mouse pos is > 32000 in game?? +// TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000 void cursorCB(GLFWwindow* window, double xpos, double ypos) { FrontEndMenuManager.m_nMouseTempPosX = xpos; FrontEndMenuManager.m_nMouseTempPosY = ypos; } +void +cursorEnterCB(GLFWwindow* window, int entered) { + PSGLOBAL(cursorIsInWindow) = !!entered; +} + /* ***************************************************************************** */ diff --git a/src/skel/platform.h b/src/skel/platform.h index 7f36d8b7..806c0a73 100644 --- a/src/skel/platform.h +++ b/src/skel/platform.h @@ -1,6 +1,8 @@ #ifndef PLATFORM_H #define PLATFORM_H +// Functions that's different on glfw/win etc. but have same signature (but if a function only used in win.cpp you can keep in win.h) + #include "rwcore.h" #include "skeleton.h" @@ -36,6 +38,9 @@ extern RwBool psNativeTextureSupport(void); extern void _InputTranslateShiftKeyUpDown(RsKeyCodes* rs); extern long _InputInitialiseMouse(bool exclusive); // returns HRESULT on Windows actually +extern void _InputShutdownMouse(); +extern bool _InputMouseNeedsExclusive(); +extern void _InputInitialiseJoys(); extern void HandleExit(); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index f8e5c38e..a2673ccb 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -2883,8 +2883,13 @@ void _InputShutdownMouse() SAFE_RELEASE(PSGLOBAL(mouse)); } -BOOL _InputMouseNeedsExclusive(void) +bool _InputMouseNeedsExclusive(void) { + // FIX: I don't know why R* needed that, but it causes infamous mouse bug on modern systems. + // Probably DirectInput bug, since Acquire() and GetDeviceState() reports everything A-OK. +#ifdef FIX_BUGS + return false; +#endif RwVideoMode vm; RwEngineGetVideoModeInfo(&vm, GcurSelVM); diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 9427822d..4b2001f8 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -1,5 +1,5 @@ -// DON'T include directly. crossplatform.h includes this if you're on Windows. +// DON'T include directly. crossplatform.h includes this if you're using D3D9 backend(win.cpp). #if (!defined(_PLATFORM_WIN_H)) #define _PLATFORM_WIN_H @@ -8,25 +8,6 @@ #define RSREGSETBREAKALLOC(_name) /* No op */ #endif /* (!defined(RSREGSETBREAKALLOC)) */ -#ifndef _INC_WINDOWS - #ifdef _WIN64 - #define _AMD64_ - #else - #define _X86_ - #endif - #include -#endif - -enum eWinVersion -{ - OS_WIN95 = 0, - OS_WIN98, - OS_WINNT, - OS_WIN2000, - OS_WINXP, -}; - - #ifdef __DINPUT_INCLUDED__ /* platform specfic global data */ typedef struct @@ -87,19 +68,16 @@ extern "C" { #endif /* __cplusplus */ -#ifdef __DINPUT_INCLUDED__ extern LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); +#ifdef __DINPUT_INCLUDED__ HRESULT _InputInitialise(); HRESULT CapturePad(RwInt32 padID); -void _InputInitialiseJoys(); void _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num); HRESULT _InputAddJoys(); HRESULT _InputGetMouseState(DIMOUSESTATE2 *state); void _InputShutdown(); -void _InputShutdownMouse(); -BOOL _InputMouseNeedsExclusive(); BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key); BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown); diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 4b83cc81..84a19b82 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -32,7 +32,7 @@ void CCarGenerator::SwitchOff() void CCarGenerator::SwitchOn() { - m_nUsesRemaining = -1; + m_nUsesRemaining = 255; m_nTimer = CalcNextGen(); ++CTheCarGenerators::CurrentActiveCount; } @@ -141,8 +141,14 @@ void CCarGenerator::DoInternalProcessing() } CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pVehicle); - if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */ + /* I don't think this is a correct comparasion */ +#ifdef FIX_BUGS + if (m_nUsesRemaining != 0) --m_nUsesRemaining; +#else + if (m_nUsesRemaining < -1) + --m_nUsesRemaining; +#endif m_nTimer = CalcNextGen(); if (m_nUsesRemaining == 0) --CTheCarGenerators::CurrentActiveCount; From 1c44368f0ab171bf3b551af66842f11d0d6ec990 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 24 Jul 2020 23:29:33 +0200 Subject: [PATCH 78/85] fixed hanim for 64 bit --- src/animation/AnimBlendClumpData.h | 2 +- src/animation/FrameUpdate.cpp | 6 +++--- src/animation/RpAnimBlend.cpp | 4 ++-- src/core/common.h | 1 + src/entities/Entity.cpp | 2 +- src/fakerw/rphanim.h | 12 ++++++++++-- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/animation/AnimBlendClumpData.h b/src/animation/AnimBlendClumpData.h index b953ee88..4043c778 100644 --- a/src/animation/AnimBlendClumpData.h +++ b/src/animation/AnimBlendClumpData.h @@ -19,7 +19,7 @@ struct AnimBlendFrameData #ifdef PED_SKIN union { RwFrame *frame; - RpHAnimStdKeyFrame *hanimFrame; + RpHAnimStdInterpFrame *hanimFrame; }; int32 nodeID; #else diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index c119d479..faeea709 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -236,7 +236,7 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) float transBlendAmount = 0.0f; CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); float totalBlendAmount = 0.0f; - RpHAnimStdKeyFrame *xform = frame->hanimFrame; + RpHAnimStdInterpFrame *xform = frame->hanimFrame; CAnimBlendNode **node; AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; @@ -297,7 +297,7 @@ FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void float curx = 0.0f, cury = 0.0f; float endx = 0.0f, endy = 0.0f; bool looped = false; - RpHAnimStdKeyFrame *xform = frame->hanimFrame; + RpHAnimStdInterpFrame *xform = frame->hanimFrame; CAnimBlendNode **node; AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; @@ -381,7 +381,7 @@ FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, vo CVector cur(0.0f, 0.0f, 0.0f); CVector end(0.0f, 0.0f, 0.0f); bool looped = false; - RpHAnimStdKeyFrame *xform = frame->hanimFrame; + RpHAnimStdInterpFrame *xform = frame->hanimFrame; CAnimBlendNode **node; AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index 6739f56a..e93615b7 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -170,9 +170,9 @@ RpAnimBlendClumpInitSkinned(RpClump *clump) frames[i].nodeID = HIERNODEID(hier, i); frames[i].resetPos = boneTab[i]; #ifdef LIBRW - frames[i].hanimFrame = (RpHAnimStdKeyFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); + frames[i].hanimFrame = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); #else - frames[i].hanimFrame = (RpHAnimStdKeyFrame*)rtANIMGETINTERPFRAME(hier->currentAnim, i); + frames[i].hanimFrame = (RpHAnimStdInterpFrame*)rtANIMGETINTERPFRAME(hier->currentAnim, i); #endif } clumpData->ForAllFrames(FrameInitCBskin, nil); diff --git a/src/core/common.h b/src/core/common.h index b3ba757d..d22c1715 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -41,6 +41,7 @@ #define HIERNODEINFO(hier) ((hier)->pNodeInfo) #define HIERNODEID(hier, i) ((hier)->pNodeInfo[i].nodeID) #define HANIMFRAME(anim, i) ((RwUInt8*)(anim)->pFrames + (i)*(anim)->interpInfo->keyFrameSize) +#define RpHAnimStdInterpFrame RpHAnimStdKeyFrame #endif #ifdef RWHALFPIXEL diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 4c88c485..e9332e8a 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -648,7 +648,7 @@ CEntity::UpdateRpHAnim(void) char buf[256]; if(this == (CEntity*)FindPlayerPed()) for(i = 0; i < hier->numNodes; i++){ - RpHAnimStdKeyFrame *kf = (RpHAnimStdKeyFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); + RpHAnimStdInterpFrame *kf = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); sprintf(buf, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %d %s", kf->q.imag.x, kf->q.imag.y, kf->q.imag.z, kf->q.real, kf->t.x, kf->t.y, kf->t.z, diff --git a/src/fakerw/rphanim.h b/src/fakerw/rphanim.h index 6ece8306..63059800 100644 --- a/src/fakerw/rphanim.h +++ b/src/fakerw/rphanim.h @@ -17,7 +17,15 @@ struct RpHAnimStdKeyFrame RtQuat q; RwV3d t; }; - +// same story, this one only exists in later RW versions +// but we need it for 64 bit builds because offset and size differs! +struct RpHAnimStdInterpFrame +{ + RpHAnimStdKeyFrame *keyFrame1; + RpHAnimStdKeyFrame *keyFrame2; + RtQuat q; + RwV3d t; +}; enum RpHAnimHierarchyFlag { @@ -56,7 +64,7 @@ RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy); #define rpHANIMHIERARCHYGETINTERPFRAME( hierarchy, nodeIndex ) \ ( (void *)( ( (RwUInt8 *)&(hierarchy->interpolator[1]) + \ ((nodeIndex) * \ - hierarchy->interpolator->currentAnimKeyFrameSize) ) ) ) + hierarchy->interpolator->currentInterpKeyFrameSize) ) ) ) RpHAnimAnimation *RpHAnimAnimationCreate(RwInt32 typeID, RwInt32 numFrames, RwInt32 flags, RwReal duration); From 7fea567eb27c033cc1d93c248dd4919bce59c998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 25 Jul 2020 15:24:24 +0300 Subject: [PATCH 79/85] Fix/change some Windows define --- src/skel/crossplatform.h | 10 +++----- src/skel/win/win.cpp | 55 ++++++++++++++++++++-------------------- src/skel/win/win.h | 3 --- 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 066570be..268eedff 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -14,14 +14,10 @@ enum eWinVersion #ifdef _WIN32 -// As long as WITHWINDOWS isn't defined / isn't included, include , which is lighter. +// As long as WITHWINDOWS isn't defined / isn't included, we only need type definitions so let's include . +// NOTE: It's perfectly fine to include here, but it can increase build size and time in *some* conditions, and maybe substantially in future if we'll use crossplatform.h more. #ifndef _INC_WINDOWS - #ifdef _WIN64 - #define _ARM64_ - #else - #define _X86_ - #endif - #include + #include #endif #if defined RW_D3D9 || defined RWLIBS #include "win.h" diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index a2673ccb..75a3a7c9 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -313,34 +313,6 @@ psNativeTextureSupport(void) return RwD3D8DeviceSupportsDXTTexture(); } -/* - ***************************************************************************** - */ -static BOOL -InitApplication(HANDLE instance) -{ - /* - * Perform any necessary MS Windows application initialization. Basically, - * this means registering the window class for this application. - */ - - WNDCLASS windowClass; - - windowClass.style = CS_BYTEALIGNWINDOW; - windowClass.lpfnWndProc = (WNDPROC) MainWndProc; - windowClass.cbClsExtra = 0; - windowClass.cbWndExtra = 0; - windowClass.hInstance = (HINSTANCE)instance; - windowClass.hIcon = nil; - windowClass.hCursor = LoadCursor(nil, IDC_ARROW); - windowClass.hbrBackground = nil; - windowClass.lpszMenuName = NULL; - windowClass.lpszClassName = AppClassName; - - return RegisterClass(&windowClass); -} - - /* ***************************************************************************** */ @@ -1305,6 +1277,33 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) return DefWindowProc(window, message, wParam, lParam); } +/* + ***************************************************************************** + */ +static BOOL +InitApplication(HANDLE instance) +{ + /* + * Perform any necessary MS Windows application initialization. Basically, + * this means registering the window class for this application. + */ + + WNDCLASS windowClass; + + windowClass.style = CS_BYTEALIGNWINDOW; + windowClass.lpfnWndProc = (WNDPROC)MainWndProc; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hInstance = (HINSTANCE)instance; + windowClass.hIcon = nil; + windowClass.hCursor = LoadCursor(nil, IDC_ARROW); + windowClass.hbrBackground = nil; + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = AppClassName; + + return RegisterClass(&windowClass); +} + /* ***************************************************************************** diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 4b2001f8..be840898 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -68,9 +68,6 @@ extern "C" { #endif /* __cplusplus */ -extern LRESULT CALLBACK -MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); - #ifdef __DINPUT_INCLUDED__ HRESULT _InputInitialise(); HRESULT CapturePad(RwInt32 padID); From 90fdc4328b2aa9dc59fdb88115b0f308affc456f Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 26 Jul 2020 23:41:01 +0200 Subject: [PATCH 80/85] CHeli and CRopes done --- src/core/Ropes.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++ src/core/Ropes.h | 31 ++++++++ src/peds/CopPed.cpp | 1 + src/peds/CopPed.h | 2 + src/render/Fluff.cpp | 4 +- src/vehicles/Heli.cpp | 148 +++++++++++++++++++++++++----------- src/vehicles/Heli.h | 9 ++- 7 files changed, 314 insertions(+), 50 deletions(-) create mode 100644 src/core/Ropes.cpp create mode 100644 src/core/Ropes.h diff --git a/src/core/Ropes.cpp b/src/core/Ropes.cpp new file mode 100644 index 00000000..4c57f190 --- /dev/null +++ b/src/core/Ropes.cpp @@ -0,0 +1,169 @@ +#include "common.h" + +#include "Timer.h" +#include "ModelIndices.h" +#include "Streaming.h" +#include "CopPed.h" +#include "Population.h" +#include "RenderBuffer.h" +#include "Camera.h" +#include "Ropes.h" + +CRope CRopes::aRopes[8]; + +RwImVertexIndex RopeIndices[64] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, + 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, + 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, + 31, 32 // unused +}; + +void +CRope::Update(void) +{ + int i; + float step = Pow(0.85f, CTimer::GetTimeStep()); + if(!m_bWasRegistered && CTimer::GetTimeInMilliseconds() > m_updateTimer){ + m_speed[0].z -= 0.0015f*CTimer::GetTimeStep(); + m_pos[0] += m_speed[0]*CTimer::GetTimeStep(); + } + for(i = 1; i < ARRAY_SIZE(m_pos); i++){ + CVector prevPos = m_pos[i]; + m_pos[i] += m_speed[i]*step*CTimer::GetTimeStep(); + m_pos[0].z -= 0.05f*CTimer::GetTimeStep(); + CVector dist = m_pos[i] - m_pos[i-1]; + m_pos[i] = m_pos[i-1] + dist/dist.Magnitude()*0.625f; + m_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep(); + } + if(!m_bWasRegistered && m_pos[0].z < 0.0f) + m_bActive = false; + m_bWasRegistered = true; +} + +void +CRope::Render(void) +{ + int i; + int numVerts = 0; + if(!TheCamera.IsSphereVisible(m_pos[16], 20.0f)) + return; + + for(i = 0; i < ARRAY_SIZE(m_pos); i++){ + RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 128, 128, 128, 100); + RwIm3DVertexSetPos(&TempBufferRenderVertices[i], m_pos[i].x, m_pos[i].y, m_pos[i].z); + } + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + + if(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ + RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); + RwIm3DEnd(); + } +} + + +void +CRopes::Init(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + aRopes[i].m_bActive = false; +} + +void +CRopes::Update(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive) + aRopes[i].Update(); +} + +void +CRopes::Render(void) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive) + aRopes[i].Render(); +} + +bool +CRopes::RegisterRope(uintptr id, CVector pos, bool setUpdateTimer) +{ + int i, j; + for(i = 0; i < ARRAY_SIZE(aRopes); i++){ + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + aRopes[i].m_pos[0] = pos; + aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f); + aRopes[i].m_bWasRegistered = true; + return true; + } + } + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(!aRopes[i].m_bActive){ + aRopes[i].m_id = id; + aRopes[i].m_pos[0] = pos; + aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f); + aRopes[i].m_unk = false; + aRopes[i].m_bWasRegistered = true; + aRopes[i].m_updateTimer = setUpdateTimer ? CTimer::GetTimeInMilliseconds() + 20000 : 0; + for(j = 1; j < ARRAY_SIZE(CRope::m_pos); j++){ + if(j & 1) + aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] + CVector(0.0f, 0.0f, 0.625f); + else + aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] - CVector(0.0f, 0.0f, 0.625f); + aRopes[i].m_speed[j] = CVector(0.0f, 0.0f, 0.0f); + } + aRopes[i].m_bActive = true; + return true; + } + return false; +} + +void +CRopes::SetSpeedOfTopNode(uintptr id, CVector speed) +{ + int i; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + aRopes[i].m_speed[0] = speed; + return; + } +} + +bool +CRopes::FindCoorsAlongRope(uintptr id, float t, CVector *coors) +{ + int i, j; + float f; + for(i = 0; i < ARRAY_SIZE(aRopes); i++) + if(aRopes[i].m_bActive && aRopes[i].m_id == id){ + t = (ARRAY_SIZE(CRope::m_pos)-1)*clamp(t, 0.0f, 0.999f); + j = t; + f = t - j; + *coors = (1.0f-f)*aRopes[i].m_pos[j] + f*aRopes[i].m_pos[j+1]; + return true; + } + return false; +} + +bool +CRopes::CreateRopeWithSwatComingDown(CVector pos) +{ + static uint32 ropeId = 0; + + if(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true)) + return false; + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + swat->bUsesCollision = false; + swat->m_pRopeEntity = (CEntity*)1; + swat->m_nRopeID = 100 + ropeId; + CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_ABSEIL, 4.0f); + ropeId++; + return true; +} diff --git a/src/core/Ropes.h b/src/core/Ropes.h new file mode 100644 index 00000000..7930fa98 --- /dev/null +++ b/src/core/Ropes.h @@ -0,0 +1,31 @@ +#pragma once + +class CRope +{ +public: + bool m_bActive; + bool m_bWasRegistered; + bool m_unk; + uintptr m_id; + uint32 m_updateTimer; + CVector m_pos[32]; + CVector m_speed[32]; + + void Update(void); + void Render(void); +}; + +class CRopes +{ + static CRope aRopes[8]; + +public: + + static void Init(void); + static void Update(void); + static void Render(void); + static bool RegisterRope(uintptr id, CVector pos, bool setUpdateTimer); + static void SetSpeedOfTopNode(uintptr id, CVector speed); + static bool FindCoorsAlongRope(uintptr id, float t, CVector *coors); + static bool CreateRopeWithSwatComingDown(CVector pos); +}; diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 86423b0a..dd122477 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -84,6 +84,7 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_nRoadblockNode = -1; // TODO(Miami): this will be nil m_bThrowsSpikeTrap = false; field_5FF = 0; + m_pRopeEntity = nil; m_fAbseilPos = 0.0f; m_bBeatingSuspect = false; m_pPointGunAt = nil; diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index 50d8165f..e48984ff 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -26,6 +26,8 @@ public: float m_fAbseilPos; eCopType m_nCopType; bool m_bThrowsSpikeTrap; + CEntity *m_pRopeEntity; // CHeli or 1 + uintptr m_nRopeID; int32 field_624; int8 field_628; diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index 4771d8a4..e4aff5c4 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -65,7 +65,7 @@ CPlaneTrail::Render(float visibility) RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); - if(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV)){ + if(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, TrailIndices, (numVerts-1)*2); RwIm3DEnd(); } @@ -238,7 +238,7 @@ CPlaneBanner::Render(void) RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[2])); #ifdef FIX_BUGS - if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV)){ + if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV|rwIM3D_VERTEXRGBA)){ #else if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 0)){ #endif diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 1e0a8c27..408fb8f9 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -14,20 +14,26 @@ #include "Shadows.h" #include "Coronas.h" #include "Explosion.h" +#include "WindModifiers.h" #include "Timecycle.h" #include "TempColModels.h" #include "World.h" #include "WaterLevel.h" +#include "Population.h" #include "PlayerPed.h" +#include "CopPed.h" #include "Wanted.h" #include "DMAudio.h" #include "Object.h" #include "HandlingMgr.h" +#include "Ropes.h" #include "Heli.h" #ifdef FIX_BUGS #include "Replay.h" #endif +//--MIAMI: done + enum { HELI_STATUS_HOVER, @@ -40,7 +46,6 @@ enum CHeli *CHeli::pHelis[NUM_HELIS]; int16 CHeli::NumRandomHelis; uint32 CHeli::TestForNewRandomHelisTimer; -int16 CHeli::NumScriptHelis; // unused bool CHeli::CatalinaHeliOn; bool CHeli::CatalinaHasBeenShotDown; bool CHeli::ScriptHeliOn; @@ -67,6 +72,9 @@ CHeli::CHeli(int32 id, uint8 CreatedBy) m_nBulletDamage = 0; m_fAngularSpeed = 0.0f; m_fRotation = 0.0f; + + m_numSwat = 4; + m_nSearchLightTimer = CTimer::GetTimeInMilliseconds(); for(i = 0; i < 6; i++){ m_aSearchLightHistoryX[i] = 0.0f; @@ -82,6 +90,8 @@ CHeli::CHeli(int32 id, uint8 CreatedBy) m_fTargetOffset = 0.0f; m_fSearchLightX = m_fSearchLightY = 0.0f; + m_aSwatState[0] = m_aSwatState[1] = m_aSwatState[2] = m_aSwatState[3] = 0; + // BUG: not in game but gets initialized to CDCDCDCD in debug m_nLastShotTime = 0; } @@ -120,6 +130,8 @@ CHeli::ProcessControl(void) if(gbModelViewer) return; + CWindModifiers::RegisterOne(GetPosition(), 1); + // Find target CVector target(0.0f, 0.0f, 0.0f); CVector2D vTargetDist; @@ -266,7 +278,9 @@ CHeli::ProcessControl(void) if(fTargetDist > targetHeight) m_heliStatus = HELI_STATUS_CHASE_PLAYER; } - // fall through, BUG? + if(m_numSwat) + SendDownSwat(); + break; case HELI_STATUS_CHASE_PLAYER:{ float targetHeight; if(m_heliType == HELI_TYPE_CATALINA) @@ -277,6 +291,7 @@ CHeli::ProcessControl(void) fTargetDist < targetHeight && CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)) m_heliStatus = HELI_STATUS_HOVER; } + break; } // Find xy speed @@ -346,13 +361,6 @@ CHeli::ProcessControl(void) if(m_fTargetOffset >= 2.0f) m_fTargetOffset -= 2.0f; - if(m_heliType == HELI_TYPE_CATALINA) - if(m_pathState == 9 || m_pathState == 11 || m_pathState == 10){ - float f = Pow(0.997f, CTimer::GetTimeStep()); - m_vecMoveSpeed.x *= f; - m_vecMoveSpeed.y *= f; - } - CVector2D speedDir = targetSpeed - m_vecMoveSpeed; float speedDiff = speedDir.Magnitude(); if(speedDiff != 0.0f) @@ -457,7 +465,7 @@ CHeli::ProcessControl(void) else if (searchLightDist < 40.0f) m_fSearchLightIntensity = 1.0f; else - m_fSearchLightIntensity = 1.0f - (40.0f - searchLightDist) / 40.0f; + m_fSearchLightIntensity = 1.0f - (40.0f - searchLightDist) / (60.0f-40.0f); if (m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x - m_fSearchLightX) + sq(FindPlayerCoors().y - m_fSearchLightY) > sq(7.0f)) m_nShootTimer = CTimer::GetTimeInMilliseconds(); @@ -524,28 +532,17 @@ CHeli::ProcessControl(void) } } - // Drop Catalina's bombs - if(m_heliType == HELI_TYPE_CATALINA && m_pathState > 8 && (CTimer::GetTimeInMilliseconds()>>9) != (CTimer::GetPreviousTimeInMilliseconds()>>9)){ - CVector bombPos = GetPosition() - 60.0f*m_vecMoveSpeed; - if(sq(FindPlayerCoors().x-bombPos.x) + sq(FindPlayerCoors().y-bombPos.y) < sq(35.0f)){ - bool found; - float groundZ = CWorld::FindGroundZFor3DCoord(bombPos.x, bombPos.y, bombPos.z, &found); - float waterZ; - if(!CWaterLevel::GetWaterLevelNoWaves(bombPos.x, bombPos.y, bombPos.z, &waterZ)) - waterZ = 0.0f; - if(groundZ > waterZ){ - bombPos.z = groundZ + 2.0f; - CExplosion::AddExplosion(nil, this, EXPLOSION_HELI_BOMB, bombPos, 0); - }else{ - bombPos.z = waterZ; - CVector dir; - for(i = 0; i < 16; i++){ - dir.x = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f; - dir.y = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f; - dir.z = 0.5f; - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, bombPos, dir, nil, 0.2f); - } - } + // Process ropes + for(i = 0; i < 4; i++){ + if(m_aSwatState[i] == 0) + continue; + + m_aSwatState[i]--; + CRopes::RegisterRope((uintptr)this + i, GetMatrix()*FindSwatPositionRelativeToHeli(i), false); + if(m_aSwatState[i] == 0){ + CVector speed = Multiply3x3(GetMatrix(), 0.05f*FindSwatPositionRelativeToHeli(i)); + speed.z = 0.0f; + CRopes::SetSpeedOfTopNode((uintptr)this + i, speed); } } @@ -664,6 +661,7 @@ CHeli::SpawnFlyingComponent(int32 component) RpAtomicSetFrame(atomic, frame); CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); obj->AttachToRwObject((RwObject*)atomic); + obj->bDontStream = true; // init object obj->m_fMass = 10.0f; @@ -709,6 +707,42 @@ CHeli::SpawnFlyingComponent(int32 component) return obj; } +CVector +CHeli::FindSwatPositionRelativeToHeli(int n) +{ + switch(n){ + case 0: return CVector(-1.2f, -1.0f, -0.5f); + case 1: return CVector( 1.2f, -1.0f, -0.5f); + case 2: return CVector(-1.2f, 1.0f, -0.5f); + case 3: return CVector( 1.2f, 1.0f, -0.5f); + default: return CVector(0.0f, 0.0f, 0.0f); + } +} + +bool +CHeli::SendDownSwat(void) +{ + if(m_numSwat == 0 || !CStreaming::HasModelLoaded(MI_SWAT) || + CGeneral::GetRandomNumber() & 0x7F || (GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f) + return false; + + CMatrix mat(GetMatrix()); + CVector pos = Multiply3x3(mat, FindSwatPositionRelativeToHeli(m_numSwat-1)) + GetPosition(); + + float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, nil); + if(Abs(FindPlayerCoors().z - groundZ) < 2.5f && CRopes::RegisterRope((uintptr)this + m_numSwat-1, pos, false)){ + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + swat->bUsesCollision = false; + swat->m_pRopeEntity = this; + RegisterReference(&swat->m_pRopeEntity); + m_numSwat--; + swat->m_nRopeID = m_numSwat; + m_aSwatState[m_numSwat] = 255; + CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_ABSEIL, 4.0f); + return true; + } + return false; +} void @@ -718,7 +752,6 @@ CHeli::InitHelis(void) NumRandomHelis = 0; TestForNewRandomHelisTimer = 0; - NumScriptHelis = 0; CatalinaHeliOn = false; ScriptHeliOn = false; for(i = 0; i < NUM_HELIS; i++) @@ -734,17 +767,20 @@ GenerateHeli(bool catalina) CVector heliPos; int i; - heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE); + if(catalina) + assert(0 && "can't create catalina's heli"); + else + heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE); if(catalina) heliPos = CVector(-224.0f, 201.0f, 83.0f); else{ heliPos = FindPlayerCoors(); - float angle = (float)(CGeneral::GetRandomNumber() & 0xFF)/0xFF * 6.28f; + float angle = (float)(CGeneral::GetRandomNumber() & 0xFF)/0x100 * 6.28f; heliPos.x += 250.0f*Sin(angle); heliPos.y += 250.0f*Cos(angle); - if(heliPos.x < -2000.0f || heliPos.x > 2000.0f || heliPos.y < -2000.0f || heliPos.y > 2000.0f){ - // directly above player + if(heliPos.x < -2000.0f-400.0f || heliPos.x > 2000.0f-400.0f || heliPos.y < -2000.0f || heliPos.y > 2000.0f){ + heliPos = FindPlayerCoors(); heliPos.x -= 250.0f*Sin(angle); heliPos.y -= 250.0f*Cos(angle); } @@ -755,6 +791,7 @@ GenerateHeli(bool catalina) heli->GetMatrix().SetRotateZOnly(DEGTORAD(270.0f)); // game actually uses 3.14 here heli->SetStatus(STATUS_ABANDONED); + heli->bIsLocked = true; int id = -1; bool found = false; @@ -783,6 +820,8 @@ CHeli::UpdateHelis(void) CReplay::IsPlayingBack() ? 0 : #endif FindPlayerPed()->m_pWanted->NumOfHelisRequired(); + if(CCullZones::PlayerNoRain() || CGame::IsInInterior()) + numHelisRequired = 0; if(CStreaming::HasModelLoaded(MI_CHOPPER) && CTimer::GetTimeInMilliseconds() > TestForNewRandomHelisTimer){ // Spawn a police heli TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 15000; @@ -831,7 +870,7 @@ CHeli::UpdateHelis(void) TheCamera.CamShake(0.7f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z); colors[0] = CRGBA(0, 0, 0, 255); - colors[1] = CRGBA(224, 230, 238, 255); + colors[1] = CRGBA(224, 224, 224, 255); colors[2] = CRGBA(0, 0, 0, 255); colors[3] = CRGBA(0, 0, 0, 255); colors[4] = CRGBA(66, 162, 252, 255); @@ -851,7 +890,7 @@ CHeli::UpdateHelis(void) int f = ++nFrameGen & 3; CParticle::AddParticle(PARTICLE_HELI_DEBRIS, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); + colors[nFrameGen&7], rotSpeed, 0, f, 0); } CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0); @@ -869,8 +908,7 @@ CHeli::UpdateHelis(void) if(i == HELI_CATALINA) CatalinaHasBeenShotDown = true; - CStats::HelisDestroyed++; - CStats::PeopleKilledByOthers += 2; + CStats::PeopleKilledByPlayer += 2; CStats::PedsKilledOfThisType[PEDTYPE_COP] += 2; CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250; pos = CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition(); @@ -888,8 +926,8 @@ CHeli::UpdateHelis(void) TheCamera.CamShake(0.4f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z); - CVector pos = pHelis[i]->GetPosition() - 2.5f*pHelis[i]->GetUp(); - CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0); + CVector pos = pHelis[i]->GetPosition() - 2.5f*pHelis[i]->GetForward(); + CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI2, pos, 0); }else pHelis[i]->m_fAngularSpeed *= 1.03f; } @@ -904,7 +942,7 @@ CHeli::UpdateHelis(void) pHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY; } - // Remove all helis if in a tunnel + // Remove all helis if in a tunnel or under water if(FindPlayerCoors().z < - 2.0f) for(i = 0; i < NUM_HELIS; i++) if(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_SHOT_DOWN) @@ -949,7 +987,7 @@ CHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, i float distToHeli = (pHelis[i]->GetPosition() - *line0).Magnitude(); CVector line = (*line1 - *line0); float lineLength = line.Magnitude(); - *bulletPos = *line0 + line*Max(1.0f, distToHeli-5.0f); + *bulletPos = *line0 + line*Max(1.0f, distToHeli-5.0f)/lineLength; pHelis[i]->m_nBulletDamage += damage; @@ -965,6 +1003,26 @@ CHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, i return hit; } +bool +CHeli::TestSniperCollision(CVector *line0, CVector *line1) +{ + int i; + bool hit = false; + + for(i = 0; i < NUM_HELIS; i++){ + CVector pilotPos = pHelis[i]->GetMatrix() * CVector(-0.43f, 1.49f, 1.5f); + if(pHelis[i] && !pHelis[i]->bBulletProof && CCollision::DistToLine(line0, line1, &pilotPos) < 0.8f){ + pHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f; + pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN; + pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 9999999; + pHelis[i]->m_numSwat = 0; + + hit = true; + } + } + return hit; +} + void CHeli::StartCatalinaFlyBy(void) { CatalinaHeliOn = true; diff --git a/src/vehicles/Heli.h b/src/vehicles/Heli.h index a8f604aa..1f372e42 100644 --- a/src/vehicles/Heli.h +++ b/src/vehicles/Heli.h @@ -21,7 +21,7 @@ enum HELI_RANDOM0, HELI_RANDOM1, HELI_SCRIPT, - HELI_CATALINA, + HELI_CATALINA, // TODO 2 in VC NUM_HELIS }; @@ -36,7 +36,6 @@ enum class CHeli : public CVehicle { public: - // 0x288 RwFrame *m_aHeliNodes[NUM_HELI_NODES]; int8 m_heliStatus; float m_fSearchLightX; @@ -49,6 +48,8 @@ public: int8 m_nHeliId; int8 m_heliType; int8 m_pathState; + int8 m_numSwat; + uint8 m_aSwatState[4]; float m_aSearchLightHistoryX[6]; float m_aSearchLightHistoryY[6]; uint32 m_nSearchLightTimer; @@ -64,7 +65,6 @@ public: static CHeli *pHelis[NUM_HELIS]; static int16 NumRandomHelis; static uint32 TestForNewRandomHelisTimer; - static int16 NumScriptHelis; // unused static bool CatalinaHeliOn; static bool CatalinaHasBeenShotDown; static bool ScriptHeliOn; @@ -79,12 +79,15 @@ public: void PreRenderAlways(void); CObject *SpawnFlyingComponent(int32 component); + CVector FindSwatPositionRelativeToHeli(int n); + bool SendDownSwat(void); static void InitHelis(void); static void UpdateHelis(void); static void SpecialHeliPreRender(void); static bool TestRocketCollision(CVector *coors); static bool TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, int32 damage); + static bool TestSniperCollision(CVector *line0, CVector *line1); static void StartCatalinaFlyBy(void); static void RemoveCatalinaHeli(void); From 6b7a8f96a6763e9f0f9e94185afe097cb63984ae Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 27 Jul 2020 15:38:34 +0200 Subject: [PATCH 81/85] CCollision done and fixes --- src/core/Collision.cpp | 367 +++++++++++++++++++++------------------ src/core/Collision.h | 31 +++- src/core/FileLoader.cpp | 10 +- src/core/SurfaceTable.h | 35 ++++ src/core/config.h | 3 +- src/render/Glass.cpp | 16 +- src/vehicles/Vehicle.cpp | 10 +- 7 files changed, 272 insertions(+), 200 deletions(-) diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index fd172cb8..639962d0 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -107,8 +107,11 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) void CCollision::SortOutCollisionAfterLoad(void) { + CColStore::LoadCollision(TheCamera.GetPosition()); + CStreaming::LoadAllRequestedModels(false); } +//--MIAMI: done void CCollision::LoadCollisionScreen(eLevelName level) { @@ -251,7 +254,7 @@ CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box) } bool -CCollision::TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) +CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) { float t; CVector normal; @@ -266,9 +269,9 @@ CCollision::TestLineTriangle(const CColLine &line, const CVector *verts, const C // find point of intersection CVector p = line.p0 + (line.p1-line.p0)*t; - const CVector &va = verts[tri.a]; - const CVector &vb = verts[tri.b]; - const CVector &vc = verts[tri.c]; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); CVector2D vec1, vec2, vec3, vect; // We do the test in 2D. With the plane direction we @@ -361,15 +364,16 @@ CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph) bool CCollision::TestSphereTriangle(const CColSphere &sphere, - const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane) { // If sphere and plane don't intersect, no collision - if(Abs(plane.CalcPoint(sphere.center)) > sphere.radius) + float planedist = plane.CalcPoint(sphere.center); + if(Abs(planedist) > sphere.radius) return false; - const CVector &va = verts[tri.a]; - const CVector &vb = verts[tri.b]; - const CVector &vc = verts[tri.c]; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); // calculate two orthogonal basis vectors for the triangle CVector vec2 = vb - va; @@ -393,28 +397,36 @@ CCollision::TestSphereTriangle(const CColSphere &sphere, int testcase = insideAB + insideAC + insideBC; float dist = 0.0f; - if(testcase == 1){ + switch(testcase){ + case 0: + return false; // shouldn't happen + case 1: // closest to a vertex if(insideAB) dist = (sphere.center - vc).Magnitude(); else if(insideAC) dist = (sphere.center - vb).Magnitude(); else if(insideBC) dist = (sphere.center - va).Magnitude(); else assert(0); - }else if(testcase == 2){ + break; + case 2: // closest to an edge + // looks like original game as DistToLine manually inlined if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center); else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center); else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center); else assert(0); - }else if(testcase == 3){ + break; + case 3: // center is in triangle - return true; - }else - assert(0); // front fell off + dist = Abs(planedist); + break; + default: + assert(0); + } return dist < sphere.radius; } -//--MIAMI: TODO +//--MIAMI: DONE bool CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough) { @@ -429,25 +441,32 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod if(!TestLineBox(newline, model.boundingBox)) return false; - for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) - if(TestLineSphere(newline, model.spheres[i])) - return true; + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue; + if(TestLineSphere(newline, model.spheres[i])) + return true; + } - for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) - if(TestLineBox(newline, model.boxes[i])) - return true; + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue; + if(TestLineBox(newline, model.boxes[i])) + return true; + } CalculateTrianglePlanes(&model); - for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) - if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) - return true; + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue; + if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i])) + return true; + } return false; } +// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used // // Process @@ -716,18 +735,19 @@ CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CC return true; } +//--MIAMI: unused bool CCollision::ProcessVerticalLineTriangle(const CColLine &line, - const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly) { float t; CVector normal; const CVector &p0 = line.p0; - const CVector &va = verts[tri.a]; - const CVector &vb = verts[tri.b]; - const CVector &vc = verts[tri.c]; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); // early out bound rect test if(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false; @@ -792,6 +812,7 @@ CCollision::ProcessVerticalLineTriangle(const CColLine &line, if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; + if(t >= mindist) return false; point.point = p; point.normal = normal; point.surfaceA = 0; @@ -817,16 +838,12 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol return false; // maybe inlined? - CColTriangle tri; - tri.a = 0; - tri.b = 1; - tri.c = 2; CColTrianglePlane plane; - plane.Set(poly->verts, tri); + plane.Set(poly->verts[0], poly->verts[1], poly->verts[2]); - const CVector &va = poly->verts[tri.a]; - const CVector &vb = poly->verts[tri.b]; - const CVector &vc = poly->verts[tri.c]; + const CVector &va = poly->verts[0]; + const CVector &vb = poly->verts[1]; + const CVector &vc = poly->verts[2]; CVector p0 = pos; CVector p1(pos.x, pos.y, z); @@ -891,8 +908,8 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol bool CCollision::ProcessLineTriangle(const CColLine &line , - const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, - CColPoint &point, float &mindist) + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + CColPoint &point, float &mindist, CStoredCollPoly *poly) { float t; CVector normal; @@ -910,9 +927,9 @@ CCollision::ProcessLineTriangle(const CColLine &line , // find point of intersection CVector p = line.p0 + (line.p1-line.p0)*t; - const CVector &va = verts[tri.a]; - const CVector &vb = verts[tri.b]; - const CVector &vc = verts[tri.c]; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); CVector2D vec1, vec2, vec3, vect; switch(plane.dir){ @@ -958,19 +975,26 @@ CCollision::ProcessLineTriangle(const CColLine &line , if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false; if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false; if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false; + if(t >= mindist) return false; point.point = p; point.normal = normal; point.surfaceA = 0; point.pieceA = 0; point.surfaceB = tri.surface; point.pieceB = 0; + if(poly){ + poly->verts[0] = va; + poly->verts[1] = vb; + poly->verts[2] = vc; + poly->valid = true; + } mindist = t; return true; } bool CCollision::ProcessSphereTriangle(const CColSphere &sphere, - const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, + const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq) { // If sphere and plane don't intersect, no collision @@ -979,9 +1003,9 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, if(Abs(planedist) > sphere.radius || distsq > mindistsq) return false; - const CVector &va = verts[tri.a]; - const CVector &vb = verts[tri.b]; - const CVector &vc = verts[tri.c]; + const CVector &va = verts[tri.a].Get(); + const CVector &vb = verts[tri.b].Get(); + const CVector &vc = verts[tri.c].Get(); // calculate two orthogonal basis vectors for the triangle CVector normal; @@ -1008,25 +1032,33 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, int testcase = insideAB + insideAC + insideBC; float dist = 0.0f; CVector p; - if(testcase == 1){ + switch(testcase){ + case 0: + return false; // shouldn't happen + case 1: // closest to a vertex if(insideAB) p = vc; else if(insideAC) p = vb; else if(insideBC) p = va; else assert(0); dist = (sphere.center - p).Magnitude(); - }else if(testcase == 2){ + break; + case 2: // closest to an edge + // looks like original game as DistToLine manually inlined if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p); else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p); else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p); else assert(0); - }else if(testcase == 3){ + break; + case 3: // center is in triangle dist = Abs(planedist); p = sphere.center - normal*planedist; - }else - assert(0); // front fell off + break; + default: + assert(0); + } if(dist >= sphere.radius || dist*dist >= mindistsq) return false; @@ -1061,18 +1093,24 @@ CCollision::ProcessLineOfSight(const CColLine &line, return false; float coldist = mindist; - for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessLineSphere(newline, model.spheres[i], point, coldist); + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue; + ProcessLineSphere(newline, model.spheres[i], point, coldist); + } - for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessLineBox(newline, model.boxes[i], point, coldist); + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue; + ProcessLineBox(newline, model.boxes[i], point, coldist); + } CalculateTrianglePlanes(&model); - for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue; + if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue; + ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist); + } if(coldist < mindist){ point.point = matrix * point.point; @@ -1095,31 +1133,33 @@ CCollision::ProcessVerticalLine(const CColLine &line, // transform line to model space // Why does the game seem to do this differently than above? CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1)); - newline.p1.x = newline.p0.x; - newline.p1.y = newline.p0.y; - if(!TestVerticalLineBox(newline, model.boundingBox)) + if(!TestLineBox(newline, model.boundingBox)) return false; + // BUG? is IsSeeThroughVertical really the right thing? also not checking shoot through float coldist = mindist; - for(i = 0; i < model.numSpheres; i++) - if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessLineSphere(newline, model.spheres[i], point, coldist); + for(i = 0; i < model.numSpheres; i++){ + if(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue; + ProcessLineSphere(newline, model.spheres[i], point, coldist); + } - for(i = 0; i < model.numBoxes; i++) - if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessLineBox(newline, model.boxes[i], point, coldist); + for(i = 0; i < model.numBoxes; i++){ + if(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue; + ProcessLineBox(newline, model.boxes[i], point, coldist); + } CalculateTrianglePlanes(&model); TempStoredPoly.valid = false; - for(i = 0; i < model.numTriangles; i++) - if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH) - ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); + for(i = 0; i < model.numTriangles; i++){ + if(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue; + ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly); + } if(coldist < mindist){ point.point = matrix * point.point; point.normal = Multiply3x3(matrix, point.normal); - if(poly && TempStoredPoly.valid){ + if(TempStoredPoly.valid && poly){ *poly = TempStoredPoly; poly->verts[0] = matrix * poly->verts[0]; poly->verts[1] = matrix * poly->verts[1]; @@ -1353,6 +1393,15 @@ CCollision::CalculateTrianglePlanes(CColModel *model) } } +void +CCollision::RemoveTrianglePlanes(CColModel *model) +{ + if(model->trianglePlanes){ + ms_colModelCache.Remove(model->GetLinkPtr()); + model->RemoveTrianglePlanes(); + } +} + void CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) { @@ -1575,15 +1624,75 @@ CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel) RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); } +static void +GetSurfaceColor(uint8 surf, uint8 &r, uint8 &g, uint8 &b) +{ + // game doesn't do this + r = 255; + g = 128; + b = 0; + + switch(CSurfaceTable::GetAdhesionGroup(surf)){ + case ADHESIVE_RUBBER: + r = 255; + g = 0; + b = 0; + break; + case ADHESIVE_HARD: + r = 255; + g = 255; + b = 128; + break; + case ADHESIVE_ROAD: + r = 128; + g = 128; + b = 128; + break; + case ADHESIVE_LOOSE: + r = 0; + g = 255; + b = 0; + break; + case ADHESIVE_SAND: + r = 255; + g = 128; + b = 128; + break; + case ADHESIVE_WET: + r = 0; + g = 0; + b = 255; + break; + } + + if(surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){ + r = 255; + g = 255; + b = 0; + } + + float f = (surf & 0xF)/32.0f + 0.5f; + r *= f; + g *= f; + b *= f; + + if(surf == SURFACE_TRANSPARENT_CLOTH || surf == SURFACE_METAL_CHAIN_FENCE || + surf == SURFACE_TRANSPARENT_STONE || surf == SURFACE_SCAFFOLD_POLE) + if(CTimer::GetFrameCounter() & 1){ + r = 0; + g = 0; + b = 0; + } +} + void CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id) { int i; int s; - float f; CVector verts[8]; CVector min, max; - int r, g, b; + uint8 r, g, b; RwImVertexIndex *iptr; RwIm3DVertex *vptr; @@ -1602,53 +1711,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, verts[1] = mat * verts[1]; verts[2] = mat * verts[2]; - // game doesn't do this - r = 255; - g = 128; - b = 0; - s = colModel.triangles[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } + GetSurfaceColor(s, r, g, b); if(s > SURFACE_METAL_GATE){ r = CGeneral::GetRandomNumber(); @@ -1689,47 +1753,7 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, verts[7] = mat * CVector(max.x, max.y, max.z); s = colModel.boxes[i].surface; - f = (s & 0xF)/32.0f + 0.5f; - switch(CSurfaceTable::GetAdhesionGroup(s)){ - case ADHESIVE_RUBBER: - r = f * 255.0f; - g = 0; - b = 0; - break; - case ADHESIVE_HARD: - r = f*255.0f; - g = f*255.0f; - b = f*128.0f; - break; - case ADHESIVE_ROAD: - r = f*128.0f; - g = f*128.0f; - b = f*128.0f; - break; - case ADHESIVE_LOOSE: - r = 0; - g = f * 255.0f; - b = 0; - break; - case ADHESIVE_WET: - r = 0; - g = 0; - b = f * 255.0f; - break; - default: - // this doesn't make much sense - r *= f; - g *= f; - b *= f; - } - - if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE || - s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE) - if(CTimer::GetFrameCounter() & 1){ - r = 0; - g = 0; - b = 0; - } + GetSurfaceColor(s, r, g, b); RenderBuffer::StartStoring(36, 8, &iptr, &vptr); RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255); @@ -1833,7 +1857,7 @@ CColLine::Set(const CVector &p0, const CVector &p1) } void -CColTriangle::Set(const CVector *, int a, int b, int c, uint8 surf, uint8 piece) +CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece) { this->a = a; this->b = b; @@ -1842,12 +1866,8 @@ CColTriangle::Set(const CVector *, int a, int b, int c, uint8 surf, uint8 piece) } void -CColTrianglePlane::Set(const CVector *v, CColTriangle &tri) +CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc) { - const CVector &va = v[tri.a]; - const CVector &vb = v[tri.b]; - const CVector &vc = v[tri.c]; - normal = CrossProduct(vc-va, vb-va); normal.Normalise(); dist = DotProduct(normal, va); @@ -1905,6 +1925,7 @@ CColModel::RemoveCollisionVolumes(void) RwFree(boxes); RwFree(vertices); RwFree(triangles); + CCollision::RemoveTrianglePlanes(this); } numSpheres = 0; numLines = 0; @@ -1950,7 +1971,7 @@ CColModel::GetLinkPtr(void) void CColModel::GetTrianglePoint(CVector &v, int i) const { - v = vertices[i]; + v = vertices[i].Get(); } CColModel& @@ -2029,7 +2050,7 @@ CColModel::operator=(const CColModel &other) if(vertices) RwFree(vertices); if(numVerts){ - vertices = (CVector*)RwMalloc(numVerts*sizeof(CVector)); + vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector)); for(i = 0; i < numVerts; i++) vertices[i] = other.vertices[i]; } diff --git a/src/core/Collision.h b/src/core/Collision.h index 09abaa1c..eb11d8c4 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -10,6 +10,19 @@ #define MAX_COLLISION_POINTS 32 #endif +struct CompressedVector +{ +#ifdef COMPRESSED_COL_VECTORS + int16 x, y, z; + CVector Get(void) const { return CVector(x, y, z)/128.0f; }; + void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; }; +#else + float x, y, z; + CVector Get(void) const { return CVector(x, y, z); }; + void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; }; +#endif +}; + struct CSphere { CVector center; @@ -63,7 +76,7 @@ struct CColTriangle uint16 c; uint8 surface; - void Set(const CVector *v, int a, int b, int c, uint8 surf, uint8 piece); + void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece); }; struct CColTrianglePlane @@ -72,7 +85,8 @@ struct CColTrianglePlane float dist; uint8 dir; - void Set(const CVector *v, CColTriangle &tri); + void Set(const CVector &va, const CVector &vb, const CVector &vc); + void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); } void GetNormal(CVector &n) const { n = normal; } float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; }; }; @@ -113,7 +127,7 @@ struct CColModel CColSphere *spheres; CColLine *lines; CColBox *boxes; - CVector *vertices; + CompressedVector *vertices; CColTriangle *triangles; CColTrianglePlane *trianglePlanes; @@ -145,24 +159,25 @@ public: static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id); static void CalculateTrianglePlanes(CColModel *model); + static void RemoveTrianglePlanes(CColModel *model); // all these return true if there's a collision static bool TestSphereSphere(const CSphere &s1, const CSphere &s2); static bool TestSphereBox(const CSphere &sph, const CBox &box); static bool TestLineBox(const CColLine &line, const CBox &box); static bool TestVerticalLineBox(const CColLine &line, const CBox &box); - static bool TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); + static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); static bool TestLineSphere(const CColLine &line, const CColSphere &sph); - static bool TestSphereTriangle(const CColSphere &sphere, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); + static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane); static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough); static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq); static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq); static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist); - static bool ProcessVerticalLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly); - static bool ProcessLineTriangle(const CColLine &line , const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist); + static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly); + static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly = nil); static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist); - static bool ProcessSphereTriangle(const CColSphere &sph, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); + static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq); static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough); static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly); static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists); diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 86ebb5dd..635192ea 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -326,13 +326,13 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) int32 numVertices = *(int16*)buf; buf += 4; if(numVertices > 0){ - model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector)); + model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector)); for(i = 0; i < numVertices; i++){ - model.vertices[i] = *(CVector*)buf; + model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8)); #if 0 - if(Abs(model.vertices[i].x) >= 256.0f || - Abs(model.vertices[i].y) >= 256.0f || - Abs(model.vertices[i].z) >= 256.0f) + if(Abs(*(float*)buf) >= 256.0f || + Abs(*(float*)(buf+4)) >= 256.0f || + Abs(*(float*)(buf+8)) >= 256.0f) printf("%s:Collision volume too big\n", modelname); #endif buf += 12; diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index d8f9be3d..359ebd5c 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -53,6 +53,41 @@ enum struct CColPoint; +inline bool +IsSeeThrough(uint8 surfType) +{ + switch(surfType) + case SURFACE_GLASS: + case SURFACE_TRANSPARENT_CLOTH: + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_SCAFFOLD_POLE: + return true; + return false; +} + +// I think the necessity of this function is really a bug +inline bool +IsSeeThroughVertical(uint8 surfType) +{ + switch(surfType) + case SURFACE_GLASS: + case SURFACE_TRANSPARENT_CLOTH: + return true; + return false; +} + +inline bool +IsShootThrough(uint8 surfType) +{ + switch(surfType) + case SURFACE_METAL_CHAIN_FENCE: + case SURFACE_TRANSPARENT_STONE: + case SURFACE_SCAFFOLD_POLE: + return true; + return false; +} + class CSurfaceTable { static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS]; diff --git a/src/core/config.h b/src/core/config.h index e67db1a3..c9c65051 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -54,7 +54,7 @@ enum Config { NUMBOATALPHALIST = 20, NUMALPHAENTITYLIST = 200, NUMALPHAUNTERWATERENTITYLIST = 30, - NUMCOLCACHELINKS = 200, + NUMCOLCACHELINKS = 50, NUMREFERENCES = 800, // Zones @@ -166,6 +166,7 @@ enum Config { #if defined GTA_PS2 # define GTA_PS2_STUFF # define RANDOMSPLASH +# define COMPRESSED_COL_VECTORS #elif defined GTA_PC # define GTA3_1_1_PATCH //# define GTA3_STEAM_PATCH diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index ac892ddb..ee36bad3 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -424,10 +424,10 @@ CGlass::RenderEntityInGlass(CEntity *entity) ASSERT(col!=nil); if ( col->numTriangles >= 2 ) { - CVector a = object->GetMatrix() * col->vertices[0]; - CVector b = object->GetMatrix() * col->vertices[1]; - CVector c = object->GetMatrix() * col->vertices[2]; - CVector d = object->GetMatrix() * col->vertices[3]; + CVector a = object->GetMatrix() * col->vertices[0].Get(); + CVector b = object->GetMatrix() * col->vertices[1].Get(); + CVector c = object->GetMatrix() * col->vertices[2].Get(); + CVector d = object->GetMatrix() * col->vertices[3].Get(); if ( object->bGlassCracked ) { @@ -613,10 +613,10 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CColModel *col = object->GetColModel(); ASSERT(col!=nil); - CVector a = object->GetMatrix() * col->vertices[0]; - CVector b = object->GetMatrix() * col->vertices[1]; - CVector c = object->GetMatrix() * col->vertices[2]; - CVector d = object->GetMatrix() * col->vertices[3]; + CVector a = object->GetMatrix() * col->vertices[0].Get(); + CVector b = object->GetMatrix() * col->vertices[1].Get(); + CVector c = object->GetMatrix() * col->vertices[2].Get(); + CVector d = object->GetMatrix() * col->vertices[3].Get(); float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 2c296ee2..378a4c0a 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -2239,7 +2239,7 @@ CVehicle::DoSunGlare(void) int a2 = colmodel->triangles[i+1].a; int b2 = colmodel->triangles[i+1].b; int c2 = colmodel->triangles[i+1].c; - CVector vert1 = colmodel->vertices[a1]; + CVector vert1 = colmodel->vertices[a1].Get(); CVector vert4; // Need an upward surface if(vert1.z <= 0.0f) @@ -2250,23 +2250,23 @@ CVehicle::DoSunGlare(void) if(a2 != a1 && a2 != b1 && a2 != c1){ // a2 is not in tri1 numTri2Verts++; - vert4 = colmodel->vertices[a2]; + vert4 = colmodel->vertices[a2].Get(); } if(b2 != a1 && b2 != b1 && b2 != c1){ // b2 is not in tri1 numTri2Verts++; - vert4 = colmodel->vertices[b2]; + vert4 = colmodel->vertices[b2].Get(); } if(c2 != a1 && c2 != b1 && c2 != c1){ // c2 is not in tri1 numTri2Verts++; - vert4 = colmodel->vertices[c2]; + vert4 = colmodel->vertices[c2].Get(); } // Need exactly one vertex from tri2 for a quad with tri1 if(numTri2Verts != 1) continue; - CVector mid = (vert1 + colmodel->vertices[b1] + colmodel->vertices[c1] + vert4)/4.0f; + CVector mid = (vert1 + colmodel->vertices[b1].Get() + colmodel->vertices[c1].Get() + vert4)/4.0f; float dy = mid.y - vert1.y; float dx = mid.x - vert1.x; float dist = 1.4f * Min(Abs(dx), Abs(dy)); From c0eb3d10e2650a4518fa5967a1ae9e2d60e56d4f Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 27 Jul 2020 15:43:03 +0200 Subject: [PATCH 82/85] CCollision done and fixes --- src/core/Collision.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 639962d0..268e3c5e 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -23,6 +23,8 @@ #include "Camera.h" #include "ColStore.h" +//--MIAMI: file done + enum Direction { DIR_X_POS, @@ -36,7 +38,6 @@ enum Direction eLevelName CCollision::ms_collisionInMemory; CLinkList CCollision::ms_colModelCache; -//--MIAMI: done void CCollision::Init(void) { @@ -45,7 +46,6 @@ CCollision::Init(void) CColStore::Initialise(); } -//--MIAMI: done void CCollision::Shutdown(void) { @@ -53,7 +53,6 @@ CCollision::Shutdown(void) CColStore::Shutdown(); } -//--MIAMI: done void CCollision::Update(void) { @@ -97,13 +96,11 @@ GetCollisionInSector(CSector §) return (eLevelName)level; } -//--MIAMI: done void CCollision::LoadCollisionWhenINeedIt(bool forceChange) { } -//--MIAMI: done void CCollision::SortOutCollisionAfterLoad(void) { @@ -111,7 +108,6 @@ CCollision::SortOutCollisionAfterLoad(void) CStreaming::LoadAllRequestedModels(false); } -//--MIAMI: done void CCollision::LoadCollisionScreen(eLevelName level) { @@ -426,7 +422,6 @@ CCollision::TestSphereTriangle(const CColSphere &sphere, return dist < sphere.radius; } -//--MIAMI: DONE bool CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough) { @@ -1075,7 +1070,6 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere, return true; } -//--MIAMI: TODO bool CCollision::ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, @@ -1121,7 +1115,6 @@ CCollision::ProcessLineOfSight(const CColLine &line, return false; } -//--MIAMI: TODO bool CCollision::ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, From 429f6b03c44fe1df791865d976b456321b273859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 27 Jul 2020 16:04:05 +0300 Subject: [PATCH 83/85] CCopPed, except spike traps --- src/core/Game.cpp | 9 + src/core/Ropes.cpp | 12 +- src/core/main.cpp | 2 + src/peds/CopPed.cpp | 341 +++++++++++++++++++++++++------------- src/peds/CopPed.h | 7 +- src/peds/PedPlacement.cpp | 8 +- src/peds/PedPlacement.h | 2 +- src/vehicles/Heli.cpp | 4 +- 8 files changed, 256 insertions(+), 129 deletions(-) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 072bc7be..39bbd364 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -88,6 +88,7 @@ #include "Zones.h" #include "Occlusion.h" #include "debugmenu.h" +#include "Ropes.h" eLevelName CGame::currLevel; int32 CGame::currArea; @@ -403,9 +404,11 @@ bool CGame::Initialise(const char* datFile) CRubbish::Init(); CClouds::Init(); CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CBridge::Init(); CGarages::Init(); + LoadingScreen("Loading the Game", "Position dynamic objects", nil); LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); CTrain::InitTrains(); CPlane::InitPlanes(); @@ -416,6 +419,7 @@ bool CGame::Initialise(const char* datFile) if ( !TheMemoryCard.m_bWantToLoad ) { #endif + LoadingScreen("Loading the Game", "Start script", nil); CTheScripts::StartTestScript(); CTheScripts::Process(); TheCamera.Process(); @@ -426,6 +430,9 @@ bool CGame::Initialise(const char* datFile) CCollision::ms_collisionInMemory = currLevel; for (int i = 0; i < MAX_PADS; i++) CPad::GetPad(i)->Clear(true); + // TODO(Miami) + // DMAudio.SetStartingTrackPositions(1); + DMAudio.ChangeMusicMode(MUSICMODE_GAME); return true; } @@ -546,6 +553,7 @@ void CGame::ReInitGameObjectVariables(void) CRemote::Init(); #endif CSpecialFX::Init(); + CRopes::Init(); CWaterCannons::Init(); CParticle::ReloadConfig(); @@ -718,6 +726,7 @@ void CGame::Process(void) CGarages::Update(); CRubbish::Update(); CSpecialFX::Update(); + CRopes::Update(); CTimeCycle::Update(); if (CReplay::ShouldStandardCameraBeProcessed()) TheCamera.Process(); diff --git a/src/core/Ropes.cpp b/src/core/Ropes.cpp index 4c57f190..dbae9ee3 100644 --- a/src/core/Ropes.cpp +++ b/src/core/Ropes.cpp @@ -31,14 +31,14 @@ CRope::Update(void) for(i = 1; i < ARRAY_SIZE(m_pos); i++){ CVector prevPos = m_pos[i]; m_pos[i] += m_speed[i]*step*CTimer::GetTimeStep(); - m_pos[0].z -= 0.05f*CTimer::GetTimeStep(); + m_pos[i].z -= 0.05f*CTimer::GetTimeStep(); CVector dist = m_pos[i] - m_pos[i-1]; - m_pos[i] = m_pos[i-1] + dist/dist.Magnitude()*0.625f; + m_pos[i] = m_pos[i-1] + (0.625f/dist.Magnitude())*dist; m_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep(); } if(!m_bWasRegistered && m_pos[0].z < 0.0f) m_bActive = false; - m_bWasRegistered = true; + m_bWasRegistered = false; } void @@ -60,7 +60,11 @@ CRope::Render(void) RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); if(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){ +#ifdef FIX_BUGS RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#else + RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1)); +#endif RwIm3DEnd(); } } @@ -159,7 +163,7 @@ CRopes::CreateRopeWithSwatComingDown(CVector pos) if(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true)) return false; - CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos); swat->bUsesCollision = false; swat->m_pRopeEntity = (CEntity*)1; swat->m_nRopeID = 100 + ropeId; diff --git a/src/core/main.cpp b/src/core/main.cpp index 0ea95c6e..d4ef8c4b 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -62,6 +62,7 @@ #include "SceneEdit.h" #include "debugmenu.h" #include "Occlusion.h" +#include "Ropes.h" GlobalScene Scene; @@ -873,6 +874,7 @@ RenderEffects(void) CGlass::Render(); CWaterCannons::Render(); CSpecialFX::Render(); + CRopes::Render(); CShadows::RenderStaticShadows(); CShadows::RenderStoredShadows(); CSkidmarks::Render(); diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index dd122477..6c9eb276 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -16,6 +16,8 @@ #include "CarCtrl.h" #include "Renderer.h" #include "Camera.h" +#include "PedPlacement.h" +#include "Ropes.h" CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) { @@ -39,12 +41,13 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_wepAccuracy = 76; break; case COP_SWAT: + case COP_HELI_SWAT: SetModelIndex(MI_SWAT); GiveDelayedWeapon(WEAPONTYPE_UZI, 1000); SetCurrentWeapon(WEAPONTYPE_UZI); m_fArmour = 50.0f; m_wepSkills = 32; /* TODO: what is this? seems unused */ - m_wepAccuracy = 64; + m_wepAccuracy = 68; break; case COP_ARMY: SetModelIndex(MI_ARMY); @@ -77,18 +80,21 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) field_5FE = 1; m_bIsDisabledCop = false; m_attackTimer = 0; + m_bBeatingSuspect = false; m_bStopAndShootDisabledZone = false; field_601 = false; m_bZoneDisabled = false; field_628 = -1; m_nRoadblockNode = -1; // TODO(Miami): this will be nil m_bThrowsSpikeTrap = false; - field_5FF = 0; m_pRopeEntity = nil; m_fAbseilPos = 0.0f; - m_bBeatingSuspect = false; - m_pPointGunAt = nil; + m_nHassleTimer = 0; + field_61C = 0; field_624 = 0; + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt); + m_pPointGunAt = nil; } CCopPed::~CCopPed() @@ -96,24 +102,17 @@ CCopPed::~CCopPed() ClearPursuit(); } +// --MIAMI: Done // Parameter should always be CPlayerPed, but it seems they considered making civilians arrestable at some point void CCopPed::SetArrestPlayer(CPed *player) { if (!IsPedInControl() || !player) return; - /* - switch (m_nCopType) { - case COP_FBI: - Say(SOUND_PED_ARREST_FBI); - break; - case COP_SWAT: - Say(SOUND_PED_ARREST_SWAT); - break; - default: - Say(SOUND_PED_ARREST_COP); - break; - } */ + + player->Say(SOUND_PED_PLAYER_REACTTOCOP); + Say(SOUND_PED_ARREST_COP); + if (player->EnteringCar()) { if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) return; @@ -128,14 +127,14 @@ CCopPed::SetArrestPlayer(CPed *player) } else if (player->m_nPedState != PED_DIE && player->m_nPedState != PED_DEAD && player->m_nPedState != PED_ARRESTED) { player->m_nLastPedState = player->m_nPedState; - player->m_nPedState = PED_ARRESTED; + player->SetPedState(PED_ARRESTED); FindPlayerPed()->m_bCanBeDamaged = false; ((CPlayerPed*)player)->m_pArrestingCop = this; this->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop); } - m_nPedState = PED_ARREST_PLAYER; + SetPedState(PED_ARREST_PLAYER); SetObjective(OBJECTIVE_NONE); m_prevObjective = OBJECTIVE_NONE; bIsPointingGunAt = false; @@ -148,10 +147,11 @@ CCopPed::SetArrestPlayer(CPed *player) player->m_pMyVehicle->bIsHandbrakeOn = true; player->m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED); } - if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) + if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) SetCurrentWeapon(WEAPONTYPE_COLT45); } +// --MIAMI: Done void CCopPed::ClearPursuit(void) { @@ -190,6 +190,7 @@ CCopPed::ClearPursuit(void) bNotAllowedToDuck = false; bKindaStayInSamePlace = false; m_bStopAndShootDisabledZone = false; + field_601 = false; m_bZoneDisabled = false; ClearObjective(); if (IsPedInControl()) { @@ -207,10 +208,14 @@ CCopPed::ClearPursuit(void) } } +// --MIAMI: Done // TODO: I don't know why they needed that parameter. void CCopPed::SetPursuit(bool ignoreCopLimit) { + if (CTimer::GetTimeInMilliseconds() < field_61C) + return; + CWanted *wanted = FindPlayerPed()->m_pWanted; if (m_bIsInPursuit || !IsPedInControl()) return; @@ -236,6 +241,7 @@ CCopPed::SetPursuit(bool ignoreCopLimit) } } +// --MIAMI: Done void CCopPed::ArrestPlayer(void) { @@ -301,6 +307,7 @@ CCopPed::ScanForCrimes(void) } } +// --MIAMI: Done void CCopPed::CopAI(void) { @@ -318,11 +325,6 @@ CCopPed::CopAI(void) if (bHitSomethingLastFrame) { m_bZoneDisabled = true; m_bIsDisabledCop = true; -#ifdef FIX_BUGS - m_nRoadblockNode = -1; -#else - m_nRoadblockNode = 0; -#endif bKindaStayInSamePlace = true; bIsRunning = false; bNotAllowedToDuck = false; @@ -349,6 +351,27 @@ CCopPed::CopAI(void) } if (wantedLevel > 0) { if (!m_bIsDisabledCop) { + // Turn and shoot the player's vehicle, if possible + if (!m_bIsInPursuit && !GetWeapon()->IsTypeMelee() && FindPlayerVehicle() && m_fDistanceToTarget < CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange) { + if (FindPlayerVehicle()->m_vecMoveSpeed.Magnitude2D() > 0.1f) { + CVector2D distToVeh = GetPosition() - FindPlayerVehicle()->GetPosition(); + distToVeh.Normalise(); + CVector2D vehSpeed = FindPlayerVehicle()->m_vecMoveSpeed; + vehSpeed.Normalise(); + + if (DotProduct2D(distToVeh, vehSpeed) > 0.8f) { + SetLookFlag(playerOrHisVeh, true); + SetMoveState(PEDMOVE_STILL); + if (TurnBody()) { + SetAttack(FindPlayerVehicle()); + SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); + SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 300.0f)); + } + } else if (m_nPedState == PED_ATTACK) + RestorePreviousState(); + } + } + if (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) { CCopPed *copFarthestToTarget = nil; float copFarthestToTargetDist = m_fDistanceToTarget; @@ -391,11 +414,14 @@ CCopPed::CopAI(void) if (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) SetCurrentWeapon(WEAPONTYPE_COLT45); - else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) { + else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) { // i.e. if player is on top of car, cop will still use colt45. - SetCurrentWeapon(WEAPONTYPE_UNARMED); + SetCurrentWeapon(GetWeaponSlot(WEAPONTYPE_NIGHTSTICK) >= 0 ? WEAPONTYPE_NIGHTSTICK : WEAPONTYPE_UNARMED); } + if (m_bBeatingSuspect && GetWeapon()->m_eWeaponType == WEAPONTYPE_NIGHTSTICK) + Say(SOUND_PED_PULLOUTWEAPON); + if (FindPlayerVehicle()) { if (m_bBeatingSuspect) { --wanted->m_CopsBeatingSuspect; @@ -406,18 +432,18 @@ CCopPed::CopAI(void) } return; } - float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange; + SetCurrentWeapon(WEAPONTYPE_COLT45); + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); + float weaponRange = weaponInfo->m_fRange; SetLookFlag(playerOrHisVeh, true); TurnBody(); - SetCurrentWeapon(WEAPONTYPE_COLT45); - if (!bIsDucking) { + if (!bIsDucking || bCrouchWhenShooting && GetCrouchFireAnim(weaponInfo)) { if (m_attackTimer >= CTimer::GetTimeInMilliseconds()) { if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) { CVector targetDist = playerOrHisVeh->GetPosition() - GetPosition(); if (m_fDistanceToTarget > 30.0f) { - CAnimBlendAssociation* crouchShootAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT); - if (crouchShootAssoc) - crouchShootAssoc->blendDelta = -1000.0f; + if (bIsDucking) + ClearDuck(); // Target is coming onto us if (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) { @@ -435,42 +461,23 @@ CCopPed::CopAI(void) bNotAllowedToDuck = false; bDuckAndCover = false; } else { - // VC checks for != nil compared to buggy behaviour of III. I check for != -1 here. -#ifdef VC_PED_PORTS + // TODO(Miami): Roadblock system is still III float dotProd; if (m_nRoadblockNode != -1) { - // TODO(MIAMI): check this, i'm only getting this compile here.... CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]]; dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition()); } else dotProd = -1.0f; if(dotProd >= 0.0f) { -#else - -#ifndef FIX_BUGS - float copRoadDotProd, targetRoadDotProd; -#else - float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f; - if (m_nRoadblockNode != -1) -#endif - { - CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]]; - CVector2D roadFwd = roadBlockRoad->GetForward(); - copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd); - targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd); - } - // Roadblock may be towards road's fwd or opposite, so check both - if ((copRoadDotProd >= 0.0f || targetRoadDotProd >= 0.0f) - && (copRoadDotProd <= 0.0f || targetRoadDotProd <= 0.0f)) { -#endif bIsPointingGunAt = true; } else { + if (bIsDucking) + ClearDuck(); m_bIsDisabledCop = false; bKindaStayInSamePlace = false; bNotAllowedToDuck = false; bCrouchWhenShooting = false; - bIsDucking = false; bDuckAndCover = false; SetPursuit(false); } @@ -478,7 +485,6 @@ CCopPed::CopAI(void) } } else { if (m_fDistanceToTarget < weaponRange) { - CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); CVector gunPos = weaponInfo->m_vecFireOffset; TransformToNode(gunPos, PED_HANDR); @@ -487,6 +493,9 @@ CCopPed::CopAI(void) if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt, false, true, false, false, true, false, false) || foundEnt && foundEnt == playerOrHisVeh) { + + if (m_pPointGunAt) + m_pPointGunAt->CleanUpOldReference((CEntity**) &m_pPointGunAt); m_pPointGunAt = playerOrHisVeh; if (playerOrHisVeh) playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt); @@ -494,7 +503,7 @@ CCopPed::CopAI(void) SetAttack(playerOrHisVeh); SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000)); } - SetAttackTimer(CGeneral::GetRandomNumberInRange(100, 300)); + SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 300)); } SetMoveState(PEDMOVE_STILL); } @@ -524,10 +533,8 @@ CCopPed::CopAI(void) ClearObjective(); SetWanderPath(CGeneral::GetRandomNumber() & 7); } - } -#ifdef VC_PED_PORTS - else { - if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && CharCreatedBy == RANDOM_CHAR) { + } else { + if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_HASSLE_CHAR && CharCreatedBy == RANDOM_CHAR) { for (int i = 0; i < m_numNearPeds; i++) { CPed *nearPed = m_nearPeds[i]; if (nearPed->CharCreatedBy == RANDOM_CHAR) { @@ -547,12 +554,30 @@ CCopPed::CopAI(void) nearPed->bBeingChasedByPolice = true; return; } + } else { + if (nearPed->m_nPedType != PEDTYPE_COP && !nearPed->IsPlayer() + && nearPed->IsPedInControl() && m_nHassleTimer < CTimer::GetTimeInMilliseconds()) { + + if (nearPed->m_objective == OBJECTIVE_NONE && nearPed->m_nPedState == PED_WANDER_PATH + && !nearPed->m_pLookTarget && nearPed->m_lookTimer < CTimer::GetTimeInMilliseconds()) { + + if ((GetPosition() - nearPed->GetPosition()).MagnitudeSqr() < sq(5.0f)) { + + if (CWorld::GetIsLineOfSightClear(GetPosition(), nearPed->GetPosition(), + true, false, false, false, false, false, false)) { + Say(SOUND_PED_COP_REACTION); + SetObjective(OBJECTIVE_HASSLE_CHAR, nearPed); + nearPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT_FOR_COP, this); + m_nHassleTimer = CTimer::GetTimeInMilliseconds() + 100000; + } + } + } + } } } } } } -#endif } } } else { @@ -563,18 +588,35 @@ CCopPed::CopAI(void) bKindaStayInSamePlace = false; bNotAllowedToDuck = false; bCrouchWhenShooting = false; - bIsDucking = false; bDuckAndCover = false; + if (bIsDucking) + ClearDuck(); if (m_pMyVehicle) SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle); } } } +// --MIAMI: Done except commented things void CCopPed::ProcessControl(void) { + if (m_nCopType == COP_HELI_SWAT) + ProcessHeliSwat(); + CPed::ProcessControl(); + + if (m_bThrowsSpikeTrap) { + // TODO(Miami) + /* + if (CGame::currArea != AREA_MALL) + ProcessStingerCop(); + */ + return; + } + + // TODO(Miami): CStinger::Process + if (bWasPostponed) return; @@ -606,25 +648,36 @@ CCopPed::ProcessControl(void) if (IsPedInControl()) SetIdle(); } - /* + if (m_bIsInPursuit) { if (player->m_nPedState != PED_ARRESTED && !player->DyingOrDead()) { - switch (m_nCopType) { - case COP_FBI: - Say(SOUND_PED_PURSUIT_FBI); - break; - case COP_SWAT: - Say(SOUND_PED_PURSUIT_SWAT); - break; - case COP_ARMY: - Say(SOUND_PED_PURSUIT_ARMY); - break; - default: - Say(SOUND_PED_PURSUIT_COP); - break; + if (player->m_pWanted->m_CurrentCops == 1) { + Say(SOUND_PED_COP_ALONE); + } else { + int numCopsNear = 0; + for (int i = 0; i < player->m_numNearPeds; ++i) { + CPed *nearPed = player->m_nearPeds[i]; + if (nearPed->m_nPedType == PEDTYPE_COP && nearPed->m_nPedState != PED_DEAD) + ++numCopsNear; + } + if (numCopsNear <= 3) { + Say(SOUND_PED_COP_LITTLECOPSAROUND); + if (!player->bInVehicle) { + CVector distToPlayer = player->GetPosition() - GetPosition(); + if (distToPlayer.MagnitudeSqr() < sq(20.0f)) { + player->Say(SOUND_PED_PLAYER_FARFROMCOPS); + if (player->m_nPedState != PED_ATTACK && player->m_nPedState != PED_AIM_GUN) { + player->SetLookFlag(this, false); + player->SetLookTimer(1000); + } + } + } + } else if ((CGeneral::GetRandomNumber() % 16) == 1) { + Say(SOUND_PED_COP_MANYCOPSAROUND); + } } } - } */ + } if (IsPedInControl()) { CopAI(); @@ -671,23 +724,10 @@ CCopPed::ProcessControl(void) RestorePreviousObjective(); } else { if (player->m_pMyVehicle && player->m_pMyVehicle->m_nNumGettingIn != 0) { - // This is 1.3f when arresting in car without seeking first (in above) -#if defined(VC_PED_PORTS) || defined(FIX_BUGS) m_distanceToCountSeekDone = 1.3f; -#else - m_distanceToCountSeekDone = 2.0f; -#endif } - if (bDuckAndCover) { -#if !defined(GTA3_1_1_PATCH) && !defined(VC_PED_PORTS) - if (!bNotAllowedToDuck && Seek()) { - SetMoveState(PEDMOVE_STILL); - SetMoveAnim(); - SetPointGunAt(m_pedInObjective); - } -#endif - } else if (Seek()) { + if (!bDuckAndCover && Seek()) { CVehicle *playerVeh = FindPlayerVehicle(); if (!playerVeh && player && player->EnteringCar()) { SetArrestPlayer(player); @@ -718,35 +758,100 @@ CCopPed::ProcessControl(void) } } } - if (!m_bStopAndShootDisabledZone) - return; - bool dontShoot = false; - if (GetIsOnScreen()) { - if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) { - CEntity *foundBuilding = nil; - CColPoint foundCol; - CVector lookPos = GetPosition() + CVector(0.0f, 0.0f, 0.7f); - CVector camPos = TheCamera.GetGameCamPosition(); - CWorld::ProcessLineOfSight(camPos, lookPos, foundCol, foundBuilding, - true, false, false, false, false, false, false); + if (m_pPointGunAt) + Say(SOUND_PED_COP_UNK_129); - // He's at least 15.0 far, in disabled zone, collided into somewhere (that's why m_bStopAndShootDisabledZone set), - // and now has building on front of him. He's stupid, we don't need him. - if (foundBuilding) { - FlagToDestroyWhenNextProcessed(); - dontShoot = true; + if (m_bStopAndShootDisabledZone) { + bool dontShoot = false; + if (GetIsOnScreen()) { + if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) { + CEntity* foundBuilding = nil; + CColPoint foundCol; + CVector lookPos = GetPosition() + CVector(0.0f, 0.0f, 0.7f); + CVector camPos = TheCamera.GetGameCamPosition(); + CWorld::ProcessLineOfSight(camPos, lookPos, foundCol, foundBuilding, + true, false, false, false, false, false, false); + + // He's at least 15.0 far, in disabled zone, collided into somewhere (that's why m_bStopAndShootDisabledZone set), + // and now has building on front of him. He's stupid, we don't need him. + if (foundBuilding) { + FlagToDestroyWhenNextProcessed(); + dontShoot = true; + } + } + } else { + FlagToDestroyWhenNextProcessed(); + dontShoot = true; + } + + if (!dontShoot) { + bStopAndShoot = true; + bKindaStayInSamePlace = true; + bIsPointingGunAt = true; + SetAttack(m_pedInObjective); + } + } + + if (field_624 >= 2 && m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) { + CVector centre = GetPosition() + CVector(0.f, 0.f, 0.65f); + if (CWorld::TestSphereAgainstWorld(centre, 0.35f, this, true, false, false, false, false, false)) { + field_624 = 0; + m_bStopAndShootDisabledZone = true; + ClearPursuit(); + SetObjective(OBJECTIVE_NONE); + SetWanderPath(CGeneral::GetRandomNumberInRange(0,8)); + field_61C = CTimer::GetTimeInMilliseconds() + 30000; + } else { + field_624 = 0; + if (GetWeapon()->IsTypeMelee()) { + // TODO(Miami): enum + for (int i = 3; i < 7; i++) { + if (HasWeaponSlot(i)) { + SetCurrentWeapon(i); + break; + } + } + SetMoveState(PEDMOVE_STILL); + bStopAndShoot = true; } } - } else { - FlagToDestroyWhenNextProcessed(); - dontShoot = true; - } - - if (!dontShoot) { - bStopAndShoot = true; - bKindaStayInSamePlace = true; - bIsPointingGunAt = true; - SetAttack(m_pedInObjective); - } + } else if (CTimer::GetTimeStep() / 100.f <= m_fDistanceTravelled) + field_624 = 0; } + +// --MIAMI: Done +void +CCopPed::ProcessHeliSwat(void) +{ + CVector bestPos = GetPosition(); + SetPedState(PED_ABSEIL); + CPedPlacement::FindZCoorForPed(&bestPos); + if (GetPosition().z - 2.0f >= bestPos.z && m_pRopeEntity) { + m_fAbseilPos += 0.003f * CTimer::GetTimeStep(); + m_vecMoveSpeed.z = -0.03f; + m_vecTurnSpeed = CVector(0.f, 0.f, (m_randomSeed % 32) * 0.003f - 0.05f); + CPhysical::ApplyTurnSpeed(); + GetMatrix().Reorthogonalise(); + CVector posOnRope; + + if (CRopes::FindCoorsAlongRope(m_nRopeID, m_fAbseilPos, &posOnRope)) { + SetPosition(posOnRope); + } else { + bUsesCollision = true; + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + SetPedState(PED_IDLE); + m_nCopType = COP_SWAT; + SetInTheAir(); + bKnockedUpIntoAir = true; + } + Say(SOUND_PED_COP_HELIPILOTPHRASE); + } else { + bUsesCollision = true; + m_vecMoveSpeed = CVector(0.f, 0.f, 0.f); + SetPedState(PED_IDLE); + m_nCopType = COP_SWAT; + SetInTheAir(); + bKnockedUpIntoAir = true; + } +} \ No newline at end of file diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index e48984ff..edec145e 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -6,7 +6,8 @@ enum eCopType COP_STREET = 0, COP_FBI = 1, COP_SWAT = 2, - COP_ARMY = 3, + COP_HELI_SWAT = 3, + COP_ARMY = 4, COP_MIAMIVICE = 5 }; @@ -18,7 +19,6 @@ public: bool m_bIsInPursuit; bool m_bIsDisabledCop; int8 field_5FE; - int8 field_5FF; bool m_bBeatingSuspect; bool m_bStopAndShootDisabledZone; bool field_601; // set when police dragging player from car @@ -28,6 +28,8 @@ public: bool m_bThrowsSpikeTrap; CEntity *m_pRopeEntity; // CHeli or 1 uintptr m_nRopeID; + uint32 m_nHassleTimer; + uint32 field_61C; int32 field_624; int8 field_628; @@ -41,6 +43,7 @@ public: void ArrestPlayer(void); void ScanForCrimes(void); void CopAI(void); + void ProcessHeliSwat(void); }; #ifndef PED_SKIN diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp index 6011ce44..8012650a 100644 --- a/src/peds/PedPlacement.cpp +++ b/src/peds/PedPlacement.cpp @@ -4,7 +4,8 @@ #include "PedPlacement.h" #include "World.h" -void +// --MIAMI: Done +bool CPedPlacement::FindZCoorForPed(CVector* pos) { float zForPed; @@ -32,8 +33,11 @@ CPedPlacement::FindZCoorForPed(CVector* pos) zForPed = Max(foundColZ, foundColZ2); - if (zForPed > -99.0f) + if (zForPed > -99.0f) { pos->z = FEET_OFFSET + zForPed; + return true; + } + return false; } CEntity* diff --git a/src/peds/PedPlacement.h b/src/peds/PedPlacement.h index 5b8354d4..d1b0cd16 100644 --- a/src/peds/PedPlacement.h +++ b/src/peds/PedPlacement.h @@ -2,7 +2,7 @@ class CPedPlacement { public: - static void FindZCoorForPed(CVector* pos); + static bool FindZCoorForPed(CVector* pos); static CEntity* IsPositionClearOfCars(Const CVector*); static bool IsPositionClearForPed(const CVector& pos, float radius = -1.0f, int total = -1, CEntity** entities = nil); }; \ No newline at end of file diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 408fb8f9..00bb0023 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -731,12 +731,12 @@ CHeli::SendDownSwat(void) float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, nil); if(Abs(FindPlayerCoors().z - groundZ) < 2.5f && CRopes::RegisterRope((uintptr)this + m_numSwat-1, pos, false)){ - CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_ARMY, pos); + CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos); swat->bUsesCollision = false; swat->m_pRopeEntity = this; RegisterReference(&swat->m_pRopeEntity); m_numSwat--; - swat->m_nRopeID = m_numSwat; + swat->m_nRopeID = (uintptr)this + m_numSwat; m_aSwatState[m_numSwat] = 255; CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_ABSEIL, 4.0f); return true; From c87b639a84ca8bc33667abc98a731a61350cc518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 26 Jul 2020 20:59:58 +0300 Subject: [PATCH 84/85] Fix casepath chaos --- src/audio/oal/stream.cpp | 12 ++-- src/core/CdStreamPosix.cpp | 16 +++-- src/core/FileMgr.cpp | 37 ++--------- src/fakerw/fake.cpp | 65 ++++++++++++------ src/skel/crossplatform.cpp | 133 +++++++++++++++++++++++-------------- src/skel/crossplatform.h | 6 +- 6 files changed, 150 insertions(+), 119 deletions(-) diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 40ec57fa..b689e929 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -255,15 +255,11 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF { // Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) #if !defined(_WIN32) - FILE *test = fopen(filename, "r"); - if (!test) { - char *r = (char*)alloca(strlen(filename) + 2); - if (casepath(filename, r)) - { - strcpy(m_aFilename, r); - } + char *real = casepath(filename); + if (real) { + strcpy(m_aFilename, real); + free(real); } else { - fclose(test); #else { #endif diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index 4d6bcdab..45fd9832 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -189,10 +189,11 @@ GetGTA3ImgSize(void) realpath(gImgNames[0], path); if (stat(path, &statbuf) == -1) { // Try case-insensitivity - char *r = (char*)alloca(strlen(gImgNames[0]) + 2); - if (casepath(gImgNames[0], r)) + char* real = casepath(gImgNames[0], false); + if (real) { - realpath(r, path); + realpath(real, path); + free(real); if (stat(path, &statbuf) != -1) goto ok; } @@ -210,7 +211,6 @@ CdStreamShutdown(void) { // Destroying semaphores and free(gpReadInfo) will be done at threads #ifndef ONE_THREAD_PER_CHANNEL - free(gChannelRequestQ.items); gCdStreamThreadStatus = 2; sem_post(&gCdStreamSema); #endif @@ -442,6 +442,7 @@ void *CdStreamThread(void *param) sem_destroy(&gpReadInfo[i].pDoneSemaphore); } sem_destroy(&gCdStreamSema); + free(gChannelRequestQ.items); #else sem_destroy(&gpReadInfo[channel].pStartSemaphore); sem_destroy(&gpReadInfo[channel].pDoneSemaphore); @@ -460,10 +461,11 @@ CdStreamAddImage(char const *path) // Fix case sensitivity and backslashes. if (gImgFiles[gNumImages] == -1) { - char *r = (char*)alloca(strlen(path) + 2); - if (casepath(path, r)) + char* real = casepath(path, false); + if (real) { - gImgFiles[gNumImages] = open(r, _gdwCdStreamFlags); + gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags); + free(real); } } diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index cdcb80f0..4477a190 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -4,6 +4,7 @@ #include #endif #include "common.h" +#include "crossplatform.h" #include "FileMgr.h" @@ -31,19 +32,16 @@ static myFILE myfiles[NUMFILES]; #include #include #include -#include "crossplatform.h" #define _getcwd getcwd // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) void mychdir(char const *path) { - char *r = (char*)alloca(strlen(path) + 2); - if (casepath(path, r)) - { + char* r = casepath(path, false); + if (r) { chdir(r); - } - else - { + free(r); + } else { errno = ENOENT; } } @@ -73,30 +71,7 @@ found: *p++ = 'b'; *p = '\0'; -#if !defined(_WIN32) - char *newPath = strdup(filename); - // Normally casepath() fixes backslashes, but if the mode is sth other than r/rb it will create new file with backslashes on linux, so fix backslashes here - char *nextBs; - while(nextBs = strstr(newPath, "\\")){ - *nextBs = '/'; - } -#else - const char *newPath = filename; -#endif - - myfiles[fd].file = fopen(newPath, realmode); -// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) -#if !defined(_WIN32) - if (!myfiles[fd].file) { - char *r = (char*)alloca(strlen(newPath) + 2); - if (casepath(newPath, r)) - { - myfiles[fd].file = fopen(r, realmode); - } - } - - free(newPath); -#endif + myfiles[fd].file = fcaseopen(filename, realmode); if(myfiles[fd].file == nil) return 0; return fd; diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 0bc69abe..7139292e 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -376,23 +376,19 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v file = rwNewT(StreamFile, 1, 0); memcpy(file, &fakefile, sizeof(StreamFile)); #ifndef _WIN32 - // Be case-insensitive and fix backslashes (from https://github.com/OneSadCookie/fcaseopen/) - FILE* first = fopen((char*)pData, "r"); - char *r; - if (!first) { - r = (char*)alloca(strlen((char*)pData) + 2); - // Use default path(and pass error handling to librw) if we can't find any match - if (!casepath((char*)pData, r)) - r = (char*)pData; + char *r = casepath((char*)pData); + if (r) { + if (file->open((char*)r, mode)) { + free(r); + return file; + } + free(r); } else - fclose(first); - - if(file->open((char*)r, mode)) - return file; -#else - if(file->open((char*)pData, mode)) - return file; #endif + { + if (file->open((char*)pData, mode)) + return file; + } rwFree(file); return nil; } @@ -856,12 +852,41 @@ RpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry ) { return Skin::get(geometr RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; } RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); } +RwImage * +RtBMPImageWrite(RwImage *image, const RwChar *imageName) +{ +#ifndef _WIN32 + char *r = casepath(imageName); + if (r) { + rw::writeBMP(image, r); + free(r); + } else { + rw::writeBMP(image, imageName); + } + +#else + rw::writeBMP(image, imageName); +#endif + return image; +} +RwImage * +RtBMPImageRead(const RwChar *imageName) +{ +#ifndef _WIN32 + RwImage *image; + char *r = casepath(imageName); + if (r) { + image = rw::readBMP(r); + free(r); + } else { + image = rw::readBMP(imageName); + } + return image; - - - -RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; } -RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); } +#else + return rw::readBMP(imageName); +#endif +} #include "rtquat.h" diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 40f4f053..6188992d 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -87,7 +87,7 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { // Funcs/features from Windows that we need on other platforms #ifndef _WIN32 char *strupr(char *s) { - char* tmp = s; + char* tmp = s; for (;*tmp;++tmp) { *tmp = toupper((unsigned char) *tmp); @@ -96,7 +96,7 @@ char *strupr(char *s) { return s; } char *strlwr(char *s) { - char* tmp = s; + char* tmp = s; for (;*tmp;++tmp) { *tmp = tolower((unsigned char) *tmp); @@ -116,86 +116,117 @@ char *trim(char *s) { return s; } -// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) -// r must have strlen(path) + 2 bytes -int casepath(char const *path, char *r) +FILE* _fcaseopen(char const* filename, char const* mode) { + FILE* result; + char* real = casepath(filename); + if (!real) + result = fopen(filename, mode); + else { + result = fopen(real, mode); + free(real); + } + return result; +} + +// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) +// Returned string should freed manually (if exists) +char* casepath(char const* path, bool checkPathFirst) +{ + if (checkPathFirst && access(path, F_OK) != -1) { + // File path is correct + return nil; + } + size_t l = strlen(path); - char *p = (char*)alloca(l + 1); + char* p = (char*)alloca(l + 1); + char* out = (char*)malloc(l + 3); // for extra ./ strcpy(p, path); - // my addon: change \'s with / - char *nextBs; - while(nextBs = strstr(p, "\\")){ - *nextBs = '/'; - } - - // my addon: linux doesn't handle filenames with spaces at the end nicely - p = trim(p); + // my addon: linux doesn't handle filenames with spaces at the end nicely + p = trim(p); size_t rl = 0; - - DIR *d; - if (p[0] == '/') + + DIR* d; + if (p[0] == '/' || p[0] == '\\') { d = opendir("/"); - p = p + 1; } else { d = opendir("."); - r[0] = '.'; - r[1] = 0; + out[0] = '.'; + out[1] = 0; rl = 1; } - - int last = 0; - char *c = strsep(&p, "/"); - while (c) + + bool cantProceed = false; // just convert slashes in what's left in string, not case sensitivity + bool mayBeTrailingSlash = false; + char* c; + while (c = strsep(&p, "/\\")) { - if (!d) + // May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid) + if (*c == '\0') { - return 0; + mayBeTrailingSlash = true; + continue; + } else { + mayBeTrailingSlash = false; } - - if (last) - { - closedir(d); - return 0; - } - - r[rl] = '/'; + + out[rl] = '/'; rl += 1; - r[rl] = 0; - - struct dirent *e = readdir(d); - while (e) + out[rl] = 0; + + if (cantProceed) + { + strcpy(out + rl, c); + rl += strlen(c); + continue; + } + + struct dirent* e; + while (e = readdir(d)) { if (strcasecmp(c, e->d_name) == 0) { - strcpy(r + rl, e->d_name); - rl += strlen(e->d_name); + strcpy(out + rl, e->d_name); + int reportedLen = (int)strlen(e->d_name); + rl += reportedLen; + assert(reportedLen == strlen(c) && "casepath: This is not good at all"); closedir(d); - d = opendir(r); - + d = opendir(out); + + // Either it wasn't a folder, or permission error, I/O error etc. + if (!d) { + cantProceed = true; + } + break; } - - e = readdir(d); } - + if (!e) { - strcpy(r + rl, c); + printf("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path); + // No match, add original name and continue converting further slashes. + strcpy(out + rl, c); rl += strlen(c); - last = 1; + cantProceed = true; } - - c = strsep(&p, "/"); } - + if (d) closedir(d); - return 1; + if (mayBeTrailingSlash) { + out[rl] = '/'; rl += 1; + out[rl] = '\0'; + } + + if (rl > l + 2) { + printf("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%d chars)\n\tCorrected: %s (%d chars)\n\n", path, l, out, rl); + } + return out; } #endif diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 268eedff..69600385 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -23,7 +23,7 @@ enum eWinVersion #include "win.h" #endif extern DWORD _dwOperatingSystemVersion; - +#define fcaseopen fopen #else char *strupr(char *str); char *strlwr(char *str); @@ -43,7 +43,9 @@ enum { }; extern long _dwOperatingSystemVersion; -int casepath(char const *path, char *r); +char *casepath(char const *path, bool checkPathFirst = true); +FILE *_fcaseopen(char const *filename, char const *mode); +#define fcaseopen _fcaseopen #endif #ifdef RW_GL3 From c649028b01984189b428d8d243016639587d5cae Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 29 Jul 2020 09:49:41 +0200 Subject: [PATCH 85/85] some fakerw additions for shadows; update librw --- librw | 2 +- src/fakerw/fake.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/librw b/librw index 49ca300b..99c15d5e 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 49ca300b88c8c298e5811b41e753589ad2a4c367 +Subproject commit 99c15d5ed78cc112e1055cc89452dd57df28da58 diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 7139292e..b9ff0144 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -35,9 +35,9 @@ RwReal RwV3dLength(const RwV3d * in) { return length(*in); } //void RwV3dAssign(RwV3d * out, const RwV3d * ina); void RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = add(*ina, *inb); } void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = sub(*ina, *inb); } -//void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar); -//void RwV3dIncrementScaled(RwV3d * out, const RwV3d * in, RwReal scalar); -//void RwV3dNegate(RwV3d * out, const RwV3d * in); +void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar) { *out = scale(*in, scalar); } +void RwV3dIncrementScaled(RwV3d * out, const RwV3d * in, RwReal scalar) { *out = add(*out, scale(*in, scalar)); } +void RwV3dNegate(RwV3d * out, const RwV3d * in) { *out = neg(*in); } RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb) { return dot(*ina, *inb); } //void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb); RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix) @@ -137,7 +137,7 @@ RwCamera *RwCameraCreate(void) { return rw::Camera::create(); } RwCamera *RwCameraClone(RwCamera * camera) { return camera->clone(); } RwCamera *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset) { camera->setViewOffset(offset); return camera; } RwCamera *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow) { camera->setViewWindow(viewWindow); return camera; } -RwCamera *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection); +RwCamera *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection) { camera->projection = projection; return camera; } RwCamera *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip) { camera->setNearPlane(nearClip); return camera; } RwCamera *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip) { camera->setFarPlane(farClip); return camera; } RwInt32 RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);