diff options
Diffstat (limited to '')
36 files changed, 1691 insertions, 808 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..327d8cc7 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,32 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": ["${default}"], + "defines": [], + "macFrameworkPath": [ + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" + ], + "compilerPath": "/opt/local/bin/clang", + "compilerArgs": ["-g"], + "cStandard": "gnu11", + "cppStandard": "gnu++14", + "browse": { + "path": [ + "/opt/local/include", + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include" + ] + } + }, + { + "name": "Linux", + "includePath": ["${default}"], + "defines": ["XDG_ROOT"], + "compilerPath": "/usr/bin/gcc", + "compilerArgs": ["-ggdb"], + "cStandard": "gnu11", + "cppStandard": "gnu++14" + } + ], + "version": 4 +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..82ce041f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,89 @@ +{ + "configurations": [ + { + "MIMode": "gdb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(gdb) Launch (Linux Debug)", + "preLaunchTask": "Compile (Debug Linux x64)", + "program": "${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Debug/re3", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "gdb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(gdb) Launch (Linux Release)", + "preLaunchTask": "Compile (Release Linux x64)", + "program": "${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Release/re3", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "lldb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(lldb) Launch (macOS Debug)", + "preLaunchTask": "Compile (Debug macOS x64)", + "program": "${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Debug/re3.app", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for lldb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "lldb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(lldb) Launch (macOS Release)", + "preLaunchTask": "Compile (Release macOS x64)", + "program": "${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Release/re3.app", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for lldb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + } + ], + "version": "0.2.0" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..10cb5627 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,30 @@ +{ + "C_Cpp.default.cStandard": "gnu11", + "C_Cpp.default.cppStandard": "gnu++14", + "C_Cpp.default.includePath": [ + "src/animation", + "src/audio", + "src/control", + "src/core", + "src/entities", + "src/extras", + "src/fakerw", + "src/math", + "src/modelinfo", + "src/objects", + "src/peds", + "src/render", + "src/rw", + "src/save", + "src/skel", + "src/text", + "src/vehicles", + "src/weapons", + "vendor/librw" + ], + "C_Cpp.vcFormat.indent.gotoLabels": "leftmostColumn", + "C_Cpp.vcFormat.space.pointerReferenceAlignment": "right", + "cSpell.enabled": false, + "files.trimFinalNewlines": false, + "files.trimTrailingWhitespace": false +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..0f610d5f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,95 @@ +{ + "tasks": [ + { + "args": ["--with-librw", "gmake2"], + "command": "./premake5Linux", + "label": "Premake (Linux)", + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": ["--with-librw", "gmake2"], + "command": "premake5", + "label": "Premake (macOS)", + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=debug_linux-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (Linux)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Debug Linux x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=release_linux-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (Linux)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Release Linux x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=debug_macosx-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (macOS)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Debug macOS x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=release_macosx-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (macOS)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Release macOS x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + } + ], + "version": "2.0.0" +} diff --git a/CODING_STYLE.md b/CODING_STYLE.md new file mode 100644 index 00000000..b8be02bc --- /dev/null +++ b/CODING_STYLE.md @@ -0,0 +1,107 @@ +# Coding style + +I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style), +but realize that this is not the most popular style, so I'm willing to compromise. +Try not to deviate too much so the code will look similar across the whole project. + +To give examples, these two styles (or anything in between) are fine: + +``` +type +functionname(args) +{ + if(a == b){ + s1; + s2; + }else{ + s3; + s4; + } + if(x != y) + s5; +} + +type functionname(args) +{ + if (a == b) { + s1; + s2; + } else { + s3; + s4; + } + if (x != y) + s5; +} +``` + +This one (or anything more extreme) is heavily discouraged: + +``` +type functionname ( args ) +{ + if ( a == b ) + { + s1; + s2; + } + else + { + s3; + s4; + } + if ( x != y ) + { + s5; + } +} +``` + +i.e. + +* Put the brace on the same line as control statements + +* Put the brace on the next line after function definitions and structs/classes + +* Put an `else` on the same line with the braces + +* Don't put braces around single statements + +* Put the function return type on a separate line + +* Indent with TABS + +As for the less cosmetic choices, here are some guidelines how the code should look: + +* Don't use magic numbers where the original source code would have had an enum or similar. +Even if you don't know the exact meaning it's better to call something `FOOBAR_TYPE_4` than just `4`, +since `4` will be used in other places and you can't easily see where else the enum value is used. + +* Don't just copy paste code from IDA, make it look nice + +* Use the right types. In particular: + + * don't use types like `__int16`, we have `int16` for that + + * don't use `unsigned`, we have typedefs for that + + * don't use `char` for anything but actual characters, use `int8`, `uint8` or `bool` + + * don't even think about using win32 types (`BYTE`, `WORD`, &c.) unless you're writing win32 specific code + + * declare pointers like `int *ptr;`, not `int* ptr;` + +* As for variable names, the original gta source code was not written in a uniform style, +but here are some observations: + + * many variables employ a form of hungarian notation, i.e.: + + * `m_` may be used for class member variables (mostly those that are considered private) + + * `ms_` for (mostly private) static members + + * `f` is a float, `i` or `n` is an integer, `b` is a boolean, `a` is an array + + * do *not* use `dw` for `DWORD` or so, we're not programming win32 + +* Generally, try to make the code look as if R* could have written it @@ -21,8 +21,7 @@ such that we have a working game at all times. ## Preparing the environment for building -- Clone the repo. -- Run `git submodule init` and `git submodule update`. +- Clone the repo using the argument `--recursive`. - Point GTA_III_RE_DIR environment variable to GTA3 root folder. - Run premake - On Windows: one of the `premake-vsXXXX.cmd` variants on root folder @@ -36,6 +35,7 @@ such that we have a working game at all times. > :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 +Please read the [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) Document ### Unreversed / incomplete classes (at least the ones we know) The following classes have only unused or practically unused code left: @@ -44,110 +44,3 @@ CCullZone - only mobile stuff CCullZones - only mobile stuff ``` -### Coding style - -I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style), -but realize that this is not the most popular style, so I'm willing to compromise. -Try not to deviate too much so the code will look similar across the whole project. - -To give examples, these two styles (or anything in between) are fine: - -``` -type -functionname(args) -{ - if(a == b){ - s1; - s2; - }else{ - s3; - s4; - } - if(x != y) - s5; -} - -type functionname(args) -{ - if (a == b) { - s1; - s2; - } else { - s3; - s4; - } - if (x != y) - s5; -} -``` - -This one (or anything more extreme) is heavily discouraged: - -``` -type functionname ( args ) -{ - if ( a == b ) - { - s1; - s2; - } - else - { - s3; - s4; - } - if ( x != y ) - { - s5; - } -} -``` - -i.e. - -* Put the brace on the same line as control statements - -* Put the brace on the next line after function definitions and structs/classes - -* Put an `else` on the same line with the braces - -* Don't put braces around single statements - -* Put the function return type on a separate line - -* Indent with TABS - -As for the less cosmetic choices, here are some guidelines how the code should look: - -* Don't use magic numbers where the original source code would have had an enum or similar. -Even if you don't know the exact meaning it's better to call something `FOOBAR_TYPE_4` than just `4`, -since `4` will be used in other places and you can't easily see where else the enum value is used. - -* Don't just copy paste code from IDA, make it look nice - -* Use the right types. In particular: - - * don't use types like `__int16`, we have `int16` for that - - * don't use `unsigned`, we have typedefs for that - - * don't use `char` for anything but actual characters, use `int8`, `uint8` or `bool` - - * don't even think about using win32 types (`BYTE`, `WORD`, &c.) unless you're writing win32 specific code - - * declare pointers like `int *ptr;`, not `int* ptr;` - -* As for variable names, the original gta source code was not written in a uniform style, -but here are some observations: - - * many variables employ a form of hungarian notation, i.e.: - - * `m_` may be used for class member variables (mostly those that are considered private) - - * `ms_` for (mostly private) static members - - * `f` is a float, `i` or `n` is an integer, `b` is a boolean, `a` is an array - - * do *not* use `dw` for `DWORD` or so, we're not programming win32 - -* Generally, try to make the code look as if R* could have written it diff --git a/premake5.lua b/premake5.lua index fb408fe0..334c9c53 100644 --- a/premake5.lua +++ b/premake5.lua @@ -185,7 +185,7 @@ project "librw" includedirs {"/usr/local/include" } libdirs { "/opt/local/lib" } libdirs { "/usr/local/lib" } - + filter "platforms:*RW34*" flags { "ExcludeFromBuild" } filter {} diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 486daebf..a4db2862 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -5,6 +5,7 @@ #include "AudioManager.h" #include "AudioScriptObject.h" #include "sampman.h" +#include "Font.h" #include "Text.h" #include "crossplatform.h" diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 74c4f006..93098d6d 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -3075,7 +3075,7 @@ void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle* pVehicle) void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) { pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0; - pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo = 0; + pVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo = 0; int nodeId = ThePaths.FindNodeClosestToCoorsFavourDirection(pVehicle->GetPosition(), 0, pVehicle->GetForward().x, pVehicle->GetForward().y); CPathNode* pNode = &ThePaths.m_pathNodes[nodeId]; int prevNodeId = -1; diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index 75d27e26..1191e8ad 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -14,6 +14,9 @@ #include "Text.h" #include "Vehicle.h" #include "GameLogic.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif #define FRENZY_ANY_PED -1 #define FRENZY_ANY_CAR -2 @@ -62,6 +65,10 @@ CDarkel::CalcFade(uint32 time, uint32 start, uint32 end) void CDarkel::DrawMessages() { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif switch (Status) { case KILLFRENZY_ONGOING: { @@ -167,6 +174,10 @@ CDarkel::ReadStatus() void CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif if (FrenzyOnGoing()) { int32 model = vehicle->GetModelIndex(); if (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) { @@ -181,6 +192,10 @@ CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle) void CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif if (FrenzyOnGoing() && (weapon == WeaponType || weapon == WEAPONTYPE_EXPLOSION || weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI @@ -206,6 +221,10 @@ CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot) void CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif CStats::PeopleKilledByOthers++; } @@ -299,6 +318,11 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode void CDarkel::Update() { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif + if (Status != KILLFRENZY_ONGOING) return; diff --git a/src/control/OnscreenTimer.cpp b/src/control/OnscreenTimer.cpp index d94e993e..52d00f43 100644 --- a/src/control/OnscreenTimer.cpp +++ b/src/control/OnscreenTimer.cpp @@ -7,29 +7,38 @@ #include "Timer.h" #include "Script.h" #include "OnscreenTimer.h" +#include "Camera.h" + +// --MIAMI: file done void COnscreenTimer::Init() { m_bDisabled = false; - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - m_sEntries[i].m_nTimerOffset = 0; - m_sEntries[i].m_nCounterOffset = 0; + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + m_sCounters[i].m_nCounterOffset = 0; + + for(uint32 j = 0; j < ARRAY_SIZE(COnscreenCounterEntry::m_aCounterText); j++) { + m_sCounters[i].m_aCounterText[j] = 0; + } + + m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER; + m_sCounters[i].m_bCounterProcessed = false; + } + for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) { + m_sClocks[i].m_nClockOffset = 0; - for(uint32 j = 0; j < 10; j++) { - m_sEntries[i].m_aTimerText[j] = 0; - m_sEntries[i].m_aCounterText[j] = 0; + for(uint32 j = 0; j < ARRAY_SIZE(COnscreenTimerEntry::m_aClockText); j++) { + m_sClocks[i].m_aClockText[j] = 0; } - m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER; - m_sEntries[i].m_bTimerProcessed = false; - m_sEntries[i].m_bCounterProcessed = false; - m_sEntries[i].m_bTimerGoingDown = true; + m_sClocks[i].m_bClockProcessed = false; + m_sClocks[i].m_bClockGoingDown = true; } } void COnscreenTimer::Process() { if(!CReplay::IsPlayingBack() && !m_bDisabled) { - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - m_sEntries[i].Process(); + for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) { + m_sClocks[i].Process(); } } } @@ -37,8 +46,19 @@ void COnscreenTimer::Process() { void COnscreenTimer::ProcessForDisplay() { if(CHud::m_Wants_To_Draw_Hud) { m_bProcessed = false; - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - if(m_sEntries[i].ProcessForDisplay()) { + for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) { + m_sClocks[i].m_bClockProcessed = false; + if (m_sClocks[i].m_nClockOffset != 0) { + m_sClocks[i].ProcessForDisplayClock(); + m_sClocks[i].m_bClockProcessed = true; + m_bProcessed = true; + } + } + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + m_sCounters[i].m_bCounterProcessed = false; + if (m_sCounters[i].m_nCounterOffset != 0) { + m_sCounters[i].ProcessForDisplayCounter(); + m_sCounters[i].m_bCounterProcessed = true; m_bProcessed = true; } } @@ -46,77 +66,81 @@ void COnscreenTimer::ProcessForDisplay() { } void COnscreenTimer::ClearCounter(uint32 offset) { - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - if(offset == m_sEntries[i].m_nCounterOffset) { - m_sEntries[i].m_nCounterOffset = 0; - m_sEntries[i].m_aCounterText[0] = 0; - m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER; - m_sEntries[i].m_bCounterProcessed = 0; + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + if(offset == m_sCounters[i].m_nCounterOffset) { + m_sCounters[i].m_nCounterOffset = 0; + m_sCounters[i].m_aCounterText[0] = 0; + m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER; + m_sCounters[i].m_bCounterProcessed = 0; } } } void COnscreenTimer::ClearClock(uint32 offset) { - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - if(offset == m_sEntries[i].m_nTimerOffset) { - m_sEntries[i].m_nTimerOffset = 0; - m_sEntries[i].m_aTimerText[0] = 0; - m_sEntries[i].m_bTimerProcessed = 0; + for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) { + if(offset == m_sClocks[i].m_nClockOffset) { + m_sClocks[i].m_nClockOffset = 0; + m_sClocks[i].m_aClockText[0] = 0; + m_sClocks[i].m_bClockProcessed = 0; + m_sClocks[i].m_bClockGoingDown = true; } } } void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos) { - m_sEntries[pos].m_nCounterOffset = offset; - if (m_sEntries[pos].m_aCounterText[0] != '\0') + if (m_sCounters[pos].m_aCounterText[0] != '\0') return; + + m_sCounters[pos].m_nCounterOffset = offset; if(text) { - strncpy(m_sEntries[pos].m_aCounterText, text, 10); + strncpy(m_sCounters[pos].m_aCounterText, text, ARRAY_SIZE(COnscreenCounterEntry::m_aCounterText)); } else { - m_sEntries[pos].m_aCounterText[0] = 0; + m_sCounters[pos].m_aCounterText[0] = 0; } - m_sEntries[pos].m_nType = type; + m_sCounters[pos].m_nType = type; } void COnscreenTimer::AddClock(uint32 offset, char* text, bool bGoingDown) { - uint32 i = 0; - for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { - if(m_sEntries[i].m_nTimerOffset == 0) { + + // dead code in here + uint32 i; + for(i = 0; i < NUMONSCREENCLOCKS; i++) { + if(m_sClocks[i].m_nClockOffset == 0) { break; } return; } - m_sEntries[i].m_nTimerOffset = offset; - m_sEntries[i].m_bTimerGoingDown = bGoingDown; + m_sClocks[i].m_nClockOffset = offset; + m_sClocks[i].m_bClockGoingDown = bGoingDown; if(text) { - strncpy(m_sEntries[i].m_aTimerText, text, 10); + strncpy(m_sClocks[i].m_aClockText, text, ARRAY_SIZE(COnscreenTimerEntry::m_aClockText)); } else { - m_sEntries[i].m_aTimerText[0] = 0; + m_sClocks[i].m_aClockText[0] = 0; } } void COnscreenTimerEntry::Process() { - if(m_nTimerOffset == 0) { + if(m_nClockOffset == 0) { return; } - int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nTimerOffset); + int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nClockOffset); int32 oldTime = *timerPtr; - if (m_bTimerGoingDown) { + if (m_bClockGoingDown) { int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds()); + *timerPtr = newTime; if (newTime < 0) { *timerPtr = 0; - m_bTimerProcessed = 0; - m_nTimerOffset = 0; - m_aTimerText[0] = 0; + m_bClockProcessed = 0; + m_nClockOffset = 0; + m_aClockText[0] = 0; } else { - *timerPtr = newTime; int32 oldTimeSeconds = oldTime / 1000; - if (oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds) { + if (oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds && !TheCamera.m_WideScreenOn) { DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000); } } @@ -125,33 +149,13 @@ void COnscreenTimerEntry::Process() { *timerPtr = oldTime + int32(CTimer::GetTimeStepInMilliseconds()); } -bool COnscreenTimerEntry::ProcessForDisplay() { - m_bTimerProcessed = false; - m_bCounterProcessed = false; - - if(m_nTimerOffset == 0 && m_nCounterOffset == 0) { - return false; - } - - if(m_nTimerOffset != 0) { - m_bTimerProcessed = true; - ProcessForDisplayClock(); - } - - if(m_nCounterOffset != 0) { - m_bCounterProcessed = true; - ProcessForDisplayCounter(); - } - return true; -} - void COnscreenTimerEntry::ProcessForDisplayClock() { - uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nTimerOffset); - sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60, + uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nClockOffset); + sprintf(m_aClockBuffer, "%02d:%02d", time / 1000 / 60 % 100, time / 1000 % 60); } -void COnscreenTimerEntry::ProcessForDisplayCounter() { +void COnscreenCounterEntry::ProcessForDisplayCounter() { uint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset); - sprintf(m_bCounterBuffer, "%d", counter); + sprintf(m_aCounterBuffer, "%d", counter); } diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h index 09473397..8c049d7d 100644 --- a/src/control/OnscreenTimer.h +++ b/src/control/OnscreenTimer.h @@ -9,30 +9,37 @@ enum class COnscreenTimerEntry { public: - uint32 m_nTimerOffset; + uint32 m_nClockOffset; + char m_aClockText[10]; + char m_aClockBuffer[40]; + bool m_bClockProcessed; + bool m_bClockGoingDown; + + void Process(); + void ProcessForDisplayClock(); +}; + +VALIDATE_SIZE(COnscreenTimerEntry, 0x3C); + +class COnscreenCounterEntry +{ +public: uint32 m_nCounterOffset; - char m_aTimerText[10]; char m_aCounterText[10]; uint16 m_nType; - char m_bCounterBuffer[42]; - char m_bTimerBuffer[42]; - bool m_bTimerProcessed; - bool m_bTimerGoingDown; + char m_aCounterBuffer[40]; bool m_bCounterProcessed; - void Process(); - bool ProcessForDisplay(); - - void ProcessForDisplayClock(); void ProcessForDisplayCounter(); }; -VALIDATE_SIZE(COnscreenTimerEntry, 0x74); +VALIDATE_SIZE(COnscreenCounterEntry, 0x3C); class COnscreenTimer { public: - COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES]; + COnscreenTimerEntry m_sClocks[NUMONSCREENCLOCKS]; + COnscreenCounterEntry m_sCounters[NUMONSCREENCOUNTERS]; bool m_bProcessed; bool m_bDisabled; @@ -47,4 +54,4 @@ public: void AddClock(uint32 offset, char* text, bool bGoingDown); }; -VALIDATE_SIZE(COnscreenTimer, 0x78); +VALIDATE_SIZE(COnscreenTimer, 0xF4); diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index a6928def..5b57cb73 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -16,6 +16,9 @@ #include "Ped.h" #include "Fire.h" #include "GameLogic.h" +#include "CarAI.h" + +// --MIAMI: file done CFireManager gFireManager; @@ -26,14 +29,13 @@ CFire::CFire() m_bPropagationFlag = true; m_bAudioSet = true; m_vecPos = CVector(0.0f, 0.0f, 0.0f); - m_pEntity = nil; - m_pSource = nil; - m_nFiremenPuttingOut = 0; m_nExtinguishTime = 0; m_nStartTime = 0; - field_20 = 1; - m_nNextTimeToAddFlames = 0; + m_pEntity = nil; + m_pSource = nil; m_fStrength = 0.8f; + m_fWaterExtinguishCountdown = 1.0f; + m_bExtinguishedWithWater = false; } CFire::~CFire() {} @@ -52,6 +54,8 @@ CFire::ProcessFire(void) CPed *ped = (CPed *)m_pEntity; CVehicle *veh = (CVehicle*)m_pEntity; + m_fWaterExtinguishCountdown = Min(1.0f, 0.002f * CTimer::GetTimeStep() + m_fWaterExtinguishCountdown); + if (m_pEntity) { m_vecPos = m_pEntity->GetPosition(); @@ -109,7 +113,7 @@ CFire::ProcessFire(void) gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1); } if (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) { - m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + 80; + m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + (m_fWaterExtinguishCountdown < 0.3f ? 400 : (m_fWaterExtinguishCountdown < 0.7f ? 200 : 80)); firePos = m_vecPos; if (veh && veh->IsVehicle() && veh->IsCar()) { @@ -170,11 +174,23 @@ CFire::Extinguish(void) m_nExtinguishTime = 0; m_bIsOngoing = false; + m_bExtinguishedWithWater = false; if (m_pEntity) { if (m_pEntity->IsPed()) { - ((CPed *)m_pEntity)->RestorePreviousState(); - ((CPed *)m_pEntity)->m_pFire = nil; + CPed *ped = (CPed*)m_pEntity; + if (ped->CanSetPedState()) { + if (ped->m_nPedState != PED_DRIVING && ped->m_nPedState != PED_FALL) { + if (ped->IsPlayer()) { + ped->SetIdle(); + } else { + ped->m_nLastPedState = PED_NONE; + ped->SetWanderPath(0); + ped->SetWaitState(WAITSTATE_FINISH_FLEE, 0); + } + } + } + ped->m_pFire = nil; } else if (m_pEntity->IsVehicle()) { ((CVehicle *)m_pEntity)->m_pCarFire = nil; } @@ -184,7 +200,7 @@ CFire::Extinguish(void) } void -CFireManager::StartFire(CVector pos, float size, bool propagation) +CFireManager::StartFire(CVector pos, float size, uint8 propagation) { CFire *fire = GetNextFreeFire(); @@ -201,11 +217,12 @@ CFireManager::StartFire(CVector pos, float size, bool propagation) fire->m_nNextTimeToAddFlames = 0; fire->ReportThisFire(); fire->m_fStrength = size; + fire->m_bExtinguishedWithWater = false; } } CFire * -CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation) +CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation) { CPed *ped = (CPed *)entityOnFire; CVehicle *veh = (CVehicle *)entityOnFire; @@ -234,10 +251,11 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength ped->SetFlee(pos, 10000); ped->m_fleeFrom = nil; } + ped->m_fleeTimer = CTimer::GetTimeInMilliseconds() + 10000; ped->bDrawLast = false; ped->SetMoveState(PEDMOVE_SPRINT); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } if (fleeFrom) { if (ped->m_nPedType == PEDTYPE_COP) { @@ -251,6 +269,9 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } else { if (entityOnFire->IsVehicle()) { veh->m_pCarFire = fire; + if (CModelInfo::IsBikeModel(veh->GetModelIndex()) || CModelInfo::IsCarModel(veh->GetModelIndex())) + CCarAI::TellOccupantsToFleeCar(veh); + if (fleeFrom) { CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE, entityOnFire, (CPed *)fleeFrom, 10000); @@ -259,6 +280,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } fire->m_bIsOngoing = true; + fire->m_bExtinguishedWithWater = false; fire->m_bIsScriptFire = false; fire->m_vecPos = entityOnFire->GetPosition(); @@ -297,26 +319,23 @@ CFireManager::Update(void) CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance) { - for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) { - int fireId = -1; - float minDistance = 999999; - for (int j = 0; j < NUM_FIRES; j++) { - if (!m_aFires[j].m_bIsOngoing) - continue; - if (m_aFires[j].m_bIsScriptFire) - continue; - if (m_aFires[j].m_nFiremenPuttingOut != i) - continue; - float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); - if (distance < minDistance) { - minDistance = distance; - fireId = j; - } + int fireId = -1; + float minDistance = 999999; + for (int j = 0; j < NUM_FIRES; j++) { + if (!m_aFires[j].m_bIsOngoing) + continue; + if (m_aFires[j].m_bIsScriptFire) + continue; + float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); + if (distance < minDistance) { + minDistance = distance; + fireId = j; } - *pDistance = minDistance; - if (fireId != -1) - return &m_aFires[fireId]; } + *pDistance = minDistance; + if (fireId != -1) + return &m_aFires[fireId]; + return nil; } @@ -369,8 +388,39 @@ CFireManager::ExtinguishPoint(CVector point, float range) } } +bool +CFireManager::ExtinguishPointWithWater(CVector point, float range) +{ + int fireI = 0; + for (int i = 0; i < NUM_FIRES; i++) { + if (m_aFires[i].m_bIsOngoing) { + if ((point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range)) { + fireI = i; + break; + } + } + } + if (fireI == NUM_FIRES) + return false; + + CFire *fireToExtinguish = &m_aFires[fireI]; + fireToExtinguish->m_fWaterExtinguishCountdown -= 0.012f * CTimer::GetTimeStep(); + CVector steamPos = fireToExtinguish->m_vecPos + + CVector((CGeneral::GetRandomNumber() - 128) * 31.f / 200.f, + (CGeneral::GetRandomNumber() - 128) * 31.f / 200.f, + CGeneral::GetRandomNumber() / 200.f); + + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.2f), nil, 0.5f); + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.1f), nil, 0.8f); + fireToExtinguish->m_bExtinguishedWithWater = true; + if (fireToExtinguish->m_fWaterExtinguishCountdown < 0.0f ) + fireToExtinguish->Extinguish(); + + return true; +} + int32 -CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation) +CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation) { CFire *fire; CPed *ped = (CPed *)target; @@ -397,12 +447,15 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt fire->m_vecPos = pos; fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400; fire->m_pEntity = target; + fire->m_bExtinguishedWithWater = false; if (target) target->RegisterReference(&fire->m_pEntity); fire->m_pSource = nil; fire->m_nNextTimeToAddFlames = 0; fire->m_fStrength = strength; + fire->m_fWaterExtinguishCountdown = 1.0f; + if (target) { if (target->IsPed()) { ped->m_pFire = fire; @@ -410,7 +463,7 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt CVector2D pos = target->GetPosition(); ped->SetFlee(pos, 10000); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } } else if (target->IsVehicle()) { veh->m_pCarFire = fire; @@ -430,8 +483,7 @@ CFireManager::RemoveAllScriptFires(void) { for (int i = 0; i < NUM_FIRES; i++) { if (m_aFires[i].m_bIsScriptFire) { - m_aFires[i].Extinguish(); - m_aFires[i].m_bIsScriptFire = false; + RemoveScriptFire(i); } } } diff --git a/src/core/Fire.h b/src/core/Fire.h index 85e53f61..8126f830 100644 --- a/src/core/Fire.h +++ b/src/core/Fire.h @@ -14,10 +14,10 @@ public: CEntity *m_pSource; uint32 m_nExtinguishTime; uint32 m_nStartTime; - int32 field_20; uint32 m_nNextTimeToAddFlames; - uint32 m_nFiremenPuttingOut; float m_fStrength; + float m_fWaterExtinguishCountdown; + bool m_bExtinguishedWithWater; CFire(); ~CFire(); @@ -34,15 +34,17 @@ class CFireManager public: uint32 m_nTotalFires; CFire m_aFires[NUM_FIRES]; - void StartFire(CVector pos, float size, bool propagation); - CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation); + + void StartFire(CVector pos, float size, uint8 propagation); + CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation); void Update(void); CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange); CFire *FindNearestFire(CVector vecPos, float *pDistance); CFire *GetNextFreeFire(void); uint32 GetTotalActiveFires() const; void ExtinguishPoint(CVector point, float range); - int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation); + bool ExtinguishPointWithWater(CVector point, float range); + int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation); bool IsScriptFireExtinguish(int16 index); void RemoveAllScriptFires(void); void RemoveScriptFire(int16 index); diff --git a/src/core/User.cpp b/src/core/User.cpp index 53196d03..8d584b74 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -10,6 +10,8 @@ #include "World.h" #include "Zones.h" +// --MIAMI: file done + CPlaceName CUserDisplay::PlaceName; COnscreenTimer CUserDisplay::OnscnTimer; CPager CUserDisplay::Pager; diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 1eb1513e..288b975e 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -9,7 +9,7 @@ #include "World.h" #include "Timer.h" -//--MIAMI: file almost done (loading/saving will perhaps stay different) +//--MIAMI: file done eLevelName CTheZones::m_CurrLevel; int16 CTheZones::FindIndex; @@ -638,127 +638,132 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) + sizeof(int16) // padding + sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray) + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(int16) // padding + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); - WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); + uint32 length = 0; + WriteSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); - WriteSaveBuf(buffer, m_CurrLevel); - WriteSaveBuf(buffer, FindIndex); - WriteSaveBuf(buffer, (int16)0); // padding + WriteSaveBuf(buffer, length, m_CurrLevel); + WriteSaveBuf(buffer, length, FindIndex); + WriteSaveBuf(buffer, length, (int16)0); // padding -// TODO(MIAMI) ? implement SaveOneZone - for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ - CZone *zone = WriteSaveBuf(buffer, NavigationZoneArray[i]); - zone->child = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].next); - } + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + SaveOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ - CZone *zone = WriteSaveBuf(buffer, InfoZoneArray[i]); - /* - The call of GetIndexForZonePointer is wrong, as it is - meant for a different array, but the game doesn't brake - if those fields are nil. Let's make sure they are. - */ - assert(InfoZoneArray[i].child == nil); - assert(InfoZoneArray[i].parent == nil); - assert(InfoZoneArray[i].next == nil); - zone->child = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].next); - } + for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + SaveOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) - WriteSaveBuf(buffer, ZoneInfoArray[i]); - - WriteSaveBuf(buffer, TotalNumberOfNavigationZones); - WriteSaveBuf(buffer, TotalNumberOfInfoZones); - WriteSaveBuf(buffer, TotalNumberOfZoneInfos); - - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { - CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); - - // see above - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); - zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); - } + WriteSaveBuf(buffer, length, ZoneInfoArray[i]); + + WriteSaveBuf(buffer, length, TotalNumberOfNavigationZones); + WriteSaveBuf(buffer, length, TotalNumberOfInfoZones); + WriteSaveBuf(buffer, length, TotalNumberOfZoneInfos); + WriteSaveBuf(buffer, length, (int16)0); // padding + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + SaveOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) - WriteSaveBuf(buffer, AudioZoneArray[i]); + WriteSaveBuf(buffer, length, AudioZoneArray[i]); - WriteSaveBuf(buffer, TotalNumberOfMapZones); - WriteSaveBuf(buffer, NumberOfAudioZones); + WriteSaveBuf(buffer, length, TotalNumberOfMapZones); + WriteSaveBuf(buffer, length, NumberOfAudioZones); VALIDATESAVEBUF(*size) } void +CTheZones::SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) +{ + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[0]); + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[4]); + + WriteSaveBuf(*buffer, *length, zone->minx); + WriteSaveBuf(*buffer, *length, zone->miny); + WriteSaveBuf(*buffer, *length, zone->minz); + WriteSaveBuf(*buffer, *length, zone->maxx); + WriteSaveBuf(*buffer, *length, zone->maxy); + WriteSaveBuf(*buffer, *length, zone->maxz); + + WriteSaveBuf(*buffer, *length, zone->type); + WriteSaveBuf(*buffer, *length, zone->level); + WriteSaveBuf(*buffer, *length, zone->zoneinfoDay); + WriteSaveBuf(*buffer, *length, zone->zoneinfoNight); + + int32 zoneId; + zoneId = GetIndexForZonePointer(zone->child); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForZonePointer(zone->parent); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForZonePointer(zone->next); + WriteSaveBuf(*buffer, *length, zoneId); +} + +void CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { INITSAVEBUF int i; - CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); + uint32 length = 0; + CheckSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - m_CurrLevel = ReadSaveBuf<eLevelName>(buffer); - FindIndex = ReadSaveBuf<int16>(buffer); - ReadSaveBuf<int16>(buffer); + m_CurrLevel = ReadSaveBuf<eLevelName>(buffer, length); + FindIndex = ReadSaveBuf<int16>(buffer, length); + ReadSaveBuf<int16>(buffer, length); -// TODO(MIAMI) ? implement LoadOneZone - for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ - NavigationZoneArray[i] = ReadSaveBuf<CZone>(buffer); + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + LoadOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - NavigationZoneArray[i].child = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].child); - NavigationZoneArray[i].parent = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].parent); - NavigationZoneArray[i].next = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].next); - } - - for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ - InfoZoneArray[i] = ReadSaveBuf<CZone>(buffer); - - /* - The call of GetPointerForZoneIndex is wrong, as it is - meant for a different array, but the game doesn't brake - if save data stored is -1. - */ - InfoZoneArray[i].child = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].child); - InfoZoneArray[i].parent = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].parent); - InfoZoneArray[i].next = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].next); - assert(InfoZoneArray[i].child == nil); - assert(InfoZoneArray[i].parent == nil); - assert(InfoZoneArray[i].next == nil); - } + for (i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + LoadOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) - ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer); - - TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer); - TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer); - TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer); - - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ - MapZoneArray[i] = ReadSaveBuf<CZone>(buffer); - - // see above - MapZoneArray[i].child = GetPointerForZoneIndex((uintptr)MapZoneArray[i].child); - MapZoneArray[i].parent = GetPointerForZoneIndex((uintptr)MapZoneArray[i].parent); - MapZoneArray[i].next = GetPointerForZoneIndex((uintptr)MapZoneArray[i].next); - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); - } + ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer, length); + + TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer, length); + TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer, length); + TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer, length); + ReadSaveBuf<int16>(buffer, length); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + LoadOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) - AudioZoneArray[i] = ReadSaveBuf<int16>(buffer); + AudioZoneArray[i] = ReadSaveBuf<int16>(buffer, length); - TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer); - NumberOfAudioZones = ReadSaveBuf<uint16>(buffer); + TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer, length); + NumberOfAudioZones = ReadSaveBuf<uint16>(buffer, length); VALIDATESAVEBUF(size) } + +void +CTheZones::LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) +{ + *(uint32*)&zone->name[0] = ReadSaveBuf<uint32>(*buffer, *length); + *(uint32*)&zone->name[4] = ReadSaveBuf<uint32>(*buffer, *length); + + zone->minx = ReadSaveBuf<float>(*buffer, *length); + zone->miny = ReadSaveBuf<float>(*buffer, *length); + zone->minz = ReadSaveBuf<float>(*buffer, *length); + zone->maxx = ReadSaveBuf<float>(*buffer, *length); + zone->maxy = ReadSaveBuf<float>(*buffer, *length); + zone->maxz = ReadSaveBuf<float>(*buffer, *length); + + zone->type = ReadSaveBuf<eZoneType>(*buffer, *length); + zone->level = ReadSaveBuf<eLevelName>(*buffer, *length); + zone->zoneinfoDay = ReadSaveBuf<int16>(*buffer, *length); + zone->zoneinfoNight = ReadSaveBuf<int16>(*buffer, *length); + + int32 zoneId; + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->child = GetPointerForZoneIndex(zoneId); + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->parent = GetPointerForZoneIndex(zoneId); + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->next = GetPointerForZoneIndex(zoneId); +}
\ No newline at end of file diff --git a/src/core/Zones.h b/src/core/Zones.h index 92e292b8..3a74427d 100644 --- a/src/core/Zones.h +++ b/src/core/Zones.h @@ -108,5 +108,7 @@ public: static void AddZoneToAudioZoneArray(CZone *zone); static void InitialiseAudioZoneArray(void); static void SaveAllZones(uint8 *buffer, uint32 *length); + static void SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); static void LoadAllZones(uint8 *buffer, uint32 length); + static void LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); }; diff --git a/src/core/common.h b/src/core/common.h index c4c133fa..0e6bd60f 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -412,6 +412,15 @@ inline void SkipSaveBuf(uint8 *&buf, int32 skip) #endif } +inline void SkipSaveBuf(uint8*& buf, uint32 &length, int32 skip) +{ + buf += skip; + length += skip; +#ifdef VALIDATE_SAVE_SIZE + _saveBufCount += skip; +#endif +} + template<typename T> inline const T ReadSaveBuf(uint8 *&buf) { @@ -421,6 +430,14 @@ inline const T ReadSaveBuf(uint8 *&buf) } template<typename T> +inline const T ReadSaveBuf(uint8 *&buf, uint32 &length) +{ + T &value = *(T*)buf; + SkipSaveBuf(buf, length, sizeof(T)); + return value; +} + +template<typename T> inline T *WriteSaveBuf(uint8 *&buf, const T &value) { T *p = (T*)buf; @@ -429,6 +446,15 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) return p; } +template<typename T> +inline T *WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value) +{ + T *p = (T*)buf; + *p = value; + SkipSaveBuf(buf, length, sizeof(T)); + return p; +} + #define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32)) @@ -439,6 +465,13 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) WriteSaveBuf(buf, d);\ WriteSaveBuf<uint32>(buf, size); +#define WriteSaveHeaderWithLength(buf,len,a,b,c,d,size) \ + WriteSaveBuf(buf, len, a);\ + WriteSaveBuf(buf, len, b);\ + WriteSaveBuf(buf, len, c);\ + WriteSaveBuf(buf, len, d);\ + WriteSaveBuf<uint32>(buf, len, size); + #define CheckSaveHeader(buf,a,b,c,d,size)\ assert(ReadSaveBuf<char>(buf) == a);\ assert(ReadSaveBuf<char>(buf) == b);\ @@ -446,5 +479,12 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) assert(ReadSaveBuf<char>(buf) == d);\ assert(ReadSaveBuf<uint32>(buf) == size); +#define CheckSaveHeaderWithLength(buf,len,a,b,c,d,size)\ + assert(ReadSaveBuf<char>(buf,len) == a);\ + assert(ReadSaveBuf<char>(buf,len) == b);\ + assert(ReadSaveBuf<char>(buf,len) == c);\ + assert(ReadSaveBuf<char>(buf,len) == d);\ + assert(ReadSaveBuf<uint32>(buf,len) == size); + void cprintf(char*, ...);
\ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index 079042f0..3f077f4c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -87,7 +87,8 @@ enum Config { NUMMBLURSTREAKS = 4, NUMSKIDMARKS = 32, - NUMONSCREENTIMERENTRIES = 1, + NUMONSCREENCLOCKS = 1, + NUMONSCREENCOUNTERS = 3, NUMRADARBLIPS = 75, NUMGENERALPICKUPS = 320, NUMSCRIPTEDPICKUPS = 16, @@ -249,6 +250,9 @@ enum Config { #if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif +#if !defined(_WIN32) && !defined(__SWITCH__) +#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and expect user to enter Controller->Detect joysticks if his joystick isn't on that list. +#endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT #define RESTORE_ALLCARSHELI_CHEAT @@ -258,7 +262,6 @@ enum Config { //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls // Hud, frontend and radar -#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. //#define BETA_SLIDING_TEXT #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC #define PC_MENU @@ -324,4 +327,4 @@ enum Config { #undef NO_ISLAND_LOADING #define PC_PARTICLE #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial -#endif
\ No newline at end of file +#endif diff --git a/src/extras/ini_parser.hpp b/src/extras/ini_parser.hpp new file mode 100644 index 00000000..99acf1ee --- /dev/null +++ b/src/extras/ini_parser.hpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com> + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ +#ifndef LINB_INI_PARSER_HPP +#define LINB_INI_PARSER_HPP + +/* + * STL-like INI Container + */ + +#include <string> // for std::string +#include <map> // for std::map +#include <cstdio> // for std::FILE +#include <algorithm> // for std::find_if +#include <functional> // for std::function + +namespace linb +{ + template< + class CharT = char, /* Not compatible with other type here, since we're using C streams */ + class StringType = std::basic_string<CharT>, + class KeyContainer = std::map<StringType, StringType>, + class SectionContainer = std::map<StringType, KeyContainer> + > class basic_ini + { + public: + typedef CharT char_type; + typedef StringType string_type; + typedef KeyContainer key_container; + typedef SectionContainer section_container; + + // Typedef container values types + typedef typename section_container::value_type value_type; + typedef typename section_container::key_type key_type; + typedef typename section_container::mapped_type mapped_type; + + // Typedef common types + typedef typename section_container::size_type size_type; + typedef typename section_container::difference_type difference_type; + + // Typedef iterators + typedef typename section_container::iterator iterator; + typedef typename section_container::const_iterator const_iterator; + typedef typename section_container::reverse_iterator reverse_iterator; + typedef typename section_container::const_reverse_iterator const_reverse_iterator; + + // typedef References and pointers + typedef typename section_container::reference reference; + typedef typename section_container::const_reference const_reference; + typedef typename section_container::pointer pointer; + typedef typename section_container::const_pointer const_pointer; + + private: + section_container data; + + public: + + basic_ini() + { } + + basic_ini(const char_type* filename) + { this->read_file(filename); } + + /* Iterator methods */ + iterator begin() + { return data.begin(); } + const_iterator begin() const + { return data.begin(); } + iterator end() + { return data.end(); } + const_iterator end() const + { return data.end(); } + const_iterator cbegin() const + { return data.cbegin(); } + const_iterator cend() const + { return data.cend(); } + + /* Reverse iterator methods */ + reverse_iterator rbegin() + { return data.rbegin(); } + const_reverse_iterator rbegin() const + { return data.rbegin(); } + reverse_iterator rend() + { return data.rend(); } + const_reverse_iterator rend() const + { return data.rend(); } + const_reverse_iterator crbegin() const + { return data.crbegin(); } + const_reverse_iterator crend() const + { return data.crend(); } + + /* Acessing index methods */ + mapped_type& operator[](const string_type& sect) + { return data[sect]; } + mapped_type& operator[](string_type&& sect) + { return data[std::forward<string_type>(sect)]; } + mapped_type& at( const string_type& sect) + { return data.at(sect); } + const mapped_type& at(const string_type& sect) const + { return data.at(sect); } + + /* Capacity information */ + bool empty() const + { return data.empty(); } + size_type size() const + { return data.size(); } + size_type max_size() const + { return data.max_size(); } + + /* Modifiers */ + void clear() + { return data.clear(); } + + /* Lookup */ + size_type count(const string_type& sect) + { return data.count(sect); } + iterator find(const string_type& sect) + { return data.find(sect); } + + /* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */ + string_type get(const string_type& sect, const key_type& key, const string_type& default_value) + { + auto it = this->find(sect); + if(it != this->end()) + { + auto itv = it->second.find(key); + if(itv != it->second.end()) + return itv->second; + } + return default_value; + } + + /* Sets the value of a value in the ini */ + void set(const string_type& sect, const key_type& key, const string_type& value) + { + (*this)[sect][key] = value; // no emplace since overwrite! + } + + /* Too lazy to continue this container... If you need more methods, just add it */ + + +#if 1 + bool read_file(const char_type* filename) + { + /* Using C stream in a STL-like container, funny? + */ + if(FILE* f = fopen(filename, "r")) + { + key_container* keys = nullptr; + char_type buf[2048]; + string_type line; + string_type key; + string_type value; + string_type null_string; + size_type pos; + + // Trims an string + auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type& + { + if(s.size()) + { + // Ignore UTF-8 BOM + while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF)) + s.erase(s.begin(), s.begin() + 3); + + if(trimLeft) + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace)))); + if(trimRight) + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end()); + } + return s; + }; + + // Start parsing + while(fgets(buf, sizeof(buf), f)) + { + // What a thing, reading into a char buffer and then putting in the string... + line = buf; + + // Find comment and remove anything after it from the line + if((pos = line.find_first_of(';')) != line.npos) + line.erase(pos); + + // Trim the string, and if it gets empty, skip this line + if(trim(line, true, true).empty()) + continue; + + // Find section name + if(line.front() == '[' && line.back() == ']') + { + pos = line.length() - 1; //line.find_first_of(']'); + if(pos != line.npos) + { + trim(key.assign(line, 1, pos-1), true, true); + keys = &data[std::move(key)]; // Create section + } + else + keys = nullptr; + } + else + { + // Find key and value positions + pos = line.find_first_of('='); + if(pos == line.npos) + { + // There's only the key + key = line; // No need for trim, line is already trimmed + value.clear(); + } + else + { + // There's the key and the value + trim(key.assign(line, 0, pos), false, true); // trim the right + trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left + } + + // Put the key/value into the current keys object, or into the section "" if no section has been found + #if __cplusplus >= 201103L || _MSC_VER >= 1800 + (keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value)); + #else + (keys ? *keys : data[null_string])[key] = value; + key.clear(); value.clear(); + #endif + } + } + + fclose(f); + return true; + } + return false; + } + + /* + * Dumps the content of this container into an ini file + */ + bool write_file(const char_type* filename) + { + if(FILE* f = fopen(filename, "w")) + { + bool first = true; + for(auto& sec : this->data) + { + fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str()); + first = false; + for(auto& kv : sec.second) + { + if(kv.second.empty()) + fprintf(f, "%s\n", kv.first.c_str()); + else + fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str()); + } + } + fclose(f); + return true; + } + return false; + } + + + /* + */ + bool load_file(const char_type* filename) + { + return read_file(filename); + } + + bool load_file(const StringType& filename) + { + return load_file(filename.c_str()); + } + + bool write_file(const StringType& filename) + { + return write_file(filename.c_str()); + } +#endif + + + + }; + + + /* Use default basic_ini + * + * Limitations: + * * Not unicode aware + * * Case sensitive + * * Sections must have unique keys + */ + typedef basic_ini<> ini; +} + +#endif + diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index a33e31f9..5b91daad 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -104,7 +104,6 @@ CEmergencyPed::FiremanAI(void) m_pAttendedFire = nearestFire; #ifdef FIX_BUGS bIsRunning = true; - ++nearestFire->m_nFiremenPuttingOut; #endif } break; @@ -116,10 +115,6 @@ CEmergencyPed::FiremanAI(void) SetMoveState(PEDMOVE_RUN); #ifdef FIX_BUGS bIsRunning = true; - if (m_pAttendedFire) { - --m_pAttendedFire->m_nFiremenPuttingOut; - } - ++nearestFire->m_nFiremenPuttingOut; m_pAttendedFire = nearestFire; } else if (!nearestFire) { #else @@ -153,10 +148,7 @@ CEmergencyPed::FiremanAI(void) case EMERGENCY_PED_STOP: #ifdef FIX_BUGS bIsRunning = false; - if (m_pAttendedFire) #endif - --m_pAttendedFire->m_nFiremenPuttingOut; - m_nPedState = PED_NONE; SetWanderPath(CGeneral::GetRandomNumber() & 7); m_pAttendedFire = nil; diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index 131534a3..912399c9 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -24,12 +24,17 @@ float CDraw::CalculateAspectRatio(void) { if (FrontEndMenuManager.m_PrefsUseWideScreen) { +#ifdef ASPECT_RATIO_SCALE if (TheCamera.m_WideScreenOn) - CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki + CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? + (5.f / 3.f) * (SCREEN_WIDTH / SCREEN_HEIGHT) / (16.f / 9.f) : + 5.f / 3.f; // It's used on theatrical showings according to Wiki else -#ifdef ASPECT_RATIO_SCALE CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f; #else + if (TheCamera.m_WideScreenOn) + CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki + else CDraw::ms_fAspectRatio = 16.f / 9.f; #endif } else if (TheCamera.m_WideScreenOn) { diff --git a/src/render/Font.cpp b/src/render/Font.cpp index c0cc333a..f14e45cd 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -5,6 +5,46 @@ #include "Font.h" #include "Timer.h" +void +AsciiToUnicode(const char *src, wchar *dst) +{ + while((*dst++ = (unsigned char)*src++) != '\0'); +} + +void +UnicodeStrcat(wchar *dst, wchar *append) +{ + UnicodeStrcpy(&dst[UnicodeStrlen(dst)], append); +} + +void +UnicodeStrcpy(wchar *dst, const wchar *src) +{ + while((*dst++ = *src++) != '\0'); +} + +int +UnicodeStrlen(const wchar *str) +{ + int len; + for(len = 0; *str != '\0'; len++, str++); + return len; +} + +void +UnicodeMakeUpperCase(wchar *dst, const wchar *src) //idk what to do with it, seems to be incorrect implementation by R* +{ + while (*src != '\0') { + if (*src < 'a' || *src > 'z') + *dst = *src; + else + *dst = *src - 32; + dst++; + src++; + } + *dst = '\0'; +} + CFontDetails CFont::Details; int16 CFont::NewLine; CSprite2d CFont::Sprite[MAX_FONTS]; @@ -1102,6 +1142,7 @@ CFont::ParseToken(wchar *s) switch(*s){ case 'B': Details.bBold = !Details.bBold; + break; case 'N': case 'n': NewLine = 1; @@ -1109,7 +1150,7 @@ CFont::ParseToken(wchar *s) case 'b': SetColor(CRGBA(27, 89, 130, 255)); Details.anonymous_23 = true; break; case 'f': Details.bFlash = !Details.bFlash; - if (Details.bFlash) + if (!Details.bFlash) Details.color.a = 255; break; case 'g': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break; diff --git a/src/render/Font.h b/src/render/Font.h index ca0ed7d0..47a39f73 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -1,5 +1,11 @@ #pragma once +void AsciiToUnicode(const char *src, wchar *dst); +void UnicodeStrcpy(wchar *dst, const wchar *src); +void UnicodeStrcat(wchar *dst, wchar *append); +int UnicodeStrlen(const wchar *str); +void UnicodeMakeUpperCase(wchar *dst, const wchar *src); + struct CFontDetails { CRGBA color; diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 36815ab5..3ea756fa 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -23,6 +23,9 @@ #include "CutsceneMgr.h" #include "Stats.h" #include "main.h" +#include "General.h" + +// --MIAMI: file done // Game has colors inlined in code. // For easier modification we collect them here: @@ -46,13 +49,14 @@ 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]; -wchar CHud::m_LastHelpMessage[256]; +wchar CHud::m_HelpMessage[HELP_MSG_LENGTH]; +wchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH]; uint32 CHud::m_HelpMessageState; uint32 CHud::m_HelpMessageTimer; int32 CHud::m_HelpMessageFadeTimer; -wchar CHud::m_HelpMessageToPrint[256]; -float CHud::m_fHelpMessageTime; +wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH]; +float CHud::m_HelpMessageDisplayTime; +bool CHud::m_HelpMessageDisplayForever; bool CHud::m_HelpMessageQuick; uint32 CHud::m_ZoneState; int32 CHud::m_ZoneFadeTimer; @@ -73,16 +77,16 @@ 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; +int32 CHud::m_ClockState; // These aren't really in CHud float CHud::BigMessageInUse[6]; float CHud::BigMessageAlpha[6]; float CHud::BigMessageX[6]; float CHud::OddJob2OffTimer; -bool CHud::CounterOnLastFrame; +bool CHud::CounterOnLastFrame[NUMONSCREENCOUNTERS]; float CHud::OddJob2XOffset; -uint16 CHud::CounterFlashTimer; +uint16 CHud::CounterFlashTimer[NUMONSCREENCOUNTERS]; uint16 CHud::OddJob2Timer; bool CHud::TimerOnLastFrame; int16 CHud::OddJob2On; @@ -110,6 +114,8 @@ uint32 CHud::m_WeaponTimer; uint32 CHud::m_LastDisplayScore; uint32 CHud::m_LastWanted; +uint32 CHud::m_LastWeapon; +uint32 CHud::m_LastTimeEnergyLost; CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; @@ -118,33 +124,82 @@ struct const char *name; const char *mask; } WeaponFilenames[] = { - {"fist", "fistm"}, - {"bat", "batm"}, - {"pistol", "pistolm" }, - {"uzi", "uzim"}, - {"shotgun", "shotgunm"}, - {"ak47", "ak47m"}, - {"m16", "m16m"}, - {"sniper", "sniperm"}, - {"rocket", "rocketm"}, - {"flame", "flamem"}, - {"molotov", "molotovm"}, - {"grenade", "grenadem"}, - {"detonator", "detonator_mask"}, - {"", ""}, - {"", ""}, - {"radardisc", "radardisc"}, - {"pager", "pagerm"}, - {"", ""}, - {"", ""}, - {"bleeder", ""}, - {"sitesniper", "sitesniperm"}, - {"siteM16", "siteM16m"}, - {"siterocket", "siterocket"} + { "fist", "fistm" }, + { "brassk", "brasskA" }, + { "screw", "screwA" }, + { "golf", "golfA" }, + { "nightstick", "nightstickA" }, + { "knife", "knifeA" }, + { "bat", "batm" }, + { "hammer", "hammerA" }, + { "cleaver", "cleaverA" }, + { "machete", "macheteA" }, + { "sword", "swordA" }, + { "chainsaw", "chainsawA" }, + { "grenade", "grenadeA" }, + { "grenade", "grenadeA" }, + { "teargas", "teargasA" }, + { "molotov", "molotovA" }, + { "rocket", "rocketA" }, + { "handGun1", "handGun1A" }, + { "", "" }, + { "python", "pythonA" }, + { "chromegun", "chromegunA" }, + { "spasshotGun", "spasshotGunA" }, + { "stubshotGun", "stubshotGunA" }, + { "tec9", "tec9A" }, + { "uzi1", "uzi1A" }, + { "uzi2", "uzi2A" }, + { "mp5", "mp5A" }, + { "", "" }, + { "m4", "m4A" }, + { "ruger", "rugerA" }, + { "sniper", "sniperA" }, + { "laserscope", "laserscopeA" }, + { "", "" }, + { "rocket", "rocketA" }, + { "flamer", "flamerA" }, + { "m60", "m60A" }, + { "minigun", "minigunA" }, + { "bomb", "bombA" }, + { "", "" }, + { "camera", "cameraA" }, + { "", "" }, + { "siterocket", "siterocket" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "radardisc", "radardisc" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "", "" }, + { "sitesniper", "sitesniperm" }, + { "siteM16", "siteM16m" }, + { "sitelaser", "sitelaserm" }, + { "laserdot", "laserdotm" }, + { "viewfinder_128", "viewfinder_128m" }, + { "bleeder", "" } }; RwTexture *gpSniperSightTex; RwTexture *gpRocketSightTex; +RwTexture *gpLaserSightTex; +RwTexture *gpLaserDotTex; +RwTexture *gpViewFinderTex; void CHud::Draw() { @@ -160,7 +215,9 @@ void CHud::Draw() return; if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) { + // unused statics in here bool DrawCrossHair = false; + bool CrossHairHidesHud = false; bool DrawCrossHairPC = false; CPlayerPed *playerPed = FindPlayerPed(); @@ -251,38 +308,70 @@ void CHud::Draw() CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); } else { + int sprite = HUD_SITESNIPER; + float xOffset = SCREEN_SCALE_X(210.0f); + float yOffset = SCREEN_SCALE_Y(210.0f); + + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE) + sprite = HUD_SITELASER; + + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_CAMERA) { + sprite = HUD_VIEWFINDER; + CrossHairHidesHud = true; + xOffset = SCREEN_SCALE_X(256.0f); + yOffset = SCREEN_SCALE_Y(192.0f); + } - // TODO(Miami) - // Sniper - rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f); - rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); + rect.left = SCREEN_WIDTH/2 - xOffset; + rect.top = SCREEN_HEIGHT/2 - yOffset; rect.right = SCREEN_WIDTH/2; rect.bottom = SCREEN_HEIGHT/2; - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.01f, 0.01f, 1.0f, 0.0f, 0.01f, 1.0f, 1.0f, 1.0f); rect.left = SCREEN_WIDTH/2; - rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); - rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); + rect.top = SCREEN_HEIGHT/2 - yOffset; + rect.right = SCREEN_WIDTH/2 + xOffset; rect.bottom = SCREEN_HEIGHT/2; - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.99f, 0.0f, 0.01f, 0.01f, 0.99f, 1.0f, 0.01f, 1.0f); - rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f); + rect.left = SCREEN_WIDTH/2 - xOffset; rect.top = SCREEN_HEIGHT/2; rect.right = SCREEN_WIDTH/2; - rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + rect.bottom = SCREEN_HEIGHT/2 + yOffset; + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.01f, 0.99f, 1.0f, 0.99f, 0.01f, 0.01f, 1.0f, 0.01f); rect.left = SCREEN_WIDTH/2; rect.top = SCREEN_HEIGHT/2; - rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); - rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); - Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), + rect.right = SCREEN_WIDTH/2 + xOffset; + rect.bottom = SCREEN_HEIGHT/2 + yOffset; + Sprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 0.99f, 0.99f, 0.01f, 0.99f, 0.99f, 0.01f, 0.1f, 0.01f); + + CVector dotPos; + float size = 25.0f; + if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE && FindPlayerPed()->GetWeapon()->LaserScopeDot(&dotPos, &size)) { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpLaserDotTex)); +#ifdef FIX_BUGS + int intensity = CGeneral::GetRandomNumberInRange(0, 37); +#else + int intensity = CGeneral::GetRandomNumberInRange(0, 35); +#endif + CSprite::RenderOneXLUSprite(dotPos.x, dotPos.y, dotPos.z, + SCREEN_SCALE_X(size), SCREEN_SCALE_Y(size), intensity - 36, 0, 0, intensity - 36, 1.0f, 127); + + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + } } } RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); @@ -293,6 +382,9 @@ void CHud::Draw() SpriteBrightness = 0; } + if (CrossHairHidesHud) + return; + /* DrawMoneyCounter */ @@ -303,9 +395,9 @@ void CHud::Draw() float alpha; if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) { - alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 0); + alpha = DrawFadeState(HUD_SCORE_FADING, 0); } else { - alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 1); + alpha = DrawFadeState(HUD_SCORE_FADING, 1); m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; } if (m_DisplayScoreState != FADED_OUT) { @@ -334,151 +426,168 @@ void CHud::Draw() /* DrawAmmo */ - CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType); - CWeapon *weapon = playerPed->GetWeapon(); - uint32 AmmoAmount = weaponInfo->m_nAmountofAmmunition; - uint32 AmmoInClip = weapon->m_nAmmoInClip; - uint32 TotalAmmo = weapon->m_nAmmoTotal; - uint32 Ammo, Clip; - - if (AmmoAmount <= 1 || AmmoAmount >= 1000) - sprintf(sTemp, "%d", TotalAmmo); - else { - if (WeaponType == WEAPONTYPE_FLAMETHROWER) { - Clip = AmmoInClip / 10; - - if ((TotalAmmo - AmmoInClip) / 10 <= 9999) - Ammo = (TotalAmmo - AmmoInClip) / 10; - else - Ammo = 9999; - } + if (m_LastWeapon == playerPed->GetWeapon()->m_eWeaponType) { + alpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 0); + } else { + alpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 1); + m_LastWeapon = playerPed->GetWeapon()->m_eWeaponType; + } + if (m_WeaponState != FADED_OUT) { + CWeapon *weapon = playerPed->GetWeapon(); + uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType)->m_nAmountofAmmunition; + uint32 AmmoInClip = weapon->m_nAmmoInClip; + uint32 TotalAmmo = weapon->m_nAmmoTotal; + uint32 Ammo, Clip; + + if (AmmoAmount <= 1 || AmmoAmount >= 1000) + sprintf(sTemp, "%d", TotalAmmo); else { - Clip = AmmoInClip; + if (WeaponType == WEAPONTYPE_FLAMETHROWER) { + Clip = AmmoInClip / 10; - if ((TotalAmmo - AmmoInClip) > 9999) - Ammo = 9999; - else - Ammo = TotalAmmo - AmmoInClip; - } + Ammo = Min((TotalAmmo - AmmoInClip) / 10, 9999); + } else { + Clip = AmmoInClip; - sprintf(sTemp, "%d-%d", Ammo, Clip); - } + Ammo = Min(TotalAmmo - AmmoInClip, 9999); + } - AsciiToUnicode(sTemp, sPrint); + sprintf(sTemp, "%d-%d", Ammo, Clip); + } - /* - DrawWeaponIcon - */ + AsciiToUnicode(sTemp, sPrint); + CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType); + /* + DrawWeaponIcon + */ - if (weaponInfo->m_nModelId <= 0) { - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - Sprites[WeaponType].Draw( - CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)), - CRGBA(255, 255, 255, 255), - 0.015f, - 0.015f, - 1.0f, - 0.0f, - 0.015f, - 1.0f, - 1.0f, - 1.0f); - } else { - CBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId); - RwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict; - if (weaponTxd) { - RwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetName()); - if (weaponIcon) { + if (FrontEndMenuManager.m_PrefsShowHud) { + if (weaponInfo->m_nModelId <= 0) { RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon)); - const float xSize = SCREEN_SCALE_X(64.0f / 2.0f); - const float ySize = SCREEN_SCALE_X(64.0f / 2.0f); - CSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize, - 255, 255, 255, 255, 1.0f, 255); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + if (FrontEndMenuManager.m_PrefsShowHud) + Sprites[WeaponType].Draw( + CRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)), + CRGBA(255, 255, 255, alpha), + 0.015f, + 0.015f, + 1.0f, + 0.0f, + 0.015f, + 1.0f, + 1.0f, + 1.0f); + } else { + CBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId); + RwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict; + if (weaponTxd) { + RwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetName()); + if (weaponIcon) { + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon)); + const float xSize = SCREEN_SCALE_X(64.0f / 2.0f); + const float ySize = SCREEN_SCALE_X(64.0f / 2.0f); + CSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize, + 255, 255, 255, 255, 1.0f, 255); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + } + } } - } - } - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f)); - CFont::SetJustifyOff(); - CFont::SetCentreOn(); - CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - CFont::SetPropOn(); - CFont::SetDropShadowPosition(0); - CFont::SetFontStyle(FONT_STANDARD); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f)); + CFont::SetJustifyOff(); + CFont::SetCentreOn(); + CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetPropOn(); + CFont::SetDropShadowPosition(0); + CFont::SetFontStyle(FONT_STANDARD); - if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { - CFont::SetDropShadowPosition(2); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); - CFont::SetColor(AMMO_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint); - CFont::SetDropShadowPosition(0); + if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, alpha)); + AMMO_COLOR.a = alpha; + CFont::SetColor(AMMO_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint); + CFont::SetDropShadowPosition(0); + } + } } /* DrawHealth */ - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - CFont::SetJustifyOff(); - CFont::SetCentreOff(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetRightJustifyOn(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetDropShadowPosition(2); - CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + if ( m_LastTimeEnergyLost == CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss ) { + CHud::DrawFadeState(HUD_ENERGY_FADING, 0); + } else { + CHud::DrawFadeState(HUD_ENERGY_FADING, 1); + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; + } - if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8 - || m_ItemToFlash != ITEM_HEALTH - || playerPed->m_fHealth < 10 - && CTimer::GetFrameCounter() & 8) { - if (playerPed->m_fHealth >= 10 - || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { + if (m_EnergyLostState != FADED_OUT) { + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetJustifyOff(); + CFont::SetCentreOff(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetRightJustifyOn(); + CFont::SetPropOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + + if (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8 + || m_ItemToFlash != ITEM_HEALTH + || playerPed->m_fHealth < 10 + && CTimer::GetFrameCounter() & 8) { + if (playerPed->m_fHealth >= 10 + || playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) { - AsciiToUnicode("{", sPrintIcon); + AsciiToUnicode("{", sPrintIcon); #ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(playerPed->m_fHealth + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fHealth + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)playerPed->m_fHealth); + sprintf(sTemp, "%03d", (int32)playerPed->m_fHealth); #endif - AsciiToUnicode(sTemp, sPrint); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(HEALTH_COLOR); + CFont::SetColor(HEALTH_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) { + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint); - - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { - // CFont::SetColor(HEALTH_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) { + // CFont::SetColor(HEALTH_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } } } - } - /* - DrawArmour - */ - if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) { - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - if (playerPed->m_fArmour > 1.0f) { - AsciiToUnicode("<", sPrintIcon); + /* + DrawArmour + */ + if (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) { + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + if (playerPed->m_fArmour > 1.0f) { + AsciiToUnicode("<", sPrintIcon); #ifdef FIX_BUGS - sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f)); + sprintf(sTemp, "%03d", int32(playerPed->m_fArmour + 0.5f)); #else - sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour); + sprintf(sTemp, "%03d", (int32)playerPed->m_fArmour); #endif - AsciiToUnicode(sTemp, sPrint); + AsciiToUnicode(sTemp, sPrint); - CFont::SetColor(ARMOUR_COLOR); + CFont::SetColor(ARMOUR_COLOR); + if (FrontEndMenuManager.m_PrefsShowHud) { - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint); - if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) { - // CFont::SetColor(ARMOUR_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 1) { + // CFont::SetColor(ARMOUR_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon); + } + } } } } @@ -486,10 +595,10 @@ void CHud::Draw() /* DrawWantedLevel */ - if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) - alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 0); - else { - alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 1); + if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) { + alpha = DrawFadeState(HUD_WANTED_FADING, 0); + } else { + alpha = DrawFadeState(HUD_WANTED_FADING, 1); m_LastWanted = playerPed->m_pWanted->m_nWantedLevel; } @@ -745,11 +854,7 @@ void CHud::Draw() break; } -#ifndef HUD_ENHANCEMENTS if (!m_Message[0]) { -#else - if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide vehicle name if wasted/busted text is displaying -#endif m_VehicleNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); @@ -787,7 +892,7 @@ void CHud::Draw() /* DrawClock */ - if (m_DrawClock) { + if (m_ClockState) { CFont::SetJustifyOff(); CFont::SetCentreOff(); CFont::SetBackgroundOff(); @@ -814,30 +919,28 @@ void CHud::Draw() wchar sTimer[16]; - if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) + if (!CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) TimerOnLastFrame = false; - if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) - CounterOnLastFrame = false; -#ifdef FIX_BUGS -#define TIMER_RIGHT_OFFSET 34.0f // Taken from VC frenzy timer -#else -#define TIMER_RIGHT_OFFSET 27.0f -#endif + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + if (!CUserDisplay::OnscnTimer.m_sCounters[0].m_bCounterProcessed) + CounterOnLastFrame[i] = false; + } + if (CUserDisplay::OnscnTimer.m_bProcessed) { - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) { + if (CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) { if (!TimerOnLastFrame) TimerFlashTimer = 1; TimerOnLastFrame = true; - if (TimerFlashTimer) { + if (TimerFlashTimer != 0) { if (++TimerFlashTimer > 50) TimerFlashTimer = 0; } - if (CTimer::GetFrameCounter() & 4 || !TimerFlashTimer) { - AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer); + if (CTimer::GetFrameCounter() & 4 || TimerFlashTimer == 0) { + AsciiToUnicode(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockBuffer, sTimer); CFont::SetPropOn(); CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); @@ -846,126 +949,84 @@ void CHud::Draw() CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetPropOff(); CFont::SetBackGroundOnlyTextOn(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), sTimer); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetColor(TIMER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); - - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) { - CFont::SetPropOn(); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(SCREEN_SCALE_X(0.64f), SCREEN_SCALE_Y(1.35f)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(110.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(110.0f), sTimer); + CFont::SetPropOn(); + if (CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText[0]) { + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(TIMER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText)); } } } - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed) { - if (!CounterOnLastFrame) - CounterFlashTimer = 1; - CounterOnLastFrame = true; + for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) { + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_bCounterProcessed) { + if (!CounterOnLastFrame[i]) + CounterFlashTimer[i] = 1; - if (CounterFlashTimer) { - if (++CounterFlashTimer > 50) - CounterFlashTimer = 0; - } + CounterOnLastFrame[i] = true; - if (CTimer::GetFrameCounter() & 4 || !CounterFlashTimer) { - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_nType == COUNTER_DISPLAY_NUMBER) { - AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer, sTimer); - CFont::SetPropOn(); - - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - CFont::SetCentreOff(); - CFont::SetRightJustifyOn(); - CFont::SetRightJustifyWrap(0.0f); - CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); - CFont::SetColor(CRGBA(244, 20, 20, 255)); - CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); - CFont::SetPropOff(); - CFont::SetBackGroundOnlyTextOn(); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), sTimer); - - CFont::SetColor(COUNTER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(132.0f), sTimer); - } else { - int counter = atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer); -#ifdef FIX_BUGS - counter = Min(counter, 100); -#endif - CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 80)); - CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET + 50.0f) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 255)); + if (CounterFlashTimer[i] != 0) { + if (++CounterFlashTimer[i] > 50) + CounterFlashTimer[i] = 0; } - if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) { - CFont::SetPropOn(); - CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f) + SCREEN_SCALE_Y(2.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(2.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); - - CFont::SetColor(COUNTER_COLOR); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText)); + if (CTimer::GetFrameCounter() & 4 || CounterFlashTimer[i] == 0) { + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_nType == COUNTER_DISPLAY_NUMBER) { + AsciiToUnicode(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer, sTimer); + CFont::SetPropOn(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); + CFont::SetPropOn(); + CFont::SetBackGroundOnlyTextOn(); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(COUNTER_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), sTimer); + } else { + int counter = atoi(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer); + + const float barWidth = SCREEN_SCALE_X(100.f / 2.f); + const float right = SCREEN_SCALE_FROM_RIGHT(37.0f); + const float left = right - barWidth; + + const float barHeight = SCREEN_SCALE_Y(11.0f); + const float top = SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f) + SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i); + const float bottom = top + barHeight; + + // shadow + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(6.0f), top + SCREEN_SCALE_Y(2.0f), right + SCREEN_SCALE_X(6.0f), bottom + SCREEN_SCALE_Y(2.0f)), CRGBA(0, 0, 0, 255)); + + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, right + SCREEN_SCALE_X(4.0f), bottom), CRGBA(27, 89, 130, 255)); + CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, left + SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_X(4.0f), bottom), CRGBA(97, 194, 247, 255)); + } + + if (CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText[0]) { + CFont::SetPropOn(); + CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); + CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetColor(COUNTER_COLOR); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText)); + } + // unused/leftover color. I wonder what was it for + CFont::SetColor(CRGBA(244, 225, 91, 255)); } } } } -#undef TIMER_RIGHT_OFFSET - - /* - DrawPager - */ - if (!m_PagerMessage[0] && PagerOn == 1) { - PagerSoundPlayed = false; - PagerOn = 2; - } - if (m_PagerMessage[0] || PagerOn == 2) { - if (!PagerOn) { - PagerOn = 1; - PagerXOffset = 150.0f; - } - if (PagerOn == 1) { - if (PagerXOffset > 0.0f) { - float fStep = PagerXOffset * 0.1f; - if (fStep > 10.0f) - fStep = 10.0f; - PagerXOffset -= fStep * CTimer::GetTimeStep(); - } - if (!PagerSoundPlayed) { - DMAudio.PlayFrontEndSound(SOUND_PAGER, 0); - PagerSoundPlayed = 1; - } - } - else if (PagerOn == 2) { - float fStep = PagerXOffset * 0.1f; - if (fStep < 2.0f) - fStep = 2.0f; - PagerXOffset += fStep; - if (PagerXOffset > 150.0f) { - PagerXOffset = 150.0f; - PagerOn = 0; - } - } - - Sprites[HUD_PAGER].Draw(CRect(SCREEN_SCALE_X(26.0f - PagerXOffset), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_X(160.0 + 26.0f - PagerXOffset), SCREEN_SCALE_Y(80.0f + 27.0f)), CRGBA(255, 255, 255, 255)); - - CFont::SetBackgroundOff(); - CFont::SetScale(SCREEN_SCALE_X(0.84f), SCREEN_SCALE_Y(1.0f)); - CFont::SetColor(PAGER_COLOR); - CFont::SetRightJustifyOff(); - CFont::SetBackgroundOff(); - CFont::SetCentreOff(); - CFont::SetJustifyOff(); - CFont::SetPropOff(); - CFont::SetFontStyle(FONT_STANDARD); - CFont::PrintString(SCREEN_SCALE_X(52.0f - PagerXOffset), SCREEN_SCALE_Y(54.0f), m_PagerMessage); - } /* DrawRadar @@ -1126,14 +1187,14 @@ void CHud::Draw() */ if (m_HelpMessage[0]) { - if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, 256)) { + if (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, HELP_MSG_LENGTH)) { 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; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH); + m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; if (TheCamera.m_ScreenReductionPercentage == 0.0f) DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); @@ -1148,7 +1209,7 @@ void CHud::Draw() default: break; } - CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH); } float fAlpha = 225.0f; @@ -1158,7 +1219,9 @@ void CHud::Draw() case 1: fAlpha = 225.0f; m_HelpMessageFadeTimer = 600; - if (m_HelpMessageTimer > m_fHelpMessageTime * 1000.0f || m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { + if (!m_HelpMessageDisplayForever && m_HelpMessageTimer > m_HelpMessageDisplayTime * 1000.0f || + m_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) { + m_HelpMessageFadeTimer = 600; m_HelpMessageState = 3; } @@ -1187,7 +1250,7 @@ void CHud::Draw() if (m_HelpMessageFadeTimer < 0) { m_HelpMessageState = 2; m_HelpMessageFadeTimer = 0; - CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, 256); + CMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, HELP_MSG_LENGTH); } fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f; break; @@ -1212,7 +1275,7 @@ void CHud::Draw() CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); CFont::DrawFonts(); - // CFont::SetColor(CRGBA(175, 175, 175, 255)); + CFont::SetColor(CRGBA(175, 175, 175, 255)); CFont::SetJustifyOff(); #ifdef MORE_LANGUAGES if (CFont::IsJapanese()) @@ -1224,9 +1287,9 @@ void CHud::Draw() 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::SetColor(CRGBA(175, 175, 175, 255)); + CFont::PrintString(SCREEN_SCALE_X(34.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), m_HelpMessageToPrint); CFont::SetAlphaFade(255.0f); CFont::SetWrapx(SCREEN_WIDTH); } @@ -1311,19 +1374,19 @@ void CHud::Draw() CFont::SetRightJustifyOn(); CFont::SetFontStyle(FONT_HEADING); - CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f - 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); + CFont::SetDropShadowPosition(2); + CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); CFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, BigMessageAlpha[2])); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(82.0f), m_BigMessage[2]); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(90.0f), m_BigMessage[2]); } else { 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; + if (m_VehicleState != 0) // Hide vehicle name if wasted/busted text is displaying + m_VehicleState = 0; + if (m_ZoneState != 0) + m_ZoneState = 0; } } else { @@ -1332,7 +1395,6 @@ void CHud::Draw() } } -// --MIAMI: Done void CHud::DrawAfterFade() { RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); @@ -1522,7 +1584,7 @@ void CHud::DrawAfterFade() BigMessageInUse[1] = 120.0f; BigMessageAlpha[1] -= CTimer::GetTimeStepInMilliseconds(); } - if (BigMessageAlpha[1] <= 0) { + if (BigMessageAlpha[1] <= 0.0f) { m_BigMessage[1][0] = 0; BigMessageInUse[1] = 0.0f; BigMessageAlpha[1] = 0.0f; @@ -1558,12 +1620,11 @@ void CHud::DrawAfterFade() void CHud::GetRidOfAllHudMessages() { - m_ZoneState = 0; - m_pLastZoneName = nil; m_ZoneNameTimer = 0; m_pZoneName = nil; + m_ZoneState = 0; - for (int i = 0; i < 256; i++) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { m_HelpMessage[i] = 0; m_LastHelpMessage[i] = 0; m_HelpMessageToPrint[i] = 0; @@ -1573,15 +1634,15 @@ void CHud::GetRidOfAllHudMessages() m_HelpMessageFadeTimer = 0; m_HelpMessageState = 0; m_HelpMessageQuick = 0; - m_fHelpMessageTime = 1.0f; + m_HelpMessageDisplayForever = false; + m_HelpMessageDisplayTime = 1.0f; m_VehicleName = nil; - m_pLastVehicleName = nil; m_pVehicleNameToPrint = nil; m_VehicleNameTimer = 0; m_VehicleFadeTimer = 0; m_VehicleState = 0; - for (int i = 0; i < 256; i++) + for (int i = 0; i < ARRAY_SIZE(m_Message); i++) m_Message[i] = 0; for (int i = 0; i < 6; i++) { @@ -1631,21 +1692,34 @@ void CHud::Initialise() Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); } + m_pLastZoneName = nil; GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; if (gpSniperSightTex == nil) - gpSniperSightTex = RwTextureRead("sitesniper", nil); + gpSniperSightTex = RwTextureRead("sitesniper", nil); // unused if (gpRocketSightTex == nil) gpRocketSightTex = RwTextureRead("siterocket", nil); - - m_DrawClock = 1; - CounterOnLastFrame = false; + if (gpLaserSightTex == nil) + gpLaserSightTex = RwTextureRead("sitelaser", nil); // unused + if (gpLaserDotTex == nil) + gpLaserDotTex = RwTextureRead("laserdot", "laserdotm"); + if (gpViewFinderTex == nil) + gpViewFinderTex = RwTextureRead("viewfinder_128", "viewfinder_128m"); // unused + + m_ClockState = 1; + CounterOnLastFrame[0] = false; + CounterOnLastFrame[1] = false; + CounterOnLastFrame[2] = false; + m_ItemToFlash = ITEM_NONE; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; + CounterFlashTimer[0] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; @@ -1676,7 +1750,9 @@ void CHud::Initialise() m_HideRadar = false; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; m_LastWanted = 0; + m_LastWeapon = 0; CTxdStore::PopCurrentTxd(); } @@ -1685,16 +1761,22 @@ void CHud::ReInitialise() { m_Wants_To_Draw_Hud = true; m_Wants_To_Draw_3dMarkers = true; + m_pLastZoneName = nil; GetRidOfAllHudMessages(); + m_pLastVehicleName = nil; - CounterOnLastFrame = false; + CounterOnLastFrame[0] = false; + CounterOnLastFrame[1] = false; + CounterOnLastFrame[2] = false; m_ItemToFlash = ITEM_NONE; - m_DrawClock = 1; + m_ClockState = 1; OddJob2Timer = 0; OddJob2OffTimer = 0.0f; OddJob2On = 0; OddJob2XOffset = 0.0f; - CounterFlashTimer = 0; + CounterFlashTimer[0] = 0; + CounterFlashTimer[1] = 0; + CounterFlashTimer[2] = 0; TimerOnLastFrame = false; TimerFlashTimer = 0; SpriteBrightness = 0; @@ -1725,15 +1807,20 @@ void CHud::ReInitialise() { m_HideRadar = false; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; + m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss; m_LastWanted = 0; + m_LastWeapon = 0; } wchar LastBigMessage[6][128]; -void CHud::SetBigMessage(wchar *message, int16 style) +void CHud::SetBigMessage(wchar *message, uint16 style) { int i = 0; + if (BigMessageInUse[style] != 0.0f) + return; + if (style == 5) { for (i = 0; i < 128; i++) { if (message[i] == 0) @@ -1758,18 +1845,42 @@ void CHud::SetBigMessage(wchar *message, int16 style) m_BigMessage[style][i] = 0; } -void CHud::SetHelpMessage(wchar *message, bool quick) +void CHud::SetHelpMessage(wchar *message, bool quick, bool displayForever) { if (!CReplay::IsPlayingBack()) { - CMessages::WideStringCopy(m_HelpMessage, message, 256); + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_HelpMessage[i] = 0; + } + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_LastHelpMessage[i] = 0; + } + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_HelpMessageToPrint[i] = 0; + } + + CMessages::WideStringCopy(m_HelpMessage, message, HELP_MSG_LENGTH); CMessages::InsertPlayerControlKeysInString(m_HelpMessage); + if (m_HelpMessageState == 0 || !CMessages::WideStringCompare(m_HelpMessage, m_HelpMessageToPrint, HELP_MSG_LENGTH)) { + for (int i = 0; i < HELP_MSG_LENGTH; i++) { + m_LastHelpMessage[i] = 0; + } - for (int i = 0; i < 256; i++) { - m_LastHelpMessage[i] = 0; + if (!message) { + m_HelpMessage[0] = 0; + m_HelpMessageToPrint[0] = 0; + } + if (!displayForever) { + m_HelpMessageState = displayForever; + } else { + m_HelpMessageState = 1; + CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH); + CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH); + } + + m_HelpMessageQuick = quick; + m_HelpMessageDisplayForever = displayForever; } - m_HelpMessageState = 0; - m_HelpMessageQuick = quick; } } @@ -1778,11 +1889,10 @@ bool CHud::IsHelpMessageBeingDisplayed(void) return m_HelpMessageState != 0; } - void CHud::SetMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_Message); i++) { if (message[i] == 0) break; @@ -1794,7 +1904,7 @@ void CHud::SetMessage(wchar *message) void CHud::SetPagerMessage(wchar *message) { int i = 0; - for (i = 0; i < 256; i++) { + for (i = 0; i < ARRAY_SIZE(m_PagerMessage); i++) { if (message[i] == 0) break; @@ -1825,6 +1935,15 @@ void CHud::Shutdown() RwTextureDestroy(gpRocketSightTex); gpRocketSightTex = nil; + RwTextureDestroy(gpLaserSightTex); + gpLaserSightTex = nil; + + RwTextureDestroy(gpLaserDotTex); + gpLaserDotTex = nil; + + RwTextureDestroy(gpViewFinderTex); + gpViewFinderTex = nil; + int HudTXD = CTxdStore::FindTxdSlot("hud"); CTxdStore::RemoveTxdSlot(HudTXD); } diff --git a/src/render/Hud.h b/src/render/Hud.h index f4c0d8c4..a4b9609a 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -1,6 +1,11 @@ #pragma once #include "Sprite2d.h" +#define HELP_MSG_LENGTH 256 + +#define HUD_TEXT_SCALE_X 0.7f +#define HUD_TEXT_SCALE_Y 1.25f + enum eItems { ITEM_NONE = -1, @@ -31,41 +36,29 @@ enum eFadeOperation enum eSprites { HUD_FIST, - HUD_BAT, - HUD_PISTOL, - HUD_UZI, - HUD_SHOTGUN, - HUD_AK47, - HUD_M16, - HUD_SNIPER, - HUD_ROCKET, - HUD_FLAME, - HUD_MOLOTOV, - HUD_GRENADE, - HUD_DETONATOR, - HUD_RADARDISC = 15, - HUD_PAGER = 16, - HUD_SITESNIPER = 20, + HUD_SITEROCKET = 41, + HUD_RADARDISC = 50, + HUD_SITESNIPER = 63, HUD_SITEM16, - HUD_SITEROCKET, - NUM_HUD_SPRITES, + HUD_SITELASER, + HUD_LASERDOT, + HUD_VIEWFINDER, + HUD_BLEEDER, + NUM_HUD_SPRITES = 69, }; -#define HUD_TEXT_SCALE_X 0.7f -#define HUD_TEXT_SCALE_Y 1.25f - class CHud { public: static CSprite2d Sprites[NUM_HUD_SPRITES]; - static wchar m_HelpMessage[256]; - static wchar m_LastHelpMessage[256]; + static wchar m_HelpMessage[HELP_MSG_LENGTH]; + static wchar m_LastHelpMessage[HELP_MSG_LENGTH]; static uint32 m_HelpMessageState; static uint32 m_HelpMessageTimer; static int32 m_HelpMessageFadeTimer; - static wchar m_HelpMessageToPrint[256]; - static float &m_HelpMessageDisplayTime; - static float m_fHelpMessageTime; + static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH]; + static float m_HelpMessageDisplayTime; + static bool m_HelpMessageDisplayForever; static bool m_HelpMessageQuick; static uint32 m_ZoneState; static int32 m_ZoneFadeTimer; @@ -86,16 +79,16 @@ public: static wchar m_BigMessage[6][128]; static int16 m_ItemToFlash; static bool m_HideRadar; - static int32 m_DrawClock; + static int32 m_ClockState; // These aren't really in CHud static float BigMessageInUse[6]; static float BigMessageAlpha[6]; static float BigMessageX[6]; static float OddJob2OffTimer; - static bool CounterOnLastFrame; + static bool CounterOnLastFrame[NUMONSCREENCOUNTERS]; static float OddJob2XOffset; - static uint16 CounterFlashTimer; + static uint16 CounterFlashTimer[NUMONSCREENCOUNTERS]; static uint16 OddJob2Timer; static bool TimerOnLastFrame; static int16 OddJob2On; @@ -121,6 +114,8 @@ public: static uint32 m_LastDisplayScore; static uint32 m_LastWanted; + static uint32 m_LastWeapon; + static uint32 m_LastTimeEnergyLost; public: static void Draw(); @@ -131,8 +126,8 @@ public: #endif static void Initialise(); static void ReInitialise(); - static void SetBigMessage(wchar *message, int16 style); - static void SetHelpMessage(wchar *message, bool quick); + static void SetBigMessage(wchar *message, uint16 style); + static void SetHelpMessage(wchar *message, bool quick, bool displayForever = false); static bool IsHelpMessageBeingDisplayed(void); static void SetMessage(wchar *message); static void SetPagerMessage(wchar *message); diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp index 2b34db37..bd2b9a68 100644 --- a/src/render/WaterCannon.cpp +++ b/src/render/WaterCannon.cpp @@ -77,9 +77,13 @@ void CWaterCannon::Update_OncePerFrame(int16 index) } } - int32 extinguishingPoint = CGeneral::GetRandomNumber() & (NUM_SEGMENTPOINTS - 1); - if ( m_abUsed[extinguishingPoint] ) - gFireManager.ExtinguishPoint(m_avecPos[extinguishingPoint], 3.0f); + for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ ) + { + if ( m_abUsed[i] && gFireManager.ExtinguishPointWithWater(m_avecPos[i], 4.0f) ) + { + break; + } + } if ( ((index + CTimer::GetFrameCounter()) & 3) == 0 ) PushPeds(); diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index b98b8243..18eecd95 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -11,6 +11,7 @@ #include "Clock.h" #include "Date.h" #include "FileMgr.h" +#include "Font.h" #include "Frontend.h" #include "GameLogic.h" #include "Gangs.h" diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 6449d586..dd0926cf 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -3,6 +3,7 @@ #include "crossplatform.h" #include "FileMgr.h" +#include "Font.h" #ifdef MORE_LANGUAGES #include "Game.h" #endif diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 6188992d..452ad9fa 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -84,6 +84,16 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { } #endif +// Because wchar length differs between platforms. +wchar* +AllocUnicode(const char* src) +{ + wchar *dst = (wchar*)malloc(strlen(src)*2 + 2); + wchar *i = dst; + while((*i++ = (unsigned char)*src++) != '\0'); + return dst; +} + // Funcs/features from Windows that we need on other platforms #ifndef _WIN32 char *strupr(char *s) { diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 69600385..1635781b 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -67,6 +67,10 @@ void CapturePad(RwInt32 padID); void joysChangeCB(int jid, int event); #endif +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +extern char gSelectedJoystickName[128]; +#endif + enum eGameState { GS_START_UP = 0, diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 0f520cad..08e5c021 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -41,7 +41,6 @@ #include "AnimViewer.h" #include "Font.h" - #define MAX_SUBSYSTEMS (16) @@ -92,6 +91,11 @@ long _dwOperatingSystemVersion; #include <signal.h> #include <errno.h> #endif + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +char gSelectedJoystickName[128] = ""; +#endif + /* ***************************************************************************** */ @@ -429,6 +433,10 @@ psInitialize(void) _dwOperatingSystemVersion = OS_WIN95; } } +#else + _dwOperatingSystemVersion = OS_WINXP; // To fool other classes +#endif + #ifndef PS2_MENU @@ -438,6 +446,8 @@ psInitialize(void) #endif + +#ifdef _WIN32 MEMORYSTATUS memstats; GlobalMemoryStatus(&memstats); @@ -445,17 +455,22 @@ psInitialize(void) debug("Physical memory size %u\n", memstats.dwTotalPhys); debug("Available physical memory %u\n", memstats.dwAvailPhys); +#elif defined (__APPLE__) + uint64_t size = 0; + uint64_t page_size = 0; + size_t uint64_len = sizeof(uint64_t); + size_t ull_len = sizeof(unsigned long long); + sysctl((int[]){CTL_HW, HW_PAGESIZE}, 2, &page_size, &ull_len, NULL, 0); + sysctl((int[]){CTL_HW, HW_MEMSIZE}, 2, &size, &uint64_len, NULL, 0); + vm_statistics_data_t vm_stat; + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &count); + _dwMemAvailPhys = (uint64_t)(vm_stat.free_count * page_size); + debug("Physical memory size %llu\n", _dwMemAvailPhys); + debug("Available physical memory %llu\n", size); #else - -#ifndef PS2_MENU - -#ifdef GTA3_1_1_PATCH - FrontEndMenuManager.LoadSettings(); -#endif - -#endif #ifndef __APPLE__ - struct sysinfo systemInfo; + struct sysinfo systemInfo; sysinfo(&systemInfo); _dwMemAvailPhys = systemInfo.freeram; debug("Physical memory size %u\n", systemInfo.totalram); @@ -476,7 +491,8 @@ psInitialize(void) #endif _dwOperatingSystemVersion = OS_WINXP; // To fool other classes #endif - TheText.Unload(); + + TheText.Unload(); return TRUE; } @@ -843,35 +859,26 @@ void joysChangeCB(int jid, int event); bool IsThisJoystickBlacklisted(int i) { +#ifndef DONT_TRUST_RECOGNIZED_JOYSTICKS + return false; +#else if (glfwJoystickIsGamepad(i)) return false; const char* joyname = glfwGetJoystickName(i); - // this is just a keyboard and mouse - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 Consumer Control - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 System Control - if (strstr(joyname, "2.4GHz Transceiver")) - return true; - // COMPANY USB Device System Control - // COMPANY USB Device Consumer Control - if (strstr(joyname, "COMPANY USB")) - return true; - // i.e. Synaptics TM2438-005 - if (strstr(joyname, "Synaptics ")) - return true; - // i.e. ELAN Touchscreen - if (strstr(joyname, "ELAN ")) - return true; - // i.e. Primax Electronics, Ltd HP Wireless Keyboard Mouse Kit Consumer Control - if (strstr(joyname, "Keyboard")) - return true; + if (strncmp(joyname, gSelectedJoystickName, strlen(gSelectedJoystickName)) == 0) + return false; - return false; + return true; +#endif } void _InputInitialiseJoys() { + PSGLOBAL(joy1id) = -1; + PSGLOBAL(joy2id) = -1; + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (PSGLOBAL(joy1id) == -1) @@ -886,6 +893,9 @@ void _InputInitialiseJoys() if (PSGLOBAL(joy1id) != -1) { int count; glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id))); +#endif ControlsManager.InitDefaultControlConfigJoyPad(count); } } @@ -2104,18 +2114,19 @@ void CapturePad(RwInt32 padID) void joysChangeCB(int jid, int event) { - if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) - { - if (PSGLOBAL(joy1id) == -1) + if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { + if (PSGLOBAL(joy1id) == -1) { PSGLOBAL(joy1id) = jid; - else if (PSGLOBAL(joy2id) == -1) +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + strcpy(gSelectedJoystickName, glfwGetJoystickName(jid)); +#endif + } else if (PSGLOBAL(joy2id) == -1) PSGLOBAL(joy2id) = jid; - } - else if (event == GLFW_DISCONNECTED) - { - if (PSGLOBAL(joy1id) == jid) + + } else if (event == GLFW_DISCONNECTED) { + if (PSGLOBAL(joy1id) == jid) { PSGLOBAL(joy1id) = -1; - else if (PSGLOBAL(joy2id) == jid) + } else if (PSGLOBAL(joy2id) == jid) PSGLOBAL(joy2id) = -1; } } diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index b98d5710..1d1037af 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -3414,4 +3414,4 @@ int strncasecmp(const char *str1, const char *str2, size_t len) return _strnicmp(str1, str2, len); } #endif -#endif
\ No newline at end of file +#endif diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 64f303eb..5adc576a 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -9,11 +9,12 @@ #include "Text.h" #include "Timer.h" +//--MIAMI: file done + static wchar WideErrorString[25]; CText TheText; -//--MIAMI: DONE CText::CText(void) { encoding = 'e'; @@ -23,7 +24,6 @@ CText::CText(void) memset(WideErrorString, 0, sizeof(WideErrorString)); } -//--MIAMI: DONE void CText::Load(void) { @@ -95,7 +95,6 @@ CText::Load(void) CFileMgr::SetDir(""); } -//--MIAMI: DONE void CText::Unload(void) { @@ -108,7 +107,6 @@ CText::Unload(void) memset(szMissionTableName, 0, sizeof(szMissionTableName)); } -//--MIAMI: DONE wchar* CText::Get(const char *key) { @@ -158,7 +156,6 @@ wchar FrenchUpperCaseTable[128] = { 253, 254, 255 }; -//--MIAMI: TODO (check tables) wchar CText::GetUpperCase(wchar c) { @@ -190,7 +187,6 @@ CText::GetUpperCase(wchar c) return c; } -//--MIAMI: DONE void CText::UpperCase(wchar *s) { @@ -200,27 +196,33 @@ CText::UpperCase(wchar *s) } } -//--MIAMI: DONE void CText::GetNameOfLoadedMissionText(char *outName) { strcpy(outName, szMissionTableName); } -//--MIAMI: DONE void CText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset) { +#if DUMB + char *_buf = (char*)buf; + for (int i = 0; i < sizeof(ChunkHeader); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } +#else // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader)); *offset += sizeof(ChunkHeader); +#endif } -//--MIAMI: DONE void CText::LoadMissionText(char *MissionTableName) { char filename[32]; + CMessages::ClearAllMessagesDisplayedByGame(); mission_keyArray.Unload(); mission_data.Unload(); @@ -306,7 +308,6 @@ CText::LoadMissionText(char *MissionTableName) } -//--MIAMI: DONE void CKeyArray::Load(size_t length, int file, size_t* offset) { @@ -318,14 +319,16 @@ CKeyArray::Load(size_t length, int file, size_t* offset) rawbytes = (char*)entries; #if DUMB - for (uint32 i = 0; i < length; i++) + for (uint32 i = 0; i < length; i++) { CFileMgr::Read(file, &rawbytes[i], 1); + (*offset)++; + } #else CFileMgr::Read(file, rawbytes, length); + *offset += length; #endif } -//--MIAMI: DONE void CKeyArray::Unload(void) { @@ -334,7 +337,6 @@ CKeyArray::Unload(void) numEntries = 0; } -//--MIAMI: DONE void CKeyArray::Update(wchar *chars) { @@ -345,7 +347,6 @@ CKeyArray::Update(wchar *chars) #endif } -//--MIAMI: DONE CKeyEntry* CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) { @@ -366,7 +367,6 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi return nil; } -//--MIAMI: DONE wchar* #ifdef FIX_BUGS CKeyArray::Search(const char *key, wchar *data, uint8 *result) @@ -402,7 +402,6 @@ CKeyArray::Search(const char *key, uint8 *result) return WideErrorString; } -//--MIAMI: DONE void CData::Load(size_t length, int file, size_t * offset) { @@ -414,14 +413,16 @@ CData::Load(size_t length, int file, size_t * offset) rawbytes = (char*)chars; #if DUMB - for(uint32 i = 0; i < length; i++) + for(uint32 i = 0; i < length; i++){ CFileMgr::Read(file, &rawbytes[i], 1); + (*offset)++; + } #else CFileMgr::Read(file, rawbytes, length); + *offset += length; #endif } -//--MIAMI: DONE void CData::Unload(void) { @@ -430,22 +431,31 @@ CData::Unload(void) numChars = 0; } -//--MIAMI: DONE void CMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int) { +#if DUMB + size_t num_of_entries = table_size / sizeof(CMissionTextOffsets::Entry); + for (size_t mi = 0; mi < num_of_entries; mi++) { + for (uint32 i = 0; i < sizeof(data[mi].szMissionName); i++) { + CFileMgr::Read(file, &data[i].szMissionName[i], 1); + (*offset)++; + } + char* _buf = (char*)&data[mi].offset; + for (uint32 i = 0; i < sizeof(data[mi].offset); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } + } + size = (uint16)num_of_entries; +#else // not exact VC code but smaller and better :P // 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; -} - -void -AsciiToUnicode(const char *src, wchar *dst) -{ - while((*dst++ = (unsigned char)*src++) != '\0'); +#endif } char* @@ -460,8 +470,29 @@ UnicodeToAscii(wchar *src) if(*src < 128) #endif aStr[len] = *src; - else - aStr[len] = '#'; + // convert to CP1252 + else if(*src <= 131) + aStr[len] = *src + 64; + else if (*src <= 141) + aStr[len] = *src + 66; + else if (*src <= 145) + aStr[len] = *src + 68; + else if (*src <= 149) + aStr[len] = *src + 71; + else if (*src <= 154) + aStr[len] = *src + 73; + else if (*src <= 164) + aStr[len] = *src + 75; + else if (*src <= 168) + aStr[len] = *src + 77; + else if (*src <= 204) + aStr[len] = *src + 80; + else switch (*src) { + case 205: aStr[len] = 209; break; + case 206: aStr[len] = 241; break; + case 207: aStr[len] = 191; break; + default: aStr[len] = '#'; break; + } aStr[len] = '\0'; return aStr; } @@ -471,7 +502,7 @@ UnicodeToAsciiForSaveLoad(wchar *src) { static char aStr[256]; int len; - for(len = 0; *src != '\0' && len < 256-1; len++, src++) + for(len = 0; *src != '\0' && len < 256; len++, src++) if(*src < 256) aStr[len] = *src; else @@ -485,7 +516,7 @@ UnicodeToAsciiForMemoryCard(wchar *src) { static char aStr[256]; int len; - for(len = 0; *src != '\0' && len < 256-1; len++, src++) + for(len = 0; *src != '\0' && len < 256; len++, src++) if(*src < 256) aStr[len] = *src; else @@ -495,41 +526,7 @@ UnicodeToAsciiForMemoryCard(wchar *src) } void -UnicodeMakeUpperCase(wchar *dst, wchar *src) //idk what to do with it, seems to be incorrect implementation by R* -{ - while (*src != '\0') { - if (*src < 'a' || *src > 'z') - *dst = *src; - else - *dst = *src - 32; - dst++; - src++; - } - *dst = '\0'; -} - -void -UnicodeStrcpy(wchar *dst, const wchar *src) -{ - while((*dst++ = *src++) != '\0'); -} - -void -UnicodeStrcat(wchar *dst, wchar *append) -{ - UnicodeStrcpy(&dst[UnicodeStrlen(dst)], append); -} - -int -UnicodeStrlen(const wchar *str) -{ - int len; - for(len = 0; *str != '\0'; len++, str++); - return len; -} - -void TextCopy(wchar *dst, const wchar *src) { while((*dst++ = *src++) != '\0'); -}
\ No newline at end of file +} diff --git a/src/text/Text.h b/src/text/Text.h index 0bad9a83..33dc313e 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -1,14 +1,9 @@ #pragma once -void AsciiToUnicode(const char *src, wchar *dst); char *UnicodeToAscii(wchar *src); char *UnicodeToAsciiForSaveLoad(wchar *src); char *UnicodeToAsciiForMemoryCard(wchar *src); -void UnicodeStrcpy(wchar *dst, const wchar *src); -void UnicodeStrcat(wchar *dst, wchar *append); -int UnicodeStrlen(const wchar *str); void TextCopy(wchar *dst, const wchar *src); -void UnicodeMakeUpperCase(wchar *dst, wchar *src); struct CKeyEntry { diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 6e86dbe4..994f3c99 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1303,7 +1303,7 @@ CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage } } #ifdef FIX_BUGS // removing dumb case when shooting police car in player's own garage gives wanted level - if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && !bHasBeenOwnedByPlayer) + if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && damagedBy != nil && !bHasBeenOwnedByPlayer) #else if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed()) #endif |