1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-12-23 19:50:00 +00:00

Merge branch 'miami' of https://github.com/GTAmodding/re3 into miami

This commit is contained in:
Roman Masanin 2020-10-12 13:42:57 +03:00
commit 417646819c
67 changed files with 2558 additions and 1039 deletions

View file

@ -1,15 +1,44 @@
language: cpp language: cpp
os: linux
dist: focal dist: focal
matrix: os: linux
jobs:
include: include:
- env: TARGET=release_linux-amd64-librw_gl3_glfw-oal - env: TARGET=release_linux-amd64-librw_gl3_glfw-oal
os: linux
- env: TARGET=debug_linux-amd64-librw_gl3_glfw-oal - env: TARGET=debug_linux-amd64-librw_gl3_glfw-oal
os: linux
- env: TARGET=release_macosx-amd64-librw_gl3_glfw-oal PREMAKE5=premake-5.0.0-alpha15
compiler: clang
os: osx
osx_image: xcode12u
- env: TARGET=debug_macosx-amd64-librw_gl3_glfw-oal PREMAKE5=premake-5.0.0-alpha15
compiler: clang
os: osx
osx_image: xcode12u
addons:
apt:
update: true
packages:
- linux-libc-dev
- libopenal-dev
- libglew-dev
- libglfw3-dev
- libsndfile1-dev
- libmpg123-dev
- gcc-8-multilib
- g++-8-multilib
homebrew:
packages:
- libsndfile
- mpg123
- glew
- glfw
- openal-soft
script: script:
- sudo apt-get update
- sudo apt-get -y install linux-libc-dev libopenal-dev libglew-dev libglfw3-dev libsndfile1-dev libmpg123-dev gcc-8-multilib g++-8-multilib
- mkdir -p "$TRAVIS_BUILD_DIR/build" - mkdir -p "$TRAVIS_BUILD_DIR/build"
- cd "$TRAVIS_BUILD_DIR" - cd "$TRAVIS_BUILD_DIR"
- ./premake5Linux --with-librw gmake2 - if [ "$TRAVIS_OS_NAME" = linux ]; then ./premake5Linux --with-librw gmake2; fi
- if [ "$TRAVIS_OS_NAME" = osx ]; then curl -L -o "${PREMAKE5}.zip" "https://github.com/premake/premake-core/releases/download/v5.0.0-alpha15/${PREMAKE5}-src.zip" && unzip -q "${PREMAKE5}.zip" && cd "$PREMAKE5" && make -f Bootstrap.mak osx && cd .. && "./${PREMAKE5}/bin/release/premake5" --with-librw gmake2; fi
- cd build - cd build
- CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1 - if [ "$TRAVIS_OS_NAME" = linux ]; then env CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1; fi
- if [ "$TRAVIS_OS_NAME" = osx ]; then make config=$TARGET -j4 verbose=1; fi

32
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -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
}

89
.vscode/launch.json vendored Normal file
View file

@ -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"
}

30
.vscode/settings.json vendored Normal file
View file

@ -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
}

95
.vscode/tasks.json vendored Normal file
View file

@ -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"
}

107
CODING_STYLE.md Normal file
View file

@ -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

111
README.md
View file

@ -21,8 +21,7 @@ such that we have a working game at all times.
## Preparing the environment for building ## Preparing the environment for building
- Clone the repo. - Clone the repo using the argument `--recursive`.
- Run `git submodule init` and `git submodule update`.
- Point GTA_III_RE_DIR environment variable to GTA3 root folder. - Point GTA_III_RE_DIR environment variable to GTA3 root folder.
- Run premake - Run premake
- On Windows: one of the `premake-vsXXXX.cmd` variants on root folder - 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. > :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 ## 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) ### Unreversed / incomplete classes (at least the ones we know)
The following classes have only unused or practically unused code left: The following classes have only unused or practically unused code left:
@ -44,110 +44,3 @@ CCullZone - only mobile stuff
CCullZones - 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

View file

@ -85,6 +85,12 @@ workspace "reVC"
"bsd-amd64-librw_gl3_glfw-oal" "bsd-amd64-librw_gl3_glfw-oal"
} }
filter { "system:macosx" }
platforms {
"macosx-arm64-librw_gl3_glfw-oal",
"macosx-amd64-librw_gl3_glfw-oal",
}
filter "configurations:Debug" filter "configurations:Debug"
defines { "DEBUG" } defines { "DEBUG" }
@ -101,6 +107,9 @@ workspace "reVC"
filter { "platforms:bsd*" } filter { "platforms:bsd*" }
system "bsd" system "bsd"
filter { "platforms:macosx*" }
system "macosx"
filter { "platforms:*x86*" } filter { "platforms:*x86*" }
architecture "x86" architecture "x86"
@ -110,6 +119,13 @@ workspace "reVC"
filter { "platforms:*arm*" } filter { "platforms:*arm*" }
architecture "ARM" architecture "ARM"
filter { "platforms:macosx-arm64-*" }
buildoptions { "-target", "arm64-apple-macos11", "-std=gnu++14" }
filter { "platforms:macosx-amd64-*" }
buildoptions { "-target", "x86_64-apple-macos10.12", "-std=gnu++14" }
filter { "platforms:*librw_d3d9*" } filter { "platforms:*librw_d3d9*" }
defines { "RW_D3D9" } defines { "RW_D3D9" }
if(not _OPTIONS["with-librw"]) then if(not _OPTIONS["with-librw"]) then
@ -163,6 +179,13 @@ project "librw"
includedirs { "/usr/local/include" } includedirs { "/usr/local/include" }
libdirs { "/usr/local/lib" } libdirs { "/usr/local/lib" }
filter "platforms:macosx*"
-- Support MacPorts and Homebrew
includedirs { "/opt/local/include" }
includedirs {"/usr/local/include" }
libdirs { "/opt/local/lib" }
libdirs { "/usr/local/lib" }
filter "platforms:*RW34*" filter "platforms:*RW34*"
flags { "ExcludeFromBuild" } flags { "ExcludeFromBuild" }
filter {} filter {}
@ -278,6 +301,11 @@ project "reVC"
filter "platforms:bsd*oal" filter "platforms:bsd*oal"
links { "openal", "mpg123", "sndfile", "pthread" } links { "openal", "mpg123", "sndfile", "pthread" }
filter "platforms:macosx*oal"
links { "openal", "mpg123", "sndfile", "pthread" }
includedirs { "/usr/local/opt/openal-soft/include" }
libdirs { "/usr/local/opt/openal-soft/lib" }
if _OPTIONS["with-opus"] then if _OPTIONS["with-opus"] then
filter {} filter {}
links { "libogg" } links { "libogg" }
@ -330,3 +358,11 @@ project "reVC"
links { "GL", "GLEW", "glfw", "sysinfo" } links { "GL", "GLEW", "glfw", "sysinfo" }
includedirs { "/usr/local/include" } includedirs { "/usr/local/include" }
libdirs { "/usr/local/lib" } libdirs { "/usr/local/lib" }
filter "platforms:macosx*gl3_glfw*"
links { "GLEW", "glfw" }
linkoptions { "-framework OpenGL" }
includedirs { "/opt/local/include" }
includedirs { "/usr/local/include" }
libdirs { "/opt/local/lib" }
libdirs { "/usr/local/lib" }

View file

@ -5,6 +5,7 @@
#include "AudioManager.h" #include "AudioManager.h"
#include "AudioScriptObject.h" #include "AudioScriptObject.h"
#include "sampman.h" #include "sampman.h"
#include "Font.h"
#include "Text.h" #include "Text.h"
#include "crossplatform.h" #include "crossplatform.h"

View file

@ -3075,7 +3075,7 @@ void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle* pVehicle)
void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle)
{ {
pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0; 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); int nodeId = ThePaths.FindNodeClosestToCoorsFavourDirection(pVehicle->GetPosition(), 0, pVehicle->GetForward().x, pVehicle->GetForward().y);
CPathNode* pNode = &ThePaths.m_pathNodes[nodeId]; CPathNode* pNode = &ThePaths.m_pathNodes[nodeId];
int prevNodeId = -1; int prevNodeId = -1;

View file

@ -14,6 +14,9 @@
#include "Text.h" #include "Text.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "GameLogic.h" #include "GameLogic.h"
#ifdef FIX_BUGS
#include "Replay.h"
#endif
#define FRENZY_ANY_PED -1 #define FRENZY_ANY_PED -1
#define FRENZY_ANY_CAR -2 #define FRENZY_ANY_CAR -2
@ -62,6 +65,10 @@ CDarkel::CalcFade(uint32 time, uint32 start, uint32 end)
void void
CDarkel::DrawMessages() CDarkel::DrawMessages()
{ {
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
switch (Status) { switch (Status) {
case KILLFRENZY_ONGOING: case KILLFRENZY_ONGOING:
{ {
@ -167,6 +174,10 @@ CDarkel::ReadStatus()
void void
CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle) CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle)
{ {
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
if (FrenzyOnGoing()) { if (FrenzyOnGoing()) {
int32 model = vehicle->GetModelIndex(); int32 model = vehicle->GetModelIndex();
if (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) { if (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) {
@ -181,6 +192,10 @@ CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle)
void void
CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot) CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot)
{ {
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
if (FrenzyOnGoing() && (weapon == WeaponType if (FrenzyOnGoing() && (weapon == WeaponType
|| weapon == WEAPONTYPE_EXPLOSION || weapon == WEAPONTYPE_EXPLOSION
|| weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI || weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI
@ -206,6 +221,10 @@ CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot)
void void
CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype) CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype)
{ {
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
CStats::PeopleKilledByOthers++; CStats::PeopleKilledByOthers++;
} }
@ -299,6 +318,11 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode
void void
CDarkel::Update() CDarkel::Update()
{ {
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
if (Status != KILLFRENZY_ONGOING) if (Status != KILLFRENZY_ONGOING)
return; return;

View file

@ -1462,7 +1462,7 @@ void CGarage::UpdateCrusherShake(float X, float Y)
} }
// This is dumb but there is no way to avoid goto. What was there originally even? // This is dumb but there is no way to avoid goto. What was there originally even?
static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, int8 nIndex) static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, uint8 nIndex)
{ {
bool bNeedToFindDoorEntities = false; bool bNeedToFindDoorEntities = false;
if (pDoor) { if (pDoor) {

View file

@ -7,29 +7,38 @@
#include "Timer.h" #include "Timer.h"
#include "Script.h" #include "Script.h"
#include "OnscreenTimer.h" #include "OnscreenTimer.h"
#include "Camera.h"
// --MIAMI: file done
void COnscreenTimer::Init() { void COnscreenTimer::Init() {
m_bDisabled = false; m_bDisabled = false;
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
m_sEntries[i].m_nTimerOffset = 0; m_sCounters[i].m_nCounterOffset = 0;
m_sEntries[i].m_nCounterOffset = 0;
for(uint32 j = 0; j < 10; j++) { for(uint32 j = 0; j < ARRAY_SIZE(COnscreenCounterEntry::m_aCounterText); j++) {
m_sEntries[i].m_aTimerText[j] = 0; m_sCounters[i].m_aCounterText[j] = 0;
m_sEntries[i].m_aCounterText[j] = 0;
} }
m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER; m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;
m_sEntries[i].m_bTimerProcessed = false; m_sCounters[i].m_bCounterProcessed = false;
m_sEntries[i].m_bCounterProcessed = false; }
m_sEntries[i].m_bTimerGoingDown = true; for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
m_sClocks[i].m_nClockOffset = 0;
for(uint32 j = 0; j < ARRAY_SIZE(COnscreenTimerEntry::m_aClockText); j++) {
m_sClocks[i].m_aClockText[j] = 0;
}
m_sClocks[i].m_bClockProcessed = false;
m_sClocks[i].m_bClockGoingDown = true;
} }
} }
void COnscreenTimer::Process() { void COnscreenTimer::Process() {
if(!CReplay::IsPlayingBack() && !m_bDisabled) { if(!CReplay::IsPlayingBack() && !m_bDisabled) {
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
m_sEntries[i].Process(); m_sClocks[i].Process();
} }
} }
} }
@ -37,8 +46,19 @@ void COnscreenTimer::Process() {
void COnscreenTimer::ProcessForDisplay() { void COnscreenTimer::ProcessForDisplay() {
if(CHud::m_Wants_To_Draw_Hud) { if(CHud::m_Wants_To_Draw_Hud) {
m_bProcessed = false; m_bProcessed = false;
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
if(m_sEntries[i].ProcessForDisplay()) { 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; m_bProcessed = true;
} }
} }
@ -46,77 +66,81 @@ void COnscreenTimer::ProcessForDisplay() {
} }
void COnscreenTimer::ClearCounter(uint32 offset) { void COnscreenTimer::ClearCounter(uint32 offset) {
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
if(offset == m_sEntries[i].m_nCounterOffset) { if(offset == m_sCounters[i].m_nCounterOffset) {
m_sEntries[i].m_nCounterOffset = 0; m_sCounters[i].m_nCounterOffset = 0;
m_sEntries[i].m_aCounterText[0] = 0; m_sCounters[i].m_aCounterText[0] = 0;
m_sEntries[i].m_nType = COUNTER_DISPLAY_NUMBER; m_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;
m_sEntries[i].m_bCounterProcessed = 0; m_sCounters[i].m_bCounterProcessed = 0;
} }
} }
} }
void COnscreenTimer::ClearClock(uint32 offset) { void COnscreenTimer::ClearClock(uint32 offset) {
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { for(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {
if(offset == m_sEntries[i].m_nTimerOffset) { if(offset == m_sClocks[i].m_nClockOffset) {
m_sEntries[i].m_nTimerOffset = 0; m_sClocks[i].m_nClockOffset = 0;
m_sEntries[i].m_aTimerText[0] = 0; m_sClocks[i].m_aClockText[0] = 0;
m_sEntries[i].m_bTimerProcessed = 0; m_sClocks[i].m_bClockProcessed = 0;
m_sClocks[i].m_bClockGoingDown = true;
} }
} }
} }
void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos) { void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos) {
m_sEntries[pos].m_nCounterOffset = offset; if (m_sCounters[pos].m_aCounterText[0] != '\0')
if (m_sEntries[pos].m_aCounterText[0] != '\0')
return; return;
m_sCounters[pos].m_nCounterOffset = offset;
if(text) { if(text) {
strncpy(m_sEntries[pos].m_aCounterText, text, 10); strncpy(m_sCounters[pos].m_aCounterText, text, ARRAY_SIZE(COnscreenCounterEntry::m_aCounterText));
} else { } 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) { void COnscreenTimer::AddClock(uint32 offset, char* text, bool bGoingDown) {
uint32 i = 0;
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) { // dead code in here
if(m_sEntries[i].m_nTimerOffset == 0) { uint32 i;
for(i = 0; i < NUMONSCREENCLOCKS; i++) {
if(m_sClocks[i].m_nClockOffset == 0) {
break; break;
} }
return; return;
} }
m_sEntries[i].m_nTimerOffset = offset; m_sClocks[i].m_nClockOffset = offset;
m_sEntries[i].m_bTimerGoingDown = bGoingDown; m_sClocks[i].m_bClockGoingDown = bGoingDown;
if(text) { if(text) {
strncpy(m_sEntries[i].m_aTimerText, text, 10); strncpy(m_sClocks[i].m_aClockText, text, ARRAY_SIZE(COnscreenTimerEntry::m_aClockText));
} else { } else {
m_sEntries[i].m_aTimerText[0] = 0; m_sClocks[i].m_aClockText[0] = 0;
} }
} }
void COnscreenTimerEntry::Process() { void COnscreenTimerEntry::Process() {
if(m_nTimerOffset == 0) { if(m_nClockOffset == 0) {
return; return;
} }
int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nTimerOffset); int32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nClockOffset);
int32 oldTime = *timerPtr; int32 oldTime = *timerPtr;
if (m_bTimerGoingDown) { if (m_bClockGoingDown) {
int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds()); int32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds());
*timerPtr = newTime;
if (newTime < 0) { if (newTime < 0) {
*timerPtr = 0; *timerPtr = 0;
m_bTimerProcessed = 0; m_bClockProcessed = 0;
m_nTimerOffset = 0; m_nClockOffset = 0;
m_aTimerText[0] = 0; m_aClockText[0] = 0;
} }
else { else {
*timerPtr = newTime;
int32 oldTimeSeconds = oldTime / 1000; 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); DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000);
} }
} }
@ -125,33 +149,13 @@ void COnscreenTimerEntry::Process() {
*timerPtr = oldTime + int32(CTimer::GetTimeStepInMilliseconds()); *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() { void COnscreenTimerEntry::ProcessForDisplayClock() {
uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nTimerOffset); uint32 time = *CTheScripts::GetPointerToScriptVariable(m_nClockOffset);
sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60, sprintf(m_aClockBuffer, "%02d:%02d", time / 1000 / 60 % 100,
time / 1000 % 60); time / 1000 % 60);
} }
void COnscreenTimerEntry::ProcessForDisplayCounter() { void COnscreenCounterEntry::ProcessForDisplayCounter() {
uint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset); uint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset);
sprintf(m_bCounterBuffer, "%d", counter); sprintf(m_aCounterBuffer, "%d", counter);
} }

View file

@ -9,30 +9,37 @@ enum
class COnscreenTimerEntry class COnscreenTimerEntry
{ {
public: public:
uint32 m_nTimerOffset; uint32 m_nClockOffset;
uint32 m_nCounterOffset; char m_aClockText[10];
char m_aTimerText[10]; char m_aClockBuffer[40];
char m_aCounterText[10]; bool m_bClockProcessed;
uint16 m_nType; bool m_bClockGoingDown;
char m_bCounterBuffer[42];
char m_bTimerBuffer[42];
bool m_bTimerProcessed;
bool m_bTimerGoingDown;
bool m_bCounterProcessed;
void Process(); void Process();
bool ProcessForDisplay();
void ProcessForDisplayClock(); void ProcessForDisplayClock();
};
VALIDATE_SIZE(COnscreenTimerEntry, 0x3C);
class COnscreenCounterEntry
{
public:
uint32 m_nCounterOffset;
char m_aCounterText[10];
uint16 m_nType;
char m_aCounterBuffer[40];
bool m_bCounterProcessed;
void ProcessForDisplayCounter(); void ProcessForDisplayCounter();
}; };
VALIDATE_SIZE(COnscreenTimerEntry, 0x74); VALIDATE_SIZE(COnscreenCounterEntry, 0x3C);
class COnscreenTimer class COnscreenTimer
{ {
public: public:
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES]; COnscreenTimerEntry m_sClocks[NUMONSCREENCLOCKS];
COnscreenCounterEntry m_sCounters[NUMONSCREENCOUNTERS];
bool m_bProcessed; bool m_bProcessed;
bool m_bDisabled; bool m_bDisabled;
@ -47,4 +54,4 @@ public:
void AddClock(uint32 offset, char* text, bool bGoingDown); void AddClock(uint32 offset, char* text, bool bGoingDown);
}; };
VALIDATE_SIZE(COnscreenTimer, 0x78); VALIDATE_SIZE(COnscreenTimer, 0xF4);

View file

@ -51,6 +51,7 @@
#include "Camera.h" #include "Camera.h"
#include "Radar.h" #include "Radar.h"
#include "Fluff.h" #include "Fluff.h"
#include "WaterCreatures.h"
uint8 CReplay::Mode; uint8 CReplay::Mode;
CAddressInReplayBuffer CReplay::Record; CAddressInReplayBuffer CReplay::Record;
@ -1300,7 +1301,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
DMAudio.SetEffectsFadeVol(0); DMAudio.SetEffectsFadeVol(0);
DMAudio.SetMusicFadeVol(0); DMAudio.SetMusicFadeVol(0);
CEscalators::Shutdown(); CEscalators::Shutdown();
// TODO(MIAMI): CWaterCreatures::RemoveAll(); CWaterCreatures::RemoveAll();
int current; int current;
for (current = 0; current < NUM_REPLAYBUFFERS; current++) for (current = 0; current < NUM_REPLAYBUFFERS; current++)
if (BufferStatus[current] == REPLAYBUFFER_RECORD) if (BufferStatus[current] == REPLAYBUFFER_RECORD)

View file

@ -34,11 +34,11 @@ struct CdReadInfo
bool bReading; bool bReading;
int32 nStatus; int32 nStatus;
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
int8 nThreadStatus; // 0: created 1:initalized 2:abort now int8 nThreadStatus; // 0: created 1:priority set up 2:abort now
pthread_t pChannelThread; pthread_t pChannelThread;
sem_t pStartSemaphore; sem_t *pStartSemaphore;
#endif #endif
sem_t pDoneSemaphore; // used for CdStreamSync sem_t *pDoneSemaphore; // used for CdStreamSync
int32 hFile; int32 hFile;
}; };
@ -51,8 +51,8 @@ char *gImgNames[MAX_CDIMAGES];
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
pthread_t _gCdStreamThread; pthread_t _gCdStreamThread;
sem_t gCdStreamSema; // released when we have new thing to read(so channel is set) sem_t *gCdStreamSema; // released when we have new thing to read(so channel is set)
int8 gCdStreamThreadStatus; // 0: created 1:initalized 2:abort now int8 gCdStreamThreadStatus; // 0: created 1:priority set up 2:abort now
Queue gChannelRequestQ; Queue gChannelRequestQ;
bool _gbCdStreamOverlapped; bool _gbCdStreamOverlapped;
#endif #endif
@ -69,40 +69,41 @@ void
CdStreamInitThread(void) CdStreamInitThread(void)
{ {
int status; int status;
char semName[20];
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32)); gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32));
gChannelRequestQ.head = 0; gChannelRequestQ.head = 0;
gChannelRequestQ.tail = 0; gChannelRequestQ.tail = 0;
gChannelRequestQ.size = gNumChannels + 1; gChannelRequestQ.size = gNumChannels + 1;
ASSERT(gChannelRequestQ.items != nil ); ASSERT(gChannelRequestQ.items != nil );
status = sem_init(&gCdStreamSema, 0, 0); gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
#endif
if (status == -1) { if (gCdStreamSema == SEM_FAILED) {
CDTRACE("failed to create stream semaphore"); CDTRACE("failed to create stream semaphore");
ASSERT(0); ASSERT(0);
return; return;
} }
#endif
if ( gNumChannels > 0 ) if ( gNumChannels > 0 )
{ {
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ )
{ {
status = sem_init(&gpReadInfo[i].pDoneSemaphore, 0, 0); sprintf(semName,"/semaphore_done%d",i);
gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 1);
if (status == -1) if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
{ {
CDTRACE("failed to create sync semaphore"); CDTRACE("failed to create sync semaphore");
ASSERT(0); ASSERT(0);
return; return;
} }
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
status = sem_init(&gpReadInfo[i].pStartSemaphore, 0, 0); sprintf(semName,"/semaphore_start%d",i);
gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 1);
if (status == -1) if (gpReadInfo[i].pStartSemaphore == SEM_FAILED)
{ {
CDTRACE("failed to create start semaphore"); CDTRACE("failed to create start semaphore");
ASSERT(0); ASSERT(0);
@ -125,8 +126,8 @@ CdStreamInitThread(void)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
debug("Using one streaming thread for all channels\n"); debug("Using one streaming thread for all channels\n");
status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil);
gCdStreamThreadStatus = 0; gCdStreamThreadStatus = 0;
status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil);
if (status == -1) if (status == -1)
{ {
@ -135,7 +136,7 @@ CdStreamInitThread(void)
return; return;
} }
#else #else
debug("Using seperate streaming threads for each channel\n"); debug("Using separate streaming threads for each channel\n");
#endif #endif
} }
@ -163,7 +164,7 @@ CdStreamInit(int32 numChannels)
debug("Using no buffered loading for streaming\n"); debug("Using no buffered loading for streaming\n");
} }
*/ */
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, fsInfo.f_bsize); void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, (RwUInt32)fsInfo.f_bsize);
ASSERT( pBuffer != nil ); ASSERT( pBuffer != nil );
gNumImages = 0; gNumImages = 0;
@ -205,7 +206,7 @@ GetGTA3ImgSize(void)
return 0; return 0;
} }
ok: ok:
return statbuf.st_size; return (uint32)statbuf.st_size;
} }
void void
@ -214,13 +215,11 @@ CdStreamShutdown(void)
// Destroying semaphores and free(gpReadInfo) will be done at threads // Destroying semaphores and free(gpReadInfo) will be done at threads
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
gCdStreamThreadStatus = 2; gCdStreamThreadStatus = 2;
sem_post(&gCdStreamSema); sem_post(gCdStreamSema);
#endif #else
#ifdef ONE_THREAD_PER_CHANNEL
for ( int32 i = 0; i < gNumChannels; i++ ) { for ( int32 i = 0; i < gNumChannels; i++ ) {
gpReadInfo[i].nThreadStatus = 2; gpReadInfo[i].nThreadStatus = 2;
sem_post(&gpReadInfo[i].pStartSemaphore); sem_post(gpReadInfo[i].pStartSemaphore);
} }
#endif #endif
} }
@ -241,11 +240,17 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
CdReadInfo *pChannel = &gpReadInfo[channel]; CdReadInfo *pChannel = &gpReadInfo[channel];
ASSERT( pChannel != nil ); ASSERT( pChannel != nil );
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) {
if (pChannel->nSectorOffset == _GET_OFFSET(offset) && pChannel->nSectorsToRead >= size)
return STREAM_SUCCESS;
flushStream[channel] = 1;
CdStreamSync(channel);
//return STREAM_NONE;
}
pChannel->hFile = hImage - 1; pChannel->hFile = hImage - 1;
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading )
return STREAM_NONE;
pChannel->nStatus = STREAM_NONE; pChannel->nStatus = STREAM_NONE;
pChannel->nSectorOffset = _GET_OFFSET(offset); pChannel->nSectorOffset = _GET_OFFSET(offset);
pChannel->nSectorsToRead = size; pChannel->nSectorsToRead = size;
@ -254,10 +259,10 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
AddToQueue(&gChannelRequestQ, channel); AddToQueue(&gChannelRequestQ, channel);
if ( sem_post(&gCdStreamSema) != 0 ) if ( sem_post(gCdStreamSema) != 0 )
printf("Signal Sema Error\n"); printf("Signal Sema Error\n");
#else #else
if ( sem_post(&gpReadInfo[channel].pStartSemaphore) != 0 ) if ( sem_post(pChannel->pStartSemaphore) != 0 )
printf("Signal Sema Error\n"); printf("Signal Sema Error\n");
#endif #endif
@ -314,13 +319,18 @@ CdStreamSync(int32 channel)
if (flushStream[channel]) { if (flushStream[channel]) {
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
pChannel->nSectorsToRead = 0; pChannel->nSectorsToRead = 0;
pthread_kill(gpReadInfo[channel].pChannelThread, SIGINT); pthread_kill(pChannel->pChannelThread, SIGUSR1);
#else
if (pChannel->bReading) { if (pChannel->bReading) {
pChannel->bLocked = true;
sem_wait(pChannel->pDoneSemaphore);
}
#else
pChannel->nSectorsToRead = 0; pChannel->nSectorsToRead = 0;
pthread_kill(_gCdStreamThread, SIGINT); if (pChannel->bReading) {
} else { pChannel->bLocked = true;
pChannel->nSectorsToRead = 0; pthread_kill(_gCdStreamThread, SIGUSR1);
sem_wait(pChannel->pDoneSemaphore);
} }
#endif #endif
pChannel->bReading = false; pChannel->bReading = false;
@ -332,7 +342,7 @@ CdStreamSync(int32 channel)
{ {
pChannel->bLocked = true; pChannel->bLocked = true;
sem_wait(&pChannel->pDoneSemaphore); sem_wait(pChannel->pDoneSemaphore);
} }
pChannel->bReading = false; pChannel->bReading = false;
@ -383,38 +393,36 @@ void *CdStreamThread(void *param)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
while (gCdStreamThreadStatus != 2) { while (gCdStreamThreadStatus != 2) {
sem_wait(&gCdStreamSema); sem_wait(gCdStreamSema);
int32 channel = GetFirstInQueue(&gChannelRequestQ); int32 channel = GetFirstInQueue(&gChannelRequestQ);
#else #else
int channel = *((int*)param); int channel = *((int*)param);
while (gpReadInfo[channel].nThreadStatus != 2){ while (gpReadInfo[channel].nThreadStatus != 2){
sem_wait(&gpReadInfo[channel].pStartSemaphore); sem_wait(gpReadInfo[channel].pStartSemaphore);
#endif #endif
ASSERT( channel < gNumChannels );
CdReadInfo *pChannel = &gpReadInfo[channel]; CdReadInfo *pChannel = &gpReadInfo[channel];
ASSERT( pChannel != nil ); ASSERT( pChannel != nil );
#ifdef ONE_THREAD_PER_CHANNEL
if (gpReadInfo[channel].nThreadStatus == 0){
gpReadInfo[channel].nThreadStatus = 1;
#else
if (gCdStreamThreadStatus == 0){
gCdStreamThreadStatus = 1;
#endif
#ifdef __linux__
pid_t tid = syscall(SYS_gettid);
int ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1);
#endif
}
// spurious wakeup or we sent interrupt signal for flushing // spurious wakeup or we sent interrupt signal for flushing
if(pChannel->nSectorsToRead == 0) if(pChannel->nSectorsToRead == 0)
continue; continue;
pChannel->bReading = true; pChannel->bReading = true;
// Not standard POSIX :shrug:
#ifdef __linux__
#ifdef ONE_THREAD_PER_CHANNEL
if (gpReadInfo[channel].nThreadStatus == 0){
gpReadInfo[channel].nThreadStatus = 1;
#else
if (gCdStreamThreadStatus == 0){
gCdStreamThreadStatus = 1;
#endif
pid_t tid = syscall(SYS_gettid);
int ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1);
}
#endif
if ( pChannel->nStatus == STREAM_NONE ) if ( pChannel->nStatus == STREAM_NONE )
{ {
ASSERT(pChannel->hFile >= 0); ASSERT(pChannel->hFile >= 0);
@ -423,7 +431,8 @@ void *CdStreamThread(void *param)
lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET); lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET);
if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) { if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) {
// pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel // pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel
pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_NONE : STREAM_ERROR; // STREAM_WAITING is a little hack to make CStreaming not process this data
pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_WAITING : STREAM_ERROR;
} else { } else {
pChannel->nStatus = STREAM_NONE; pChannel->nStatus = STREAM_NONE;
} }
@ -437,22 +446,33 @@ void *CdStreamThread(void *param)
if ( pChannel->bLocked ) if ( pChannel->bLocked )
{ {
sem_post(&pChannel->pDoneSemaphore); sem_post(pChannel->pDoneSemaphore);
} }
pChannel->bReading = false; pChannel->bReading = false;
} }
char semName[20];
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ )
{ {
sem_destroy(&gpReadInfo[i].pDoneSemaphore); sem_close(gpReadInfo[i].pDoneSemaphore);
sprintf(semName,"/semaphore_done%d",i);
sem_unlink(semName);
} }
sem_destroy(&gCdStreamSema); sem_close(gCdStreamSema);
sem_unlink("/semaphore_cd_stream");
free(gChannelRequestQ.items); free(gChannelRequestQ.items);
#else #else
sem_destroy(&gpReadInfo[channel].pStartSemaphore); sem_close(gpReadInfo[channel].pStartSemaphore);
sem_destroy(&gpReadInfo[channel].pDoneSemaphore); sprintf(semName,"/semaphore_start%d",channel);
sem_unlink(semName);
sem_close(gpReadInfo[channel].pDoneSemaphore);
sprintf(semName,"/semaphore_done%d",channel);
sem_unlink(semName);
#endif #endif
if (gpReadInfo)
free(gpReadInfo); free(gpReadInfo);
gpReadInfo = nil;
pthread_exit(nil); pthread_exit(nil);
} }
@ -502,8 +522,10 @@ CdStreamGetImageName(int32 cd)
void void
CdStreamRemoveImages(void) CdStreamRemoveImages(void)
{ {
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ ) {
flushStream[i] = 1;
CdStreamSync(i); CdStreamSync(i);
}
for ( int32 i = 0; i < gNumImages; i++ ) for ( int32 i = 0; i < gNumImages; i++ )
{ {

View file

@ -1052,7 +1052,11 @@ CFileLoader::Load2dEffect(const char *line)
&effect->attractor.dir.z, &effect->attractor.dir.z,
&probability); &probability);
effect->attractor.type = flags; effect->attractor.type = flags;
#ifdef FIX_BUGS
effect->attractor.probability = clamp(probability, 0, 255);
#else
effect->attractor.probability = probability; effect->attractor.probability = probability;
#endif
break; break;
case EFFECT_PED_ATTRACTOR: case EFFECT_PED_ATTRACTOR:
sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f", sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f",

View file

@ -142,17 +142,17 @@ static size_t
myfread(void *buf, size_t elt, size_t n, int fd) myfread(void *buf, size_t elt, size_t n, int fd)
{ {
if(myfiles[fd].isText){ if(myfiles[fd].isText){
char *p; unsigned char *p;
size_t i; size_t i;
int c; int c;
n *= elt; n *= elt;
p = (char*)buf; p = (unsigned char*)buf;
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
c = myfgetc(fd); c = myfgetc(fd);
if(c == EOF) if(c == EOF)
break; break;
*p++ = c; *p++ = (unsigned char)c;
} }
return i / elt; return i / elt;
} }
@ -163,12 +163,12 @@ static size_t
myfwrite(void *buf, size_t elt, size_t n, int fd) myfwrite(void *buf, size_t elt, size_t n, int fd)
{ {
if(myfiles[fd].isText){ if(myfiles[fd].isText){
char *p; unsigned char *p;
size_t i; size_t i;
int c; int c;
n *= elt; n *= elt;
p = (char*)buf; p = (unsigned char*)buf;
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
c = *p++; c = *p++;
myfputc(c, fd); myfputc(c, fd);

View file

@ -16,6 +16,9 @@
#include "Ped.h" #include "Ped.h"
#include "Fire.h" #include "Fire.h"
#include "GameLogic.h" #include "GameLogic.h"
#include "CarAI.h"
// --MIAMI: file done
CFireManager gFireManager; CFireManager gFireManager;
@ -26,14 +29,13 @@ CFire::CFire()
m_bPropagationFlag = true; m_bPropagationFlag = true;
m_bAudioSet = true; m_bAudioSet = true;
m_vecPos = CVector(0.0f, 0.0f, 0.0f); m_vecPos = CVector(0.0f, 0.0f, 0.0f);
m_pEntity = nil;
m_pSource = nil;
m_nFiremenPuttingOut = 0;
m_nExtinguishTime = 0; m_nExtinguishTime = 0;
m_nStartTime = 0; m_nStartTime = 0;
field_20 = 1; m_pEntity = nil;
m_nNextTimeToAddFlames = 0; m_pSource = nil;
m_fStrength = 0.8f; m_fStrength = 0.8f;
m_fWaterExtinguishCountdown = 1.0f;
m_bExtinguishedWithWater = false;
} }
CFire::~CFire() {} CFire::~CFire() {}
@ -52,6 +54,8 @@ CFire::ProcessFire(void)
CPed *ped = (CPed *)m_pEntity; CPed *ped = (CPed *)m_pEntity;
CVehicle *veh = (CVehicle*)m_pEntity; CVehicle *veh = (CVehicle*)m_pEntity;
m_fWaterExtinguishCountdown = Min(1.0f, 0.002f * CTimer::GetTimeStep() + m_fWaterExtinguishCountdown);
if (m_pEntity) { if (m_pEntity) {
m_vecPos = m_pEntity->GetPosition(); m_vecPos = m_pEntity->GetPosition();
@ -109,7 +113,7 @@ CFire::ProcessFire(void)
gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1); gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1);
} }
if (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) { 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; firePos = m_vecPos;
if (veh && veh->IsVehicle() && veh->IsCar()) { if (veh && veh->IsVehicle() && veh->IsCar()) {
@ -170,11 +174,23 @@ CFire::Extinguish(void)
m_nExtinguishTime = 0; m_nExtinguishTime = 0;
m_bIsOngoing = false; m_bIsOngoing = false;
m_bExtinguishedWithWater = false;
if (m_pEntity) { if (m_pEntity) {
if (m_pEntity->IsPed()) { if (m_pEntity->IsPed()) {
((CPed *)m_pEntity)->RestorePreviousState(); CPed *ped = (CPed*)m_pEntity;
((CPed *)m_pEntity)->m_pFire = nil; 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()) { } else if (m_pEntity->IsVehicle()) {
((CVehicle *)m_pEntity)->m_pCarFire = nil; ((CVehicle *)m_pEntity)->m_pCarFire = nil;
} }
@ -184,7 +200,7 @@ CFire::Extinguish(void)
} }
void void
CFireManager::StartFire(CVector pos, float size, bool propagation) CFireManager::StartFire(CVector pos, float size, uint8 propagation)
{ {
CFire *fire = GetNextFreeFire(); CFire *fire = GetNextFreeFire();
@ -201,11 +217,12 @@ CFireManager::StartFire(CVector pos, float size, bool propagation)
fire->m_nNextTimeToAddFlames = 0; fire->m_nNextTimeToAddFlames = 0;
fire->ReportThisFire(); fire->ReportThisFire();
fire->m_fStrength = size; fire->m_fStrength = size;
fire->m_bExtinguishedWithWater = false;
} }
} }
CFire * 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; CPed *ped = (CPed *)entityOnFire;
CVehicle *veh = (CVehicle *)entityOnFire; CVehicle *veh = (CVehicle *)entityOnFire;
@ -234,10 +251,11 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength
ped->SetFlee(pos, 10000); ped->SetFlee(pos, 10000);
ped->m_fleeFrom = nil; ped->m_fleeFrom = nil;
} }
ped->m_fleeTimer = CTimer::GetTimeInMilliseconds() + 10000;
ped->bDrawLast = false; ped->bDrawLast = false;
ped->SetMoveState(PEDMOVE_SPRINT); ped->SetMoveState(PEDMOVE_SPRINT);
ped->SetMoveAnim(); ped->SetMoveAnim();
ped->m_nPedState = PED_ON_FIRE; ped->SetPedState(PED_ON_FIRE);
} }
if (fleeFrom) { if (fleeFrom) {
if (ped->m_nPedType == PEDTYPE_COP) { if (ped->m_nPedType == PEDTYPE_COP) {
@ -251,6 +269,9 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength
} else { } else {
if (entityOnFire->IsVehicle()) { if (entityOnFire->IsVehicle()) {
veh->m_pCarFire = fire; veh->m_pCarFire = fire;
if (CModelInfo::IsBikeModel(veh->GetModelIndex()) || CModelInfo::IsCarModel(veh->GetModelIndex()))
CCarAI::TellOccupantsToFleeCar(veh);
if (fleeFrom) { if (fleeFrom) {
CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE, CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE,
entityOnFire, (CPed *)fleeFrom, 10000); entityOnFire, (CPed *)fleeFrom, 10000);
@ -259,6 +280,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength
} }
fire->m_bIsOngoing = true; fire->m_bIsOngoing = true;
fire->m_bExtinguishedWithWater = false;
fire->m_bIsScriptFire = false; fire->m_bIsScriptFire = false;
fire->m_vecPos = entityOnFire->GetPosition(); fire->m_vecPos = entityOnFire->GetPosition();
@ -297,7 +319,6 @@ CFireManager::Update(void)
CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance) CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance)
{ {
for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) {
int fireId = -1; int fireId = -1;
float minDistance = 999999; float minDistance = 999999;
for (int j = 0; j < NUM_FIRES; j++) { for (int j = 0; j < NUM_FIRES; j++) {
@ -305,8 +326,6 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance)
continue; continue;
if (m_aFires[j].m_bIsScriptFire) if (m_aFires[j].m_bIsScriptFire)
continue; continue;
if (m_aFires[j].m_nFiremenPuttingOut != i)
continue;
float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D();
if (distance < minDistance) { if (distance < minDistance) {
minDistance = distance; minDistance = distance;
@ -316,7 +335,7 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance)
*pDistance = minDistance; *pDistance = minDistance;
if (fireId != -1) if (fireId != -1)
return &m_aFires[fireId]; return &m_aFires[fireId];
}
return nil; 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 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; CFire *fire;
CPed *ped = (CPed *)target; CPed *ped = (CPed *)target;
@ -397,12 +447,15 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt
fire->m_vecPos = pos; fire->m_vecPos = pos;
fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400; fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;
fire->m_pEntity = target; fire->m_pEntity = target;
fire->m_bExtinguishedWithWater = false;
if (target) if (target)
target->RegisterReference(&fire->m_pEntity); target->RegisterReference(&fire->m_pEntity);
fire->m_pSource = nil; fire->m_pSource = nil;
fire->m_nNextTimeToAddFlames = 0; fire->m_nNextTimeToAddFlames = 0;
fire->m_fStrength = strength; fire->m_fStrength = strength;
fire->m_fWaterExtinguishCountdown = 1.0f;
if (target) { if (target) {
if (target->IsPed()) { if (target->IsPed()) {
ped->m_pFire = fire; ped->m_pFire = fire;
@ -410,7 +463,7 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt
CVector2D pos = target->GetPosition(); CVector2D pos = target->GetPosition();
ped->SetFlee(pos, 10000); ped->SetFlee(pos, 10000);
ped->SetMoveAnim(); ped->SetMoveAnim();
ped->m_nPedState = PED_ON_FIRE; ped->SetPedState(PED_ON_FIRE);
} }
} else if (target->IsVehicle()) { } else if (target->IsVehicle()) {
veh->m_pCarFire = fire; veh->m_pCarFire = fire;
@ -430,8 +483,7 @@ CFireManager::RemoveAllScriptFires(void)
{ {
for (int i = 0; i < NUM_FIRES; i++) { for (int i = 0; i < NUM_FIRES; i++) {
if (m_aFires[i].m_bIsScriptFire) { if (m_aFires[i].m_bIsScriptFire) {
m_aFires[i].Extinguish(); RemoveScriptFire(i);
m_aFires[i].m_bIsScriptFire = false;
} }
} }
} }

View file

@ -14,10 +14,10 @@ public:
CEntity *m_pSource; CEntity *m_pSource;
uint32 m_nExtinguishTime; uint32 m_nExtinguishTime;
uint32 m_nStartTime; uint32 m_nStartTime;
int32 field_20;
uint32 m_nNextTimeToAddFlames; uint32 m_nNextTimeToAddFlames;
uint32 m_nFiremenPuttingOut;
float m_fStrength; float m_fStrength;
float m_fWaterExtinguishCountdown;
bool m_bExtinguishedWithWater;
CFire(); CFire();
~CFire(); ~CFire();
@ -34,15 +34,17 @@ class CFireManager
public: public:
uint32 m_nTotalFires; uint32 m_nTotalFires;
CFire m_aFires[NUM_FIRES]; 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); void Update(void);
CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange); CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange);
CFire *FindNearestFire(CVector vecPos, float *pDistance); CFire *FindNearestFire(CVector vecPos, float *pDistance);
CFire *GetNextFreeFire(void); CFire *GetNextFreeFire(void);
uint32 GetTotalActiveFires() const; uint32 GetTotalActiveFires() const;
void ExtinguishPoint(CVector point, float range); 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); bool IsScriptFireExtinguish(int16 index);
void RemoveAllScriptFires(void); void RemoveAllScriptFires(void);
void RemoveScriptFire(int16 index); void RemoveScriptFire(int16 index);

View file

@ -90,6 +90,7 @@
#include "debugmenu.h" #include "debugmenu.h"
#include "Ropes.h" #include "Ropes.h"
#include "WindModifiers.h" #include "WindModifiers.h"
#include "WaterCreatures.h"
#include "postfx.h" #include "postfx.h"
#include "custompipes.h" #include "custompipes.h"
@ -478,8 +479,7 @@ bool CGame::ShutDown(void)
CPlane::Shutdown(); CPlane::Shutdown();
CTrain::Shutdown(); CTrain::Shutdown();
CScriptPaths::Shutdown(); CScriptPaths::Shutdown();
// TODO(Miami) CWaterCreatures::RemoveAll();
// CWaterCreatures::RemoveAll();
CSpecialFX::Shutdown(); CSpecialFX::Shutdown();
#ifndef PS2 #ifndef PS2
CGarages::Shutdown(); CGarages::Shutdown();
@ -650,7 +650,7 @@ void CGame::ShutDownForRestart(void)
CRadar::RemoveRadarSections(); CRadar::RemoveRadarSections();
FrontEndMenuManager.UnloadTextures(); FrontEndMenuManager.UnloadTextures();
CParticleObject::RemoveAllExpireableParticleObjects(); CParticleObject::RemoveAllExpireableParticleObjects();
//CWaterCreatures::RemoveAll(); //TODO(Miami) CWaterCreatures::RemoveAll();
CSetPieces::Init(); CSetPieces::Init();
CPedType::Shutdown(); CPedType::Shutdown();
CSpecialFX::Shutdown(); CSpecialFX::Shutdown();

View file

@ -2,6 +2,8 @@
#include <ctype.h> #include <ctype.h>
// --MIAMI: file done
class CGeneral class CGeneral
{ {
public: public:

View file

@ -3209,7 +3209,7 @@ int16 CPad::SniperModeLookLeftRight(void)
if ( Abs(axis) > Abs(dpad) ) { if ( Abs(axis) > Abs(dpad) ) {
if ( Abs(axis) > 35.0f ) { if ( Abs(axis) > 35.0f ) {
return (axis > 0.f ? axis - 35.f : axis + 35.f) * 1.3763441f; return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35));
} else { } else {
return 0; return 0;
} }
@ -3231,7 +3231,7 @@ int16 CPad::SniperModeLookUpDown(void)
if ( Abs(axis) > Abs(dpad) ) { if ( Abs(axis) > Abs(dpad) ) {
if ( Abs(axis) > 35.0f ) { if ( Abs(axis) > 35.0f ) {
return (axis > 0.f ? axis - 35.f : axis + 35.f) * 1.3763441f; return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35));
} else { } else {
return 0; return 0;
} }

View file

@ -46,7 +46,11 @@ CStreamingInfo CStreaming::ms_endRequestedList;
int32 CStreaming::ms_oldSectorX; int32 CStreaming::ms_oldSectorX;
int32 CStreaming::ms_oldSectorY; int32 CStreaming::ms_oldSectorY;
int32 CStreaming::ms_streamingBufferSize; int32 CStreaming::ms_streamingBufferSize;
#ifndef ONE_THREAD_PER_CHANNEL
int8 *CStreaming::ms_pStreamingBuffer[2]; int8 *CStreaming::ms_pStreamingBuffer[2];
#else
int8 *CStreaming::ms_pStreamingBuffer[4];
#endif
size_t CStreaming::ms_memoryUsed; size_t CStreaming::ms_memoryUsed;
CStreamingChannel CStreaming::ms_channel[2]; CStreamingChannel CStreaming::ms_channel[2];
int32 CStreaming::ms_channelError; int32 CStreaming::ms_channelError;
@ -197,6 +201,10 @@ CStreaming::Init2(void)
ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
ms_streamingBufferSize /= 2; ms_streamingBufferSize /= 2;
ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
#ifdef ONE_THREAD_PER_CHANNEL
ms_pStreamingBuffer[2] = (int8*)RwMallocAlign(ms_streamingBufferSize*2*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
ms_pStreamingBuffer[3] = ms_pStreamingBuffer[2] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
#endif
debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); debug("Streaming buffer size is %d sectors", ms_streamingBufferSize);
// PC only, figure out how much memory we got // PC only, figure out how much memory we got
@ -2196,6 +2204,110 @@ CStreaming::LoadRequestedModels(void)
} }
} }
// Let's load models first, then process it. Unfortunately processing models are still single-threaded.
// Currently only supported on POSIX streamer.
#ifdef ONE_THREAD_PER_CHANNEL
void
CStreaming::LoadAllRequestedModels(bool priority)
{
static bool bInsideLoadAll = false;
int imgOffset, streamId, status;
int i;
uint32 posn, size;
if(bInsideLoadAll)
return;
bInsideLoadAll = true;
FlushChannels();
imgOffset = GetCdImageOffset(CdStreamGetLastPosn());
int streamIds[ARRAY_SIZE(ms_pStreamingBuffer)];
int streamSizes[ARRAY_SIZE(ms_pStreamingBuffer)];
int streamPoses[ARRAY_SIZE(ms_pStreamingBuffer)];
bool first = true;
int processI = 0;
while (true) {
// Enumerate files and start reading
for (int i=0; i<ARRAY_SIZE(ms_pStreamingBuffer); i++) {
if (!first && streamIds[i] != -1) {
processI = i;
continue;
}
if(ms_endRequestedList.m_prev != &ms_startRequestedList){
streamId = GetNextFileOnCd(0, priority);
if(streamId == -1){
streamIds[i] = -1;
break;
}
if (ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)) {
streamIds[i] = -1;
if (size > (uint32)ms_streamingBufferSize) {
if (i + 1 == ARRAY_SIZE(ms_pStreamingBuffer))
continue;
else if (!first && streamIds[i+1] != -1)
continue;
} else {
if (i != 0 && streamIds[i-1] != -1 && streamSizes[i-1] > (uint32)ms_streamingBufferSize)
continue;
}
ms_aInfoForModel[streamId].RemoveFromList();
DecrementRef(streamId);
streamIds[i] = streamId;
streamSizes[i] = size;
streamPoses[i] = posn;
CdStreamRead(i, ms_pStreamingBuffer[i], imgOffset+posn, size);
processI = i;
} else {
ms_aInfoForModel[streamId].RemoveFromList();
DecrementRef(streamId);
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
streamIds[i] = -1;
}
} else
streamIds[i] = -1;
}
first = false;
// Now process
if (streamIds[processI] == -1)
break;
// Try again on error
while (CdStreamSync(processI) != STREAM_NONE) {
CdStreamRead(processI, ms_pStreamingBuffer[processI], imgOffset+streamPoses[processI], streamSizes[processI]);
}
ms_aInfoForModel[streamIds[processI]].m_loadState = STREAMSTATE_READING;
MakeSpaceFor(streamSizes[processI] * CDSTREAM_SECTOR_SIZE);
ConvertBufferToObject(ms_pStreamingBuffer[processI], streamIds[processI]);
if(ms_aInfoForModel[streamIds[processI]].m_loadState == STREAMSTATE_STARTED)
FinishLoadingLargeFile(ms_pStreamingBuffer[processI], streamIds[processI]);
if(streamIds[processI] < STREAM_OFFSET_TXD){
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamIds[processI]);
if(mi->IsSimple())
mi->m_alpha = 255;
}
streamIds[processI] = -1;
}
ms_bLoadingBigModel = false;
for(i = 0; i < 4; i++){
ms_channel[1].streamIds[i] = -1;
ms_channel[1].offsets[i] = -1;
}
ms_channel[1].state = CHANNELSTATE_IDLE;
bInsideLoadAll = false;
}
#else
void void
CStreaming::LoadAllRequestedModels(bool priority) CStreaming::LoadAllRequestedModels(bool priority)
{ {
@ -2256,6 +2368,7 @@ CStreaming::LoadAllRequestedModels(bool priority)
ms_channel[1].state = CHANNELSTATE_IDLE; ms_channel[1].state = CHANNELSTATE_IDLE;
bInsideLoadAll = false; bInsideLoadAll = false;
} }
#endif
void void
CStreaming::FlushChannels(void) CStreaming::FlushChannels(void)
@ -2287,6 +2400,14 @@ CStreaming::FlushRequestList(void)
next = si->m_next; next = si->m_next;
RemoveModel(si - ms_aInfoForModel); RemoveModel(si - ms_aInfoForModel);
} }
#ifndef _WIN32
if(ms_channel[0].state == CHANNELSTATE_READING) {
flushStream[0] = 1;
}
if(ms_channel[1].state == CHANNELSTATE_READING) {
flushStream[1] = 1;
}
#endif
FlushChannels(); FlushChannels();
} }
@ -2815,10 +2936,15 @@ CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem)
void void
CStreaming::MakeSpaceFor(int32 size) CStreaming::MakeSpaceFor(int32 size)
{ {
// BUG: ms_memoryAvailable can be uninitialized #ifdef FIX_BUGS
// the code still happens to work in that case because ms_memoryAvailable is unsigned #define MB (1024 * 1024)
// but it's not nice.... if(ms_memoryAvailable == 0) {
extern size_t _dwMemAvailPhys;
ms_memoryAvailable = (_dwMemAvailPhys - 10 * MB) / 2;
if(ms_memoryAvailable < 65 * MB) ms_memoryAvailable = 65 * MB;
}
#undef MB
#endif
while(ms_memoryUsed >= ms_memoryAvailable - size) while(ms_memoryUsed >= ms_memoryAvailable - size)
if(!RemoveLeastUsedModel(STREAMFLAGS_20)){ if(!RemoveLeastUsedModel(STREAMFLAGS_20)){
DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); DeleteRwObjectsBehindCamera(ms_memoryAvailable - size);

View file

@ -10,6 +10,8 @@
#include "World.h" #include "World.h"
#include "Zones.h" #include "Zones.h"
// --MIAMI: file done
CPlaceName CUserDisplay::PlaceName; CPlaceName CUserDisplay::PlaceName;
COnscreenTimer CUserDisplay::OnscnTimer; COnscreenTimer CUserDisplay::OnscnTimer;
CPager CUserDisplay::Pager; CPager CUserDisplay::Pager;

View file

@ -9,7 +9,7 @@
#include "World.h" #include "World.h"
#include "Timer.h" #include "Timer.h"
//--MIAMI: file almost done (loading/saving will perhaps stay different) //--MIAMI: file done
eLevelName CTheZones::m_CurrLevel; eLevelName CTheZones::m_CurrLevel;
int16 CTheZones::FindIndex; int16 CTheZones::FindIndex;
@ -638,127 +638,132 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
+ sizeof(int16) // padding + sizeof(int16) // padding
+ sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray) + sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray)
+ sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos) + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos)
+ sizeof(int16) // padding
+ sizeof(MapZoneArray) + sizeof(AudioZoneArray) + sizeof(MapZoneArray) + sizeof(AudioZoneArray)
+ sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); + 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, length, m_CurrLevel);
WriteSaveBuf(buffer, FindIndex); WriteSaveBuf(buffer, length, FindIndex);
WriteSaveBuf(buffer, (int16)0); // padding WriteSaveBuf(buffer, length, (int16)0); // padding
// TODO(MIAMI) ? implement SaveOneZone for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++)
for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ SaveOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG);
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(InfoZoneArray); i++){ for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++)
CZone *zone = WriteSaveBuf(buffer, InfoZoneArray[i]); SaveOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO);
/*
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(ZoneInfoArray); i++) for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
WriteSaveBuf(buffer, ZoneInfoArray[i]); WriteSaveBuf(buffer, length, ZoneInfoArray[i]);
WriteSaveBuf(buffer, TotalNumberOfNavigationZones); WriteSaveBuf(buffer, length, TotalNumberOfNavigationZones);
WriteSaveBuf(buffer, TotalNumberOfInfoZones); WriteSaveBuf(buffer, length, TotalNumberOfInfoZones);
WriteSaveBuf(buffer, TotalNumberOfZoneInfos); WriteSaveBuf(buffer, length, TotalNumberOfZoneInfos);
WriteSaveBuf(buffer, length, (int16)0); // padding
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++)
CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); SaveOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE);
// 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);
}
for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++)
WriteSaveBuf(buffer, AudioZoneArray[i]); WriteSaveBuf(buffer, length, AudioZoneArray[i]);
WriteSaveBuf(buffer, TotalNumberOfMapZones); WriteSaveBuf(buffer, length, TotalNumberOfMapZones);
WriteSaveBuf(buffer, NumberOfAudioZones); WriteSaveBuf(buffer, length, NumberOfAudioZones);
VALIDATESAVEBUF(*size) 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 void
CTheZones::LoadAllZones(uint8 *buffer, uint32 size) CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
{ {
INITSAVEBUF INITSAVEBUF
int i; 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); m_CurrLevel = ReadSaveBuf<eLevelName>(buffer, length);
FindIndex = ReadSaveBuf<int16>(buffer); FindIndex = ReadSaveBuf<int16>(buffer, length);
ReadSaveBuf<int16>(buffer); ReadSaveBuf<int16>(buffer, length);
// TODO(MIAMI) ? implement LoadOneZone for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++)
for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ LoadOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG);
NavigationZoneArray[i] = ReadSaveBuf<CZone>(buffer);
NavigationZoneArray[i].child = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].child); for (i = 0; i < ARRAY_SIZE(InfoZoneArray); i++)
NavigationZoneArray[i].parent = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].parent); LoadOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO);
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(ZoneInfoArray); i++) for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer); ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer, length);
TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer); TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer, length);
TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer); TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer, length);
TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer); TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer, length);
ReadSaveBuf<int16>(buffer, length);
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++)
MapZoneArray[i] = ReadSaveBuf<CZone>(buffer); LoadOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE);
// 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);
}
for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++)
AudioZoneArray[i] = ReadSaveBuf<int16>(buffer); AudioZoneArray[i] = ReadSaveBuf<int16>(buffer, length);
TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer); TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer, length);
NumberOfAudioZones = ReadSaveBuf<uint16>(buffer); NumberOfAudioZones = ReadSaveBuf<uint16>(buffer, length);
VALIDATESAVEBUF(size) 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);
}

View file

@ -108,5 +108,7 @@ public:
static void AddZoneToAudioZoneArray(CZone *zone); static void AddZoneToAudioZoneArray(CZone *zone);
static void InitialiseAudioZoneArray(void); static void InitialiseAudioZoneArray(void);
static void SaveAllZones(uint8 *buffer, uint32 *length); 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 LoadAllZones(uint8 *buffer, uint32 length);
static void LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType);
}; };

View file

@ -106,7 +106,7 @@ typedef uint16_t wchar;
inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w) inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)
{ {
uint32 m = MASK(p,s); uint32 m = MASK(p,s);
return w & ~m | b<<p & m; return (w & ~m) | ((b<<p) & m);
} }
inline uint32 ldb(uint32 p, uint32 s, uint32 w) inline uint32 ldb(uint32 p, uint32 s, uint32 w)
{ {
@ -412,6 +412,15 @@ inline void SkipSaveBuf(uint8 *&buf, int32 skip)
#endif #endif
} }
inline void SkipSaveBuf(uint8*& buf, uint32 &length, int32 skip)
{
buf += skip;
length += skip;
#ifdef VALIDATE_SAVE_SIZE
_saveBufCount += skip;
#endif
}
template<typename T> template<typename T>
inline const T ReadSaveBuf(uint8 *&buf) inline const T ReadSaveBuf(uint8 *&buf)
{ {
@ -420,6 +429,14 @@ inline const T ReadSaveBuf(uint8 *&buf)
return value; return value;
} }
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> template<typename T>
inline T *WriteSaveBuf(uint8 *&buf, const T &value) inline T *WriteSaveBuf(uint8 *&buf, const T &value)
{ {
@ -429,6 +446,15 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value)
return p; 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)) #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(buf, d);\
WriteSaveBuf<uint32>(buf, size); 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)\ #define CheckSaveHeader(buf,a,b,c,d,size)\
assert(ReadSaveBuf<char>(buf) == a);\ assert(ReadSaveBuf<char>(buf) == a);\
assert(ReadSaveBuf<char>(buf) == b);\ assert(ReadSaveBuf<char>(buf) == b);\
@ -446,5 +479,12 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value)
assert(ReadSaveBuf<char>(buf) == d);\ assert(ReadSaveBuf<char>(buf) == d);\
assert(ReadSaveBuf<uint32>(buf) == size); 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*, ...); void cprintf(char*, ...);

View file

@ -87,7 +87,8 @@ enum Config {
NUMMBLURSTREAKS = 4, NUMMBLURSTREAKS = 4,
NUMSKIDMARKS = 32, NUMSKIDMARKS = 32,
NUMONSCREENTIMERENTRIES = 1, NUMONSCREENCLOCKS = 1,
NUMONSCREENCOUNTERS = 3,
NUMRADARBLIPS = 75, NUMRADARBLIPS = 75,
NUMGENERALPICKUPS = 320, NUMGENERALPICKUPS = 320,
NUMSCRIPTEDPICKUPS = 16, NUMSCRIPTEDPICKUPS = 16,
@ -137,6 +138,7 @@ enum Config {
NUM_CRANES = 8, NUM_CRANES = 8,
NUM_ESCALATORS = 22, NUM_ESCALATORS = 22,
NUM_WATER_CREATURES = 8,
NUM_EXPLOSIONS = 48, NUM_EXPLOSIONS = 48,
@ -248,6 +250,9 @@ enum Config {
#if !defined(RW_GL3) && defined(_WIN32) #if !defined(RW_GL3) && defined(_WIN32)
#define XINPUT #define XINPUT
#endif #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 DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m
#define KANGAROO_CHEAT #define KANGAROO_CHEAT
#define RESTORE_ALLCARSHELI_CHEAT #define RESTORE_ALLCARSHELI_CHEAT
@ -257,7 +262,6 @@ enum Config {
//#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls
// Hud, frontend and radar // 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 BETA_SLIDING_TEXT
#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC
#define PC_MENU #define PC_MENU

View file

@ -4,6 +4,8 @@
#include "World.h" #include "World.h"
#include "Dummy.h" #include "Dummy.h"
// --MIAMI: file done
void *CDummy::operator new(size_t sz) { return CPools::GetDummyPool()->New(); } void *CDummy::operator new(size_t sz) { return CPools::GetDummyPool()->New(); }
void CDummy::operator delete(void *p, size_t sz) { CPools::GetDummyPool()->Delete((CDummy*)p); } void CDummy::operator delete(void *p, size_t sz) { CPools::GetDummyPool()->Delete((CDummy*)p); }

View file

@ -1208,3 +1208,36 @@ bool CEntity::IsEntityOccluded(void) {
return false; return false;
} }
/*
0x487A10 - SetAtomicAlphaCB
0x4879E0 - SetClumpAlphaCB
*/
RpMaterial* SetAtomicAlphaCB(RpMaterial *material, void *data) {
((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;
return material;
}
RpAtomic* SetClumpAlphaCB(RpAtomic *atomic, void *data) {
RpGeometry *geometry = RpAtomicGetGeometry(atomic);
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)data);
return atomic;
}
void CEntity::SetRwObjectAlpha(int32 alpha) {
if (m_rwObject != nil) {
switch (RwObjectGetType(m_rwObject)) {
case rpATOMIC: {
RpGeometry *geometry = RpAtomicGetGeometry((RpAtomic*)m_rwObject);
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)alpha);
break;
}
case rpCLUMP:
RpClumpForAllAtomics((RpClump*)m_rwObject, SetClumpAlphaCB, (void*)alpha);
break;
}
}
}

View file

@ -179,6 +179,7 @@ public:
void ModifyMatrixForTreeInWind(void); void ModifyMatrixForTreeInWind(void);
void ModifyMatrixForBannerInWind(void); void ModifyMatrixForBannerInWind(void);
void ProcessLightsForEntity(void); void ProcessLightsForEntity(void);
void SetRwObjectAlpha(int32 alpha);
static void AddSteamsFromGround(CPtrList& list); static void AddSteamsFromGround(CPtrList& list);
}; };

314
src/extras/ini_parser.hpp Normal file
View file

@ -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

View file

@ -3,6 +3,8 @@
#include "DummyObject.h" #include "DummyObject.h"
#include "Pools.h" #include "Pools.h"
// --MIAMI: file done
CDummyObject::CDummyObject(CObject *obj) CDummyObject::CDummyObject(CObject *obj)
{ {
SetModelIndexNoCreate(obj->GetModelIndex()); SetModelIndexNoCreate(obj->GetModelIndex());

View file

@ -36,6 +36,7 @@ CObject::CObject(void)
m_colour2 = 0; m_colour2 = 0;
m_colour1 = m_colour2; m_colour1 = m_colour2;
m_nBonusValue = 0; m_nBonusValue = 0;
// m_nCostValue = 0; // TODO(Miami)
bIsPickup = false; bIsPickup = false;
bPickupObjWithMessage = false; bPickupObjWithMessage = false;
bOutOfStock = false; bOutOfStock = false;
@ -44,8 +45,12 @@ CObject::CObject(void)
bHasBeenDamaged = false; bHasBeenDamaged = false;
m_nRefModelIndex = -1; m_nRefModelIndex = -1;
bUseVehicleColours = false; bUseVehicleColours = false;
// bIsStreetLight = false; // duplicate
m_pCurSurface = nil; m_pCurSurface = nil;
m_pCollidingEntity = nil; m_pCollidingEntity = nil;
m_nBeachballBounces = 0;
bIsStreetLight = false;
m_area = AREA_EVERYWHERE;
} }
CObject::CObject(int32 mi, bool createRW) CObject::CObject(int32 mi, bool createRW)
@ -138,12 +143,16 @@ CObject::Render(void)
bool bool
CObject::SetupLighting(void) CObject::SetupLighting(void)
{ {
DeActivateDirectional();
SetAmbientColours();
if(bRenderScorched){ if(bRenderScorched){
WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f); WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
return true; return true;
} else if (bIsPickup) {
SetFullAmbient();
return true;
} else if (bIsWeapon) {
ActivateDirectional();
SetAmbientColoursForPedsCarsAndObjects();
return true;
} }
return false; return false;
} }
@ -151,8 +160,10 @@ CObject::SetupLighting(void)
void void
CObject::RemoveLighting(bool reset) CObject::RemoveLighting(bool reset)
{ {
if(reset) if(reset) {
WorldReplaceScorchedLightsWithNormal(Scene.world); SetAmbientColours();
DeActivateDirectional();
}
} }
void void
@ -363,6 +374,8 @@ CObject::CanBeDeleted(void)
return true; return true;
case CUTSCENE_OBJECT: case CUTSCENE_OBJECT:
return false; return false;
case CONTROLLED_SUB_OBJECT:
return false;
default: default:
return true; return true;
} }

View file

@ -8,7 +8,7 @@ enum {
MISSION_OBJECT = 2, MISSION_OBJECT = 2,
TEMP_OBJECT = 3, TEMP_OBJECT = 3,
CUTSCENE_OBJECT = 4, CUTSCENE_OBJECT = 4,
ESCALATOR_OBJECT = 5, CONTROLLED_SUB_OBJECT = 5,
}; };
enum CollisionSpecialResponseCase enum CollisionSpecialResponseCase

View file

@ -2,6 +2,8 @@
#include "Projectile.h" #include "Projectile.h"
// --MIAMI: file done
CProjectile::CProjectile(int32 model) : CObject() CProjectile::CProjectile(int32 model) : CObject()
{ {
m_fMass = 1.0f; m_fMass = 1.0f;

View file

@ -23,7 +23,7 @@ CStingerSegment::CStingerSegment()
m_fBuoyancy = GRAVITY * m_fMass * 0.1f; m_fBuoyancy = GRAVITY * m_fMass * 0.1f;
bExplosionProof = true; bExplosionProof = true;
SetModelIndex(MI_PLC_STINGER); SetModelIndex(MI_PLC_STINGER);
ObjectCreatedBy = ESCALATOR_OBJECT; ObjectCreatedBy = CONTROLLED_SUB_OBJECT;
NumOfStingerSegments++; NumOfStingerSegments++;
} }

View file

@ -104,7 +104,6 @@ CEmergencyPed::FiremanAI(void)
m_pAttendedFire = nearestFire; m_pAttendedFire = nearestFire;
#ifdef FIX_BUGS #ifdef FIX_BUGS
bIsRunning = true; bIsRunning = true;
++nearestFire->m_nFiremenPuttingOut;
#endif #endif
} }
break; break;
@ -116,10 +115,6 @@ CEmergencyPed::FiremanAI(void)
SetMoveState(PEDMOVE_RUN); SetMoveState(PEDMOVE_RUN);
#ifdef FIX_BUGS #ifdef FIX_BUGS
bIsRunning = true; bIsRunning = true;
if (m_pAttendedFire) {
--m_pAttendedFire->m_nFiremenPuttingOut;
}
++nearestFire->m_nFiremenPuttingOut;
m_pAttendedFire = nearestFire; m_pAttendedFire = nearestFire;
} else if (!nearestFire) { } else if (!nearestFire) {
#else #else
@ -153,10 +148,7 @@ CEmergencyPed::FiremanAI(void)
case EMERGENCY_PED_STOP: case EMERGENCY_PED_STOP:
#ifdef FIX_BUGS #ifdef FIX_BUGS
bIsRunning = false; bIsRunning = false;
if (m_pAttendedFire)
#endif #endif
--m_pAttendedFire->m_nFiremenPuttingOut;
m_nPedState = PED_NONE; m_nPedState = PED_NONE;
SetWanderPath(CGeneral::GetRandomNumber() & 7); SetWanderPath(CGeneral::GetRandomNumber() & 7);
m_pAttendedFire = nil; m_pAttendedFire = nil;

View file

@ -3,6 +3,8 @@
#include "main.h" #include "main.h"
#include "PedRoutes.h" #include "PedRoutes.h"
// --MIAMI: file done
CRouteNode gaRoutes[NUMPEDROUTES]; CRouteNode gaRoutes[NUMPEDROUTES];
void void

View file

@ -4,6 +4,8 @@
#include "FileMgr.h" #include "FileMgr.h"
#include "PedStats.h" #include "PedStats.h"
// --MIAMI: file done
CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS]; CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];
void void

View file

@ -24,12 +24,17 @@ float
CDraw::CalculateAspectRatio(void) CDraw::CalculateAspectRatio(void)
{ {
if (FrontEndMenuManager.m_PrefsUseWideScreen) { if (FrontEndMenuManager.m_PrefsUseWideScreen) {
#ifdef ASPECT_RATIO_SCALE
if (TheCamera.m_WideScreenOn)
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
CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f;
#else
if (TheCamera.m_WideScreenOn) if (TheCamera.m_WideScreenOn)
CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki CDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki
else else
#ifdef ASPECT_RATIO_SCALE
CDraw::ms_fAspectRatio = FrontEndMenuManager.m_PrefsUseWideScreen == AR_AUTO ? SCREEN_WIDTH / SCREEN_HEIGHT : 16.f / 9.f;
#else
CDraw::ms_fAspectRatio = 16.f / 9.f; CDraw::ms_fAspectRatio = 16.f / 9.f;
#endif #endif
} else if (TheCamera.m_WideScreenOn) { } else if (TheCamera.m_WideScreenOn) {

View file

@ -1358,7 +1358,7 @@ CEscalator::Update(void) {
if (m_pSteps[i]) { if (m_pSteps[i]) {
m_pSteps[i]->SetPosition(m_pos1); m_pSteps[i]->SetPosition(m_pos1);
CWorld::Add(m_pSteps[i]); CWorld::Add(m_pSteps[i]);
m_pSteps[i]->ObjectCreatedBy = ESCALATOR_OBJECT; m_pSteps[i]->ObjectCreatedBy = CONTROLLED_SUB_OBJECT;
} }
} }
} }

View file

@ -5,6 +5,46 @@
#include "Font.h" #include "Font.h"
#include "Timer.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; CFontDetails CFont::Details;
int16 CFont::NewLine; int16 CFont::NewLine;
CSprite2d CFont::Sprite[MAX_FONTS]; CSprite2d CFont::Sprite[MAX_FONTS];
@ -1102,6 +1142,7 @@ CFont::ParseToken(wchar *s)
switch(*s){ switch(*s){
case 'B': case 'B':
Details.bBold = !Details.bBold; Details.bBold = !Details.bBold;
break;
case 'N': case 'N':
case 'n': case 'n':
NewLine = 1; NewLine = 1;
@ -1109,7 +1150,7 @@ CFont::ParseToken(wchar *s)
case 'b': SetColor(CRGBA(27, 89, 130, 255)); Details.anonymous_23 = true; break; case 'b': SetColor(CRGBA(27, 89, 130, 255)); Details.anonymous_23 = true; break;
case 'f': case 'f':
Details.bFlash = !Details.bFlash; Details.bFlash = !Details.bFlash;
if (Details.bFlash) if (!Details.bFlash)
Details.color.a = 255; Details.color.a = 255;
break; break;
case 'g': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break; case 'g': SetColor(CRGBA(255, 150, 225, 255)); Details.anonymous_23 = true; break;

View file

@ -1,5 +1,11 @@
#pragma once #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 struct CFontDetails
{ {
CRGBA color; CRGBA color;

View file

@ -23,6 +23,9 @@
#include "CutsceneMgr.h" #include "CutsceneMgr.h"
#include "Stats.h" #include "Stats.h"
#include "main.h" #include "main.h"
#include "General.h"
// --MIAMI: file done
// Game has colors inlined in code. // Game has colors inlined in code.
// For easier modification we collect them here: // 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 ODDJOB2_COLOR(97, 194, 247, 255);
CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255); CRGBA MISSIONTITLE_COLOR(220, 172, 2, 255);
wchar CHud::m_HelpMessage[256]; wchar CHud::m_HelpMessage[HELP_MSG_LENGTH];
wchar CHud::m_LastHelpMessage[256]; wchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH];
uint32 CHud::m_HelpMessageState; uint32 CHud::m_HelpMessageState;
uint32 CHud::m_HelpMessageTimer; uint32 CHud::m_HelpMessageTimer;
int32 CHud::m_HelpMessageFadeTimer; int32 CHud::m_HelpMessageFadeTimer;
wchar CHud::m_HelpMessageToPrint[256]; wchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH];
float CHud::m_fHelpMessageTime; float CHud::m_HelpMessageDisplayTime;
bool CHud::m_HelpMessageDisplayForever;
bool CHud::m_HelpMessageQuick; bool CHud::m_HelpMessageQuick;
uint32 CHud::m_ZoneState; uint32 CHud::m_ZoneState;
int32 CHud::m_ZoneFadeTimer; int32 CHud::m_ZoneFadeTimer;
@ -73,16 +77,16 @@ bool CHud::m_Wants_To_Draw_3dMarkers;
wchar CHud::m_BigMessage[6][128]; wchar CHud::m_BigMessage[6][128];
int16 CHud::m_ItemToFlash; int16 CHud::m_ItemToFlash;
bool CHud::m_HideRadar; bool CHud::m_HideRadar;
int32 CHud::m_DrawClock; int32 CHud::m_ClockState;
// These aren't really in CHud // These aren't really in CHud
float CHud::BigMessageInUse[6]; float CHud::BigMessageInUse[6];
float CHud::BigMessageAlpha[6]; float CHud::BigMessageAlpha[6];
float CHud::BigMessageX[6]; float CHud::BigMessageX[6];
float CHud::OddJob2OffTimer; float CHud::OddJob2OffTimer;
bool CHud::CounterOnLastFrame; bool CHud::CounterOnLastFrame[NUMONSCREENCOUNTERS];
float CHud::OddJob2XOffset; float CHud::OddJob2XOffset;
uint16 CHud::CounterFlashTimer; uint16 CHud::CounterFlashTimer[NUMONSCREENCOUNTERS];
uint16 CHud::OddJob2Timer; uint16 CHud::OddJob2Timer;
bool CHud::TimerOnLastFrame; bool CHud::TimerOnLastFrame;
int16 CHud::OddJob2On; int16 CHud::OddJob2On;
@ -110,6 +114,8 @@ uint32 CHud::m_WeaponTimer;
uint32 CHud::m_LastDisplayScore; uint32 CHud::m_LastDisplayScore;
uint32 CHud::m_LastWanted; uint32 CHud::m_LastWanted;
uint32 CHud::m_LastWeapon;
uint32 CHud::m_LastTimeEnergyLost;
CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; CSprite2d CHud::Sprites[NUM_HUD_SPRITES];
@ -119,32 +125,81 @@ struct
const char *mask; const char *mask;
} WeaponFilenames[] = { } WeaponFilenames[] = {
{ "fist", "fistm" }, { "fist", "fistm" },
{ "brassk", "brasskA" },
{ "screw", "screwA" },
{ "golf", "golfA" },
{ "nightstick", "nightstickA" },
{ "knife", "knifeA" },
{ "bat", "batm" }, { "bat", "batm" },
{"pistol", "pistolm" }, { "hammer", "hammerA" },
{"uzi", "uzim"}, { "cleaver", "cleaverA" },
{"shotgun", "shotgunm"}, { "machete", "macheteA" },
{"ak47", "ak47m"}, { "sword", "swordA" },
{"m16", "m16m"}, { "chainsaw", "chainsawA" },
{"sniper", "sniperm"}, { "grenade", "grenadeA" },
{"rocket", "rocketm"}, { "grenade", "grenadeA" },
{"flame", "flamem"}, { "teargas", "teargasA" },
{"molotov", "molotovm"}, { "molotov", "molotovA" },
{"grenade", "grenadem"}, { "rocket", "rocketA" },
{"detonator", "detonator_mask"}, { "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" }, { "radardisc", "radardisc" },
{"pager", "pagerm"},
{ "", "" }, { "", "" },
{ "", "" }, { "", "" },
{"bleeder", ""}, { "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "sitesniper", "sitesniperm" }, { "sitesniper", "sitesniperm" },
{ "siteM16", "siteM16m" }, { "siteM16", "siteM16m" },
{"siterocket", "siterocket"} { "sitelaser", "sitelaserm" },
{ "laserdot", "laserdotm" },
{ "viewfinder_128", "viewfinder_128m" },
{ "bleeder", "" }
}; };
RwTexture *gpSniperSightTex; RwTexture *gpSniperSightTex;
RwTexture *gpRocketSightTex; RwTexture *gpRocketSightTex;
RwTexture *gpLaserSightTex;
RwTexture *gpLaserDotTex;
RwTexture *gpViewFinderTex;
void CHud::Draw() void CHud::Draw()
{ {
@ -160,7 +215,9 @@ void CHud::Draw()
return; return;
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) { if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
// unused statics in here
bool DrawCrossHair = false; bool DrawCrossHair = false;
bool CrossHairHidesHud = false;
bool DrawCrossHairPC = false; bool DrawCrossHairPC = false;
CPlayerPed *playerPed = FindPlayerPed(); 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); 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(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
} }
else { else {
int sprite = HUD_SITESNIPER;
float xOffset = SCREEN_SCALE_X(210.0f);
float yOffset = SCREEN_SCALE_Y(210.0f);
// TODO(Miami) if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE)
// Sniper sprite = HUD_SITELASER;
rect.left = SCREEN_WIDTH/2 - SCREEN_SCALE_X(210.0f);
rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); if (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_CAMERA) {
sprite = HUD_VIEWFINDER;
CrossHairHidesHud = true;
xOffset = SCREEN_SCALE_X(256.0f);
yOffset = SCREEN_SCALE_Y(192.0f);
}
rect.left = SCREEN_WIDTH/2 - xOffset;
rect.top = SCREEN_HEIGHT/2 - yOffset;
rect.right = SCREEN_WIDTH/2; rect.right = SCREEN_WIDTH/2;
rect.bottom = SCREEN_HEIGHT/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); 0.01f, 0.01f, 1.0f, 0.0f, 0.01f, 1.0f, 1.0f, 1.0f);
rect.left = SCREEN_WIDTH/2; rect.left = SCREEN_WIDTH/2;
rect.top = SCREEN_HEIGHT/2 - SCREEN_SCALE_Y(210.0f); rect.top = SCREEN_HEIGHT/2 - yOffset;
rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); rect.right = SCREEN_WIDTH/2 + xOffset;
rect.bottom = SCREEN_HEIGHT/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.99f, 0.0f, 0.01f, 0.01f, 0.99f, 1.0f, 0.01f, 1.0f); 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.top = SCREEN_HEIGHT/2;
rect.right = SCREEN_WIDTH/2; rect.right = SCREEN_WIDTH/2;
rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); rect.bottom = SCREEN_HEIGHT/2 + yOffset;
Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 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); 0.01f, 0.99f, 1.0f, 0.99f, 0.01f, 0.01f, 1.0f, 0.01f);
rect.left = SCREEN_WIDTH/2; rect.left = SCREEN_WIDTH/2;
rect.top = SCREEN_HEIGHT/2; rect.top = SCREEN_HEIGHT/2;
rect.right = SCREEN_WIDTH/2 + SCREEN_SCALE_X(210.0f); rect.right = SCREEN_WIDTH/2 + xOffset;
rect.bottom = SCREEN_HEIGHT/2 + SCREEN_SCALE_Y(210.0f); rect.bottom = SCREEN_HEIGHT/2 + yOffset;
Sprites[HUD_SITESNIPER].Draw(CRect(rect), CRGBA(255, 255, 255, 255), 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); 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); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
@ -293,6 +382,9 @@ void CHud::Draw()
SpriteBrightness = 0; SpriteBrightness = 0;
} }
if (CrossHairHidesHud)
return;
/* /*
DrawMoneyCounter DrawMoneyCounter
*/ */
@ -303,9 +395,9 @@ void CHud::Draw()
float alpha; float alpha;
if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) { if (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) {
alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 0); alpha = DrawFadeState(HUD_SCORE_FADING, 0);
} else { } else {
alpha = CHud::DrawFadeState(HUD_SCORE_FADING, 1); alpha = DrawFadeState(HUD_SCORE_FADING, 1);
m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
} }
if (m_DisplayScoreState != FADED_OUT) { if (m_DisplayScoreState != FADED_OUT) {
@ -334,9 +426,15 @@ void CHud::Draw()
/* /*
DrawAmmo DrawAmmo
*/ */
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType); 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(); CWeapon *weapon = playerPed->GetWeapon();
uint32 AmmoAmount = weaponInfo->m_nAmountofAmmunition; uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType)->m_nAmountofAmmunition;
uint32 AmmoInClip = weapon->m_nAmmoInClip; uint32 AmmoInClip = weapon->m_nAmmoInClip;
uint32 TotalAmmo = weapon->m_nAmmoTotal; uint32 TotalAmmo = weapon->m_nAmmoTotal;
uint32 Ammo, Clip; uint32 Ammo, Clip;
@ -347,34 +445,29 @@ void CHud::Draw()
if (WeaponType == WEAPONTYPE_FLAMETHROWER) { if (WeaponType == WEAPONTYPE_FLAMETHROWER) {
Clip = AmmoInClip / 10; Clip = AmmoInClip / 10;
if ((TotalAmmo - AmmoInClip) / 10 <= 9999) Ammo = Min((TotalAmmo - AmmoInClip) / 10, 9999);
Ammo = (TotalAmmo - AmmoInClip) / 10; } else {
else
Ammo = 9999;
}
else {
Clip = AmmoInClip; Clip = AmmoInClip;
if ((TotalAmmo - AmmoInClip) > 9999) Ammo = Min(TotalAmmo - AmmoInClip, 9999);
Ammo = 9999;
else
Ammo = TotalAmmo - AmmoInClip;
} }
sprintf(sTemp, "%d-%d", Ammo, Clip); sprintf(sTemp, "%d-%d", Ammo, Clip);
} }
AsciiToUnicode(sTemp, sPrint); AsciiToUnicode(sTemp, sPrint);
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType);
/* /*
DrawWeaponIcon DrawWeaponIcon
*/ */
if (FrontEndMenuManager.m_PrefsShowHud) {
if (weaponInfo->m_nModelId <= 0) { if (weaponInfo->m_nModelId <= 0) {
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
if (FrontEndMenuManager.m_PrefsShowHud)
Sprites[WeaponType].Draw( 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)), 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), CRGBA(255, 255, 255, alpha),
0.015f, 0.015f,
0.015f, 0.015f,
1.0f, 1.0f,
@ -412,15 +505,27 @@ void CHud::Draw()
if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) { if (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) {
CFont::SetDropShadowPosition(2); CFont::SetDropShadowPosition(2);
CFont::SetDropColor(CRGBA(0, 0, 0, 255)); CFont::SetDropColor(CRGBA(0, 0, 0, alpha));
AMMO_COLOR.a = alpha;
CFont::SetColor(AMMO_COLOR); CFont::SetColor(AMMO_COLOR);
if (FrontEndMenuManager.m_PrefsShowHud)
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint);
CFont::SetDropShadowPosition(0); CFont::SetDropShadowPosition(0);
} }
}
}
/* /*
DrawHealth DrawHealth
*/ */
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_EnergyLostState != FADED_OUT) {
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetJustifyOff(); CFont::SetJustifyOff();
@ -448,7 +553,7 @@ void CHud::Draw()
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) { if (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) {
@ -457,6 +562,7 @@ void CHud::Draw()
} }
} }
} }
}
/* /*
DrawArmour DrawArmour
@ -473,6 +579,7 @@ void CHud::Draw()
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);
@ -482,14 +589,16 @@ void CHud::Draw()
} }
} }
} }
}
}
/* /*
DrawWantedLevel DrawWantedLevel
*/ */
if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) if (m_LastWanted == playerPed->m_pWanted->m_nWantedLevel) {
alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 0); alpha = DrawFadeState(HUD_WANTED_FADING, 0);
else { } else {
alpha = CHud::DrawFadeState(HUD_WANTED_FADING, 1); alpha = DrawFadeState(HUD_WANTED_FADING, 1);
m_LastWanted = playerPed->m_pWanted->m_nWantedLevel; m_LastWanted = playerPed->m_pWanted->m_nWantedLevel;
} }
@ -745,11 +854,7 @@ void CHud::Draw()
break; break;
} }
#ifndef HUD_ENHANCEMENTS
if (!m_Message[0]) { 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(); m_VehicleNameTimer += CTimer::GetTimeStepInMilliseconds();
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetPropOn(); CFont::SetPropOn();
@ -787,7 +892,7 @@ void CHud::Draw()
/* /*
DrawClock DrawClock
*/ */
if (m_DrawClock) { if (m_ClockState) {
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
@ -814,30 +919,28 @@ void CHud::Draw()
wchar sTimer[16]; wchar sTimer[16];
if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) if (!CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed)
TimerOnLastFrame = false; TimerOnLastFrame = false;
if (!CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterProcessed)
CounterOnLastFrame = false;
#ifdef FIX_BUGS for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
#define TIMER_RIGHT_OFFSET 34.0f // Taken from VC frenzy timer if (!CUserDisplay::OnscnTimer.m_sCounters[0].m_bCounterProcessed)
#else CounterOnLastFrame[i] = false;
#define TIMER_RIGHT_OFFSET 27.0f }
#endif
if (CUserDisplay::OnscnTimer.m_bProcessed) { if (CUserDisplay::OnscnTimer.m_bProcessed) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerProcessed) { if (CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) {
if (!TimerOnLastFrame) if (!TimerOnLastFrame)
TimerFlashTimer = 1; TimerFlashTimer = 1;
TimerOnLastFrame = true; TimerOnLastFrame = true;
if (TimerFlashTimer) { if (TimerFlashTimer != 0) {
if (++TimerFlashTimer > 50) if (++TimerFlashTimer > 50)
TimerFlashTimer = 0; TimerFlashTimer = 0;
} }
if (CTimer::GetFrameCounter() & 4 || !TimerFlashTimer) { if (CTimer::GetFrameCounter() & 4 || TimerFlashTimer == 0) {
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bTimerBuffer, sTimer); AsciiToUnicode(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockBuffer, sTimer);
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
@ -846,125 +949,83 @@ void CHud::Draw()
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetPropOff(); CFont::SetPropOff();
CFont::SetBackGroundOnlyTextOn(); CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetDropShadowPosition(2);
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::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetColor(TIMER_COLOR); CFont::SetColor(TIMER_COLOR);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET), SCREEN_SCALE_Y(110.0f), sTimer); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(110.0f), sTimer);
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_aTimerText[0]) {
CFont::SetPropOn(); 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));
if (CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText[0]) {
CFont::SetDropShadowPosition(2);
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetColor(TIMER_COLOR); 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;
if (CounterFlashTimer) {
if (++CounterFlashTimer > 50)
CounterFlashTimer = 0;
}
if (CTimer::GetFrameCounter() & 4 || !CounterFlashTimer) { for(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {
if (CUserDisplay::OnscnTimer.m_sEntries[0].m_nType == COUNTER_DISPLAY_NUMBER) { if (CUserDisplay::OnscnTimer.m_sCounters[i].m_bCounterProcessed) {
AsciiToUnicode(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer, sTimer); if (!CounterOnLastFrame[i])
CounterFlashTimer[i] = 1;
CounterOnLastFrame[i] = true;
if (CounterFlashTimer[i] != 0) {
if (++CounterFlashTimer[i] > 50)
CounterFlashTimer[i] = 0;
}
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::SetPropOn();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetRightJustifyWrap(0.0f); CFont::SetRightJustifyWrap(0.0f);
CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetColor(CRGBA(244, 20, 20, 255));
CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH)); 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 (CUserDisplay::OnscnTimer.m_sEntries[0].m_aCounterText[0]) {
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y)); CFont::SetBackGroundOnlyTextOn();
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetDropShadowPosition(2);
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::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetColor(COUNTER_COLOR); 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)); 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);
}
}
#undef TIMER_RIGHT_OFFSET
/* const float barWidth = SCREEN_SCALE_X(100.f / 2.f);
DrawPager const float right = SCREEN_SCALE_FROM_RIGHT(37.0f);
*/ const float left = right - barWidth;
if (!m_PagerMessage[0] && PagerOn == 1) {
PagerSoundPlayed = false; const float barHeight = SCREEN_SCALE_Y(11.0f);
PagerOn = 2; 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;
if (m_PagerMessage[0] || PagerOn == 2) {
if (!PagerOn) { // shadow
PagerOn = 1; 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));
PagerXOffset = 150.0f;
} CSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, right + SCREEN_SCALE_X(4.0f), bottom), CRGBA(27, 89, 130, 255));
if (PagerOn == 1) { 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 (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)); if (CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText[0]) {
CFont::SetPropOn();
CFont::SetBackgroundOff(); CFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));
CFont::SetScale(SCREEN_SCALE_X(0.84f), SCREEN_SCALE_Y(1.0f)); CFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));
CFont::SetColor(PAGER_COLOR); CFont::SetDropShadowPosition(2);
CFont::SetRightJustifyOff(); CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetBackgroundOff(); CFont::SetColor(COUNTER_COLOR);
CFont::SetCentreOff(); 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));
CFont::SetJustifyOff(); }
CFont::SetPropOff(); // unused/leftover color. I wonder what was it for
CFont::SetFontStyle(FONT_STANDARD); CFont::SetColor(CRGBA(244, 225, 91, 255));
CFont::PrintString(SCREEN_SCALE_X(52.0f - PagerXOffset), SCREEN_SCALE_Y(54.0f), m_PagerMessage); }
}
}
} }
/* /*
@ -1126,14 +1187,14 @@ void CHud::Draw()
*/ */
if (m_HelpMessage[0]) { 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) { switch (m_HelpMessageState) {
case 0: case 0:
m_HelpMessageFadeTimer = 0; m_HelpMessageFadeTimer = 0;
m_HelpMessageState = 2; m_HelpMessageState = 2;
m_HelpMessageTimer = 0; m_HelpMessageTimer = 0;
CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, 256); CMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH);
m_fHelpMessageTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f;
if (TheCamera.m_ScreenReductionPercentage == 0.0f) if (TheCamera.m_ScreenReductionPercentage == 0.0f)
DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0);
@ -1148,7 +1209,7 @@ void CHud::Draw()
default: default:
break; break;
} }
CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, 256); CMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH);
} }
float fAlpha = 225.0f; float fAlpha = 225.0f;
@ -1158,7 +1219,9 @@ void CHud::Draw()
case 1: case 1:
fAlpha = 225.0f; fAlpha = 225.0f;
m_HelpMessageFadeTimer = 600; 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_HelpMessageFadeTimer = 600;
m_HelpMessageState = 3; m_HelpMessageState = 3;
} }
@ -1187,7 +1250,7 @@ void CHud::Draw()
if (m_HelpMessageFadeTimer < 0) { if (m_HelpMessageFadeTimer < 0) {
m_HelpMessageState = 2; m_HelpMessageState = 2;
m_HelpMessageFadeTimer = 0; 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; fAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;
break; break;
@ -1212,7 +1275,7 @@ void CHud::Draw()
CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f)); CFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f));
CFont::DrawFonts(); CFont::DrawFonts();
// CFont::SetColor(CRGBA(175, 175, 175, 255)); CFont::SetColor(CRGBA(175, 175, 175, 255));
CFont::SetJustifyOff(); CFont::SetJustifyOff();
#ifdef MORE_LANGUAGES #ifdef MORE_LANGUAGES
if (CFont::IsJapanese()) if (CFont::IsJapanese())
@ -1224,9 +1287,9 @@ void CHud::Draw()
CFont::SetBackgroundOn(); CFont::SetBackgroundOn();
CFont::SetBackGroundOnlyTextOff(); CFont::SetBackGroundOnlyTextOff();
CFont::SetDropShadowPosition(0); CFont::SetDropShadowPosition(0);
CFont::SetColor(CRGBA(175, 175, 175, 255));
CFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f)); 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::SetAlphaFade(255.0f);
CFont::SetWrapx(SCREEN_WIDTH); CFont::SetWrapx(SCREEN_WIDTH);
} }
@ -1311,19 +1374,19 @@ void CHud::Draw()
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
CFont::SetColor(CRGBA(0, 0, 0, BigMessageAlpha[2])); CFont::SetDropShadowPosition(2);
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f - 4.0f), SCREEN_SCALE_FROM_BOTTOM(78.0f), m_BigMessage[2]); CFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[2]));
CFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, 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 { else {
BigMessageInUse[2] = 1.0f; BigMessageInUse[2] = 1.0f;
BigMessageAlpha[2] = 0.0f; BigMessageAlpha[2] = 0.0f;
if (CHud::m_VehicleState != 0) if (m_VehicleState != 0) // Hide vehicle name if wasted/busted text is displaying
CHud::m_VehicleState = 0; m_VehicleState = 0;
if (CHud::m_ZoneState != 0) if (m_ZoneState != 0)
CHud::m_ZoneState = 0; m_ZoneState = 0;
} }
} }
else { else {
@ -1332,7 +1395,6 @@ void CHud::Draw()
} }
} }
// --MIAMI: Done
void CHud::DrawAfterFade() void CHud::DrawAfterFade()
{ {
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
@ -1522,7 +1584,7 @@ void CHud::DrawAfterFade()
BigMessageInUse[1] = 120.0f; BigMessageInUse[1] = 120.0f;
BigMessageAlpha[1] -= CTimer::GetTimeStepInMilliseconds(); BigMessageAlpha[1] -= CTimer::GetTimeStepInMilliseconds();
} }
if (BigMessageAlpha[1] <= 0) { if (BigMessageAlpha[1] <= 0.0f) {
m_BigMessage[1][0] = 0; m_BigMessage[1][0] = 0;
BigMessageInUse[1] = 0.0f; BigMessageInUse[1] = 0.0f;
BigMessageAlpha[1] = 0.0f; BigMessageAlpha[1] = 0.0f;
@ -1558,12 +1620,11 @@ void CHud::DrawAfterFade()
void CHud::GetRidOfAllHudMessages() void CHud::GetRidOfAllHudMessages()
{ {
m_ZoneState = 0;
m_pLastZoneName = nil;
m_ZoneNameTimer = 0; m_ZoneNameTimer = 0;
m_pZoneName = nil; 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_HelpMessage[i] = 0;
m_LastHelpMessage[i] = 0; m_LastHelpMessage[i] = 0;
m_HelpMessageToPrint[i] = 0; m_HelpMessageToPrint[i] = 0;
@ -1573,15 +1634,15 @@ void CHud::GetRidOfAllHudMessages()
m_HelpMessageFadeTimer = 0; m_HelpMessageFadeTimer = 0;
m_HelpMessageState = 0; m_HelpMessageState = 0;
m_HelpMessageQuick = 0; m_HelpMessageQuick = 0;
m_fHelpMessageTime = 1.0f; m_HelpMessageDisplayForever = false;
m_HelpMessageDisplayTime = 1.0f;
m_VehicleName = nil; m_VehicleName = nil;
m_pLastVehicleName = nil;
m_pVehicleNameToPrint = nil; m_pVehicleNameToPrint = nil;
m_VehicleNameTimer = 0; m_VehicleNameTimer = 0;
m_VehicleFadeTimer = 0; m_VehicleFadeTimer = 0;
m_VehicleState = 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; m_Message[i] = 0;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
@ -1631,21 +1692,34 @@ void CHud::Initialise()
Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask); Sprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask);
} }
m_pLastZoneName = nil;
GetRidOfAllHudMessages(); GetRidOfAllHudMessages();
m_pLastVehicleName = nil;
if (gpSniperSightTex == nil) if (gpSniperSightTex == nil)
gpSniperSightTex = RwTextureRead("sitesniper", nil); gpSniperSightTex = RwTextureRead("sitesniper", nil); // unused
if (gpRocketSightTex == nil) if (gpRocketSightTex == nil)
gpRocketSightTex = RwTextureRead("siterocket", nil); gpRocketSightTex = RwTextureRead("siterocket", nil);
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_DrawClock = 1;
CounterOnLastFrame = false;
m_ItemToFlash = ITEM_NONE; m_ItemToFlash = ITEM_NONE;
OddJob2Timer = 0; OddJob2Timer = 0;
OddJob2OffTimer = 0.0f; OddJob2OffTimer = 0.0f;
OddJob2On = 0; OddJob2On = 0;
OddJob2XOffset = 0.0f; OddJob2XOffset = 0.0f;
CounterFlashTimer = 0; CounterFlashTimer[0] = 0;
CounterFlashTimer[1] = 0;
CounterFlashTimer[2] = 0;
TimerOnLastFrame = false; TimerOnLastFrame = false;
TimerFlashTimer = 0; TimerFlashTimer = 0;
SpriteBrightness = 0; SpriteBrightness = 0;
@ -1676,7 +1750,9 @@ void CHud::Initialise()
m_HideRadar = false; m_HideRadar = false;
m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss;
m_LastWanted = 0; m_LastWanted = 0;
m_LastWeapon = 0;
CTxdStore::PopCurrentTxd(); CTxdStore::PopCurrentTxd();
} }
@ -1685,16 +1761,22 @@ void CHud::ReInitialise() {
m_Wants_To_Draw_Hud = true; m_Wants_To_Draw_Hud = true;
m_Wants_To_Draw_3dMarkers = true; m_Wants_To_Draw_3dMarkers = true;
m_pLastZoneName = nil;
GetRidOfAllHudMessages(); GetRidOfAllHudMessages();
m_pLastVehicleName = nil;
CounterOnLastFrame = false; CounterOnLastFrame[0] = false;
CounterOnLastFrame[1] = false;
CounterOnLastFrame[2] = false;
m_ItemToFlash = ITEM_NONE; m_ItemToFlash = ITEM_NONE;
m_DrawClock = 1; m_ClockState = 1;
OddJob2Timer = 0; OddJob2Timer = 0;
OddJob2OffTimer = 0.0f; OddJob2OffTimer = 0.0f;
OddJob2On = 0; OddJob2On = 0;
OddJob2XOffset = 0.0f; OddJob2XOffset = 0.0f;
CounterFlashTimer = 0; CounterFlashTimer[0] = 0;
CounterFlashTimer[1] = 0;
CounterFlashTimer[2] = 0;
TimerOnLastFrame = false; TimerOnLastFrame = false;
TimerFlashTimer = 0; TimerFlashTimer = 0;
SpriteBrightness = 0; SpriteBrightness = 0;
@ -1725,15 +1807,20 @@ void CHud::ReInitialise() {
m_HideRadar = false; m_HideRadar = false;
m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney; m_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;
m_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss;
m_LastWanted = 0; m_LastWanted = 0;
m_LastWeapon = 0;
} }
wchar LastBigMessage[6][128]; wchar LastBigMessage[6][128];
void CHud::SetBigMessage(wchar *message, int16 style) void CHud::SetBigMessage(wchar *message, uint16 style)
{ {
int i = 0; int i = 0;
if (BigMessageInUse[style] != 0.0f)
return;
if (style == 5) { if (style == 5) {
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
if (message[i] == 0) if (message[i] == 0)
@ -1758,18 +1845,42 @@ void CHud::SetBigMessage(wchar *message, int16 style)
m_BigMessage[style][i] = 0; m_BigMessage[style][i] = 0;
} }
void CHud::SetHelpMessage(wchar *message, bool quick) void CHud::SetHelpMessage(wchar *message, bool quick, bool displayForever)
{ {
if (!CReplay::IsPlayingBack()) { if (!CReplay::IsPlayingBack()) {
CMessages::WideStringCopy(m_HelpMessage, message, 256); for (int i = 0; i < HELP_MSG_LENGTH; i++) {
CMessages::InsertPlayerControlKeysInString(m_HelpMessage); 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;
}
for (int i = 0; i < 256; i++) { 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; m_LastHelpMessage[i] = 0;
} }
m_HelpMessageState = 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_HelpMessageQuick = quick;
m_HelpMessageDisplayForever = displayForever;
}
} }
} }
@ -1778,11 +1889,10 @@ bool CHud::IsHelpMessageBeingDisplayed(void)
return m_HelpMessageState != 0; return m_HelpMessageState != 0;
} }
void CHud::SetMessage(wchar *message) void CHud::SetMessage(wchar *message)
{ {
int i = 0; int i = 0;
for (i = 0; i < 256; i++) { for (i = 0; i < ARRAY_SIZE(m_Message); i++) {
if (message[i] == 0) if (message[i] == 0)
break; break;
@ -1794,7 +1904,7 @@ void CHud::SetMessage(wchar *message)
void CHud::SetPagerMessage(wchar *message) void CHud::SetPagerMessage(wchar *message)
{ {
int i = 0; int i = 0;
for (i = 0; i < 256; i++) { for (i = 0; i < ARRAY_SIZE(m_PagerMessage); i++) {
if (message[i] == 0) if (message[i] == 0)
break; break;
@ -1825,6 +1935,15 @@ void CHud::Shutdown()
RwTextureDestroy(gpRocketSightTex); RwTextureDestroy(gpRocketSightTex);
gpRocketSightTex = nil; gpRocketSightTex = nil;
RwTextureDestroy(gpLaserSightTex);
gpLaserSightTex = nil;
RwTextureDestroy(gpLaserDotTex);
gpLaserDotTex = nil;
RwTextureDestroy(gpViewFinderTex);
gpViewFinderTex = nil;
int HudTXD = CTxdStore::FindTxdSlot("hud"); int HudTXD = CTxdStore::FindTxdSlot("hud");
CTxdStore::RemoveTxdSlot(HudTXD); CTxdStore::RemoveTxdSlot(HudTXD);
} }

View file

@ -1,6 +1,11 @@
#pragma once #pragma once
#include "Sprite2d.h" #include "Sprite2d.h"
#define HELP_MSG_LENGTH 256
#define HUD_TEXT_SCALE_X 0.7f
#define HUD_TEXT_SCALE_Y 1.25f
enum eItems enum eItems
{ {
ITEM_NONE = -1, ITEM_NONE = -1,
@ -31,41 +36,29 @@ enum eFadeOperation
enum eSprites enum eSprites
{ {
HUD_FIST, HUD_FIST,
HUD_BAT, HUD_SITEROCKET = 41,
HUD_PISTOL, HUD_RADARDISC = 50,
HUD_UZI, HUD_SITESNIPER = 63,
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_SITEM16, HUD_SITEM16,
HUD_SITEROCKET, HUD_SITELASER,
NUM_HUD_SPRITES, 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 class CHud
{ {
public: public:
static CSprite2d Sprites[NUM_HUD_SPRITES]; static CSprite2d Sprites[NUM_HUD_SPRITES];
static wchar m_HelpMessage[256]; static wchar m_HelpMessage[HELP_MSG_LENGTH];
static wchar m_LastHelpMessage[256]; static wchar m_LastHelpMessage[HELP_MSG_LENGTH];
static uint32 m_HelpMessageState; static uint32 m_HelpMessageState;
static uint32 m_HelpMessageTimer; static uint32 m_HelpMessageTimer;
static int32 m_HelpMessageFadeTimer; static int32 m_HelpMessageFadeTimer;
static wchar m_HelpMessageToPrint[256]; static wchar m_HelpMessageToPrint[HELP_MSG_LENGTH];
static float &m_HelpMessageDisplayTime; static float m_HelpMessageDisplayTime;
static float m_fHelpMessageTime; static bool m_HelpMessageDisplayForever;
static bool m_HelpMessageQuick; static bool m_HelpMessageQuick;
static uint32 m_ZoneState; static uint32 m_ZoneState;
static int32 m_ZoneFadeTimer; static int32 m_ZoneFadeTimer;
@ -86,16 +79,16 @@ public:
static wchar m_BigMessage[6][128]; static wchar m_BigMessage[6][128];
static int16 m_ItemToFlash; static int16 m_ItemToFlash;
static bool m_HideRadar; static bool m_HideRadar;
static int32 m_DrawClock; static int32 m_ClockState;
// These aren't really in CHud // These aren't really in CHud
static float BigMessageInUse[6]; static float BigMessageInUse[6];
static float BigMessageAlpha[6]; static float BigMessageAlpha[6];
static float BigMessageX[6]; static float BigMessageX[6];
static float OddJob2OffTimer; static float OddJob2OffTimer;
static bool CounterOnLastFrame; static bool CounterOnLastFrame[NUMONSCREENCOUNTERS];
static float OddJob2XOffset; static float OddJob2XOffset;
static uint16 CounterFlashTimer; static uint16 CounterFlashTimer[NUMONSCREENCOUNTERS];
static uint16 OddJob2Timer; static uint16 OddJob2Timer;
static bool TimerOnLastFrame; static bool TimerOnLastFrame;
static int16 OddJob2On; static int16 OddJob2On;
@ -121,6 +114,8 @@ public:
static uint32 m_LastDisplayScore; static uint32 m_LastDisplayScore;
static uint32 m_LastWanted; static uint32 m_LastWanted;
static uint32 m_LastWeapon;
static uint32 m_LastTimeEnergyLost;
public: public:
static void Draw(); static void Draw();
@ -131,8 +126,8 @@ public:
#endif #endif
static void Initialise(); static void Initialise();
static void ReInitialise(); static void ReInitialise();
static void SetBigMessage(wchar *message, int16 style); static void SetBigMessage(wchar *message, uint16 style);
static void SetHelpMessage(wchar *message, bool quick); static void SetHelpMessage(wchar *message, bool quick, bool displayForever = false);
static bool IsHelpMessageBeingDisplayed(void); static bool IsHelpMessageBeingDisplayed(void);
static void SetMessage(wchar *message); static void SetMessage(wchar *message);
static void SetPagerMessage(wchar *message); static void SetPagerMessage(wchar *message);

View file

@ -366,6 +366,12 @@ COcclusion::ProcessBeforeRendering(void)
} }
NumActiveOccluders--; NumActiveOccluders--;
i--; i--;
// Taken from Mobile!
#ifdef FIX_BUGS
if (i == -1) {
i = 0;
}
#endif
} }
} }
} }

View file

@ -1220,8 +1220,11 @@ void CParticle::Update()
if ( psystem->m_Type == PARTICLE_HEATHAZE || psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST ) if ( psystem->m_Type == PARTICLE_HEATHAZE || psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST )
{ {
#ifdef FIX_BUGS
int32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE;
#else
int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE; int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;
#endif
vecMoveStep.x = Sin(nSinCosIndex); vecMoveStep.x = Sin(nSinCosIndex);
vecMoveStep.y = Sin(nSinCosIndex); vecMoveStep.y = Sin(nSinCosIndex);
@ -1233,8 +1236,11 @@ void CParticle::Update()
if ( psystem->m_Type == PARTICLE_BEASTIE ) if ( psystem->m_Type == PARTICLE_BEASTIE )
{ {
#ifdef FIX_BUGS
int32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE;
#else
int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE; int32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;
#endif
particle->m_vecVelocity.x = 0.50f * Cos(nSinCosIndex); particle->m_vecVelocity.x = 0.50f * Cos(nSinCosIndex);
particle->m_vecVelocity.y = Cos(nSinCosIndex); particle->m_vecVelocity.y = Cos(nSinCosIndex);
particle->m_vecVelocity.z = 0.25f * Sin(nSinCosIndex); particle->m_vecVelocity.z = 0.25f * Sin(nSinCosIndex);
@ -1750,7 +1756,11 @@ void CParticle::Update()
} }
if ( particle->m_nRotationStep != 0 ) if ( particle->m_nRotationStep != 0 )
#ifdef FIX_BUGS
particle->m_nRotation = CGeneral::LimitAngle(particle->m_nRotation + particle->m_nRotationStep);
#else
particle->m_nRotation += particle->m_nRotationStep; particle->m_nRotation += particle->m_nRotationStep;
#endif
if ( particle->m_fCurrentZRadius != 0.0f ) if ( particle->m_fCurrentZRadius != 0.0f )
{ {
@ -2403,7 +2413,7 @@ void CParticle::HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos)
{ {
float fHeadingRad = entity->GetForward().Heading(); float fHeadingRad = entity->GetForward().Heading();
float fHeading = RADTODEG(fHeadingRad); float fHeading = RADTODEG(fHeadingRad);
float fBirdAngle = Cos(DEGTORAD(1.5f)); float fBirdAngle = ::Cos(DEGTORAD(1.5f));
tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[PARTICLE_BIRD_FRONT]; tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[PARTICLE_BIRD_FRONT];
CParticle *particle = psystem->m_pParticles; CParticle *particle = psystem->m_pParticles;

View file

@ -77,9 +77,13 @@ void CWaterCannon::Update_OncePerFrame(int16 index)
} }
} }
int32 extinguishingPoint = CGeneral::GetRandomNumber() & (NUM_SEGMENTPOINTS - 1); for ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )
if ( m_abUsed[extinguishingPoint] ) {
gFireManager.ExtinguishPoint(m_avecPos[extinguishingPoint], 3.0f); if ( m_abUsed[i] && gFireManager.ExtinguishPointWithWater(m_avecPos[i], 4.0f) )
{
break;
}
}
if ( ((index + CTimer::GetFrameCounter()) & 3) == 0 ) if ( ((index + CTimer::GetFrameCounter()) & 3) == 0 )
PushPeds(); PushPeds();

View file

@ -0,0 +1,267 @@
#include "WaterCreatures.h"
#include "ModelIndices.h"
#include "World.h"
#include "WaterLevel.h"
#include "Camera.h"
#include "PlayerPed.h"
#include "config.h"
#include "General.h"
int CWaterCreatures::nNumActiveSeaLifeForms;
CWaterCreature CWaterCreatures::aWaterCreatures[NUM_WATER_CREATURES];
struct WaterCreatureProperties aProperties[65] = {
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_JELLYFISH, 0.01f, 2.2f, 0.0005f, 3.5f },
{ &MI_JELLYFISH01, 0.01f, 2.2f, 0.0005f, 3.5f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_TURTLE, 0.01f, 2.0f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_DOLPHIN, 0.03f, 1.5f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_SHARK, 0.03f, 0.4f, 0.0005f, 4.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH1SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH2SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH2S, 0.04f, 1.5f, 0.0008f, 3.0f },
{ &MI_FISH3SINGLE, 0.04f, 3.0f, 0.0008f, 3.0f },
{ &MI_FISH3S, 0.04f, 1.5f, 0.0008f, 3.0f },
};
CWaterCreature::CWaterCreature() {
Free();
}
CWaterCreature::~CWaterCreature() {
//looks like unused
}
void CWaterCreature::Initialise(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {
this->m_pObj = pObj;
this->m_fRightMult = fRightMult;
this->m_fZTurnSpeed = fZTurnSpeed;
this->m_fWaterDepth = fWaterDepth;
this->m_alpha = alpha;
this->m_state = state;
}
void CWaterCreature::Allocate(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {
CWaterCreature::Initialise(pObj, fRightMult, fZTurnSpeed, fWaterDepth, alpha, state);
}
void CWaterCreature::Free() {
CWaterCreature::Initialise(nil, 0.0f, 0.0f, 0.0f, 0, WATER_CREATURE_DISABLED);
}
CWaterCreature *CWaterCreatures::GetFishStructSlot() {
for (int i = 0; i < NUM_WATER_CREATURES; i++)
if (aWaterCreatures[i].m_state == WATER_CREATURE_DISABLED)
return &aWaterCreatures[i];
return nil;
}
CObject *CWaterCreatures::CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle) {
if (CObject::nNoTempObjects >= 40)
return nil;
CObject *pObj = new CObject(modelID, true);
if (!pObj) return nil;
pObj->GetMatrix().GetPosition() = pos;
pObj->GetMatrix().UpdateRW();
pObj->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
pObj->GetMatrix().SetRotateZOnly(DEGTORAD(zRotAngle));
pObj->GetMatrix().UpdateRW();
pObj->ObjectCreatedBy = CONTROLLED_SUB_OBJECT;
pObj->bIsStatic = false;
if (pObj->ObjectCreatedBy == TEMP_OBJECT) {
CObject::nNoTempObjects++;
pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
}
pObj->bTouchingWater = true;
pObj->bUnderwater = true;
CWorld::Add(pObj);
return pObj;
}
bool CWaterCreatures::IsSpaceForMoreWaterCreatures() {
return nNumActiveSeaLifeForms < NUM_WATER_CREATURES;
}
float CWaterCreatures::CalculateFishHeading(CVector const& pos1, CVector const& pos2) {
CVector delta = pos1 - pos2;
delta.Normalise();
return Atan2(-delta.x, delta.y);
}
void CWaterCreatures::CreateOne(CVector const& pos, int32 modelID) {
if (!IsSpaceForMoreWaterCreatures())
return;
CVector storedPos = pos;
float fDepth, fLevelNoWaves;
if (!TheCamera.IsSphereVisible(storedPos, 3.0f)
&& CWaterLevel::GetWaterDepth(storedPos, &fDepth, &fLevelNoWaves, nil) && fDepth > 4.5f) {
if (modelID == -1 || modelID < 0 || modelID > 64)
modelID = CGeneral::GetRandomNumberInRange(0, 64);
WaterCreatureProperties *creature = &aProperties[modelID];
storedPos.z = fLevelNoWaves - creature->fLevel;
float fRightMult = CGeneral::GetRandomNumberInRange(0.0f, creature->fRightMult) + 0.01f;
float angle = CWaterCreatures::CalculateFishHeading(FindPlayerPed()->GetPosition(), storedPos);
CObject *fish = CreateSeaLifeForm(storedPos, *(int16*)creature->modelID, angle);
if (!fish) return;
fish->SetRwObjectAlpha(255);
CWaterCreature *wc = GetFishStructSlot();
wc->Allocate(fish, fRightMult, 0.0f, creature->fWaterDepth, 255, WATER_CREATURE_ALLOCATED);
nNumActiveSeaLifeForms++;
}
}
void CWaterCreatures::FreeFishStructSlot(CWaterCreature *wc) {
wc->Free();
}
void CWaterCreatures::UpdateAll() {
if (nNumActiveSeaLifeForms == 0)
return;
CVector playerPos = FindPlayerPed()->GetPosition();
for (int i = 0; i < NUM_WATER_CREATURES; i++) {
switch (aWaterCreatures[i].m_state) {
case WATER_CREATURE_ACTIVE:
aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;
if (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) {
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(0);
aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE;
break;
}
case WATER_CREATURE_ALLOCATED: {
if ((playerPos - aWaterCreatures[i].m_pObj->GetPosition()).Magnitude() < SQR(75.0f)) {
if (aWaterCreatures[i].m_alpha < 255)
aWaterCreatures[i].m_alpha = Min(aWaterCreatures[i].m_alpha + 4, 255);
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);
CVector newRight = aWaterCreatures[i].m_pObj->GetRight();
newRight.Normalise();
aWaterCreatures[i].m_pObj->m_vecMoveSpeed = newRight * aWaterCreatures[i].m_fRightMult;
aWaterCreatures[i].m_pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, aWaterCreatures[i].m_fZTurnSpeed);
aWaterCreatures[i].m_pObj->bIsStatic = false;
float fDepth = 0.0;
CWaterLevel::GetWaterDepth(aWaterCreatures[i].m_pObj->GetPosition(), &fDepth, nil, nil);
if (aWaterCreatures[i].m_fWaterDepth < fDepth) {
if (aWaterCreatures[i].m_pObj->m_nEndOfLifeTime - 40000 <= CTimer::GetTimeInMilliseconds())
aWaterCreatures[i].m_state = WATER_CREATURE_ACTIVE;
}
else {
aWaterCreatures[i].m_state = WATER_CREATURE_UPDATE;
}
}
else {
aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE;
}
break;
}
case WATER_CREATURE_UPDATE: {
aWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;
if (aWaterCreatures[i].m_alpha <= 0) {
aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE;
}
else {
aWaterCreatures[i].m_alpha = Max(aWaterCreatures[i].m_alpha - 6, 0);
aWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);
CVector newRight = aWaterCreatures[i].m_pObj->GetRight();
newRight.Normalise();
newRight.x *= aWaterCreatures[i].m_fRightMult;
newRight.y *= aWaterCreatures[i].m_fRightMult;
newRight.z -= 0.015f;
aWaterCreatures[i].m_pObj->m_vecMoveSpeed = newRight;
if (!aWaterCreatures[i].m_pObj->GetIsOnScreen())
aWaterCreatures[i].m_state = WATER_CREATURE_TO_REMOVE;
}
break;
}
case WATER_CREATURE_TO_REMOVE:
if (aWaterCreatures[i].m_pObj)
CWorld::Remove(aWaterCreatures[i].m_pObj);
FreeFishStructSlot(&aWaterCreatures[i]);
nNumActiveSeaLifeForms--;
aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;
break;
default:
break;
}
}
}
void CWaterCreatures::RemoveAll() {
for (int i = 0; i < NUM_WATER_CREATURES; i++) {
if (aWaterCreatures[i].m_state != WATER_CREATURE_DISABLED) {
CWorld::Remove(aWaterCreatures[i].m_pObj);
FreeFishStructSlot(&aWaterCreatures[i]);
aWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;
nNumActiveSeaLifeForms--;
}
}
}

View file

@ -0,0 +1,49 @@
#pragma once
#include "Object.h"
enum eFishSlotState {
WATER_CREATURE_ALLOCATED = 0,
WATER_CREATURE_ACTIVE,
WATER_CREATURE_UPDATE,
WATER_CREATURE_TO_REMOVE,
WATER_CREATURE_DISABLED
};
class CWaterCreature {
public:
CObject *m_pObj;
float m_fRightMult;
float m_fZTurnSpeed;
int32 m_alpha;
float m_fWaterDepth;
int32 m_state;
CWaterCreature();
~CWaterCreature();
void Allocate(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);
void Free();
void Initialise(CObject *pObj, float fRightMult, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);
};
class CWaterCreatures {
public:
static CWaterCreature aWaterCreatures[NUM_WATER_CREATURES];
static int32 nNumActiveSeaLifeForms;
static CObject *CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle);
static void CreateOne(CVector const& pos, int32 modelID);
static void UpdateAll();
static void FreeFishStructSlot(CWaterCreature *wc);
static bool IsSpaceForMoreWaterCreatures();
static float CalculateFishHeading(CVector const& pos1, CVector const& pos2);
static void RemoveAll();
static CWaterCreature* GetFishStructSlot();
};
struct WaterCreatureProperties {
int16 *modelID;
float fRightMult;
float fLevel;
float fUnknown; //unused
float fWaterDepth;
};

View file

@ -27,6 +27,7 @@
#include "Replay.h" #include "Replay.h"
#include "WaterLevel.h" #include "WaterLevel.h"
#include "SurfaceTable.h" #include "SurfaceTable.h"
#include "WaterCreatures.h"
#define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src)) #define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src))
@ -2821,8 +2822,7 @@ CWaterLevel::HandleSeaLifeForms()
} }
else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 ) else if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )
{ {
//TODO(MIAMI) if ( CWaterCreatures::IsSpaceForMoreWaterCreatures() )
// if ( CWaterCreatures::IsSpaceForMoreWaterCreatures() )
{ {
for ( int32 i = 0; i < 3; i++ ) for ( int32 i = 0; i < 3; i++ )
{ {
@ -2838,14 +2838,12 @@ CWaterLevel::HandleSeaLifeForms()
vecPos.x += (fCos - fSin) * fAngle; vecPos.x += (fCos - fSin) * fAngle;
vecPos.y += (fSin + fCos) * fAngle; vecPos.y += (fSin + fCos) * fAngle;
//TODO(MIAMI) CWaterCreatures::CreateOne(vecPos, -1);
//CWaterCreatures::CreateOne(vecPos, 0xFFFFFFFF);
} }
} }
} }
//TODO(MIAMI) CWaterCreatures::UpdateAll();
//CWaterCreatures::UpdateAll();
} }
void void

View file

@ -22,3 +22,4 @@ void SetAmbientColours(void);
void SetAmbientColoursForPedsCarsAndObjects(void); void SetAmbientColoursForPedsCarsAndObjects(void);
void SetAmbientColoursToIndicateRoadGroup(int i); void SetAmbientColoursToIndicateRoadGroup(int i);
void SetAmbientColours(RwRGBAReal *color); void SetAmbientColours(RwRGBAReal *color);
void SetFullAmbient(void);

View file

@ -11,6 +11,7 @@
#include "Clock.h" #include "Clock.h"
#include "Date.h" #include "Date.h"
#include "FileMgr.h" #include "FileMgr.h"
#include "Font.h"
#include "Frontend.h" #include "Frontend.h"
#include "GameLogic.h" #include "GameLogic.h"
#include "Gangs.h" #include "Gangs.h"

View file

@ -3,6 +3,7 @@
#include "crossplatform.h" #include "crossplatform.h"
#include "FileMgr.h" #include "FileMgr.h"
#include "Font.h"
#ifdef MORE_LANGUAGES #ifdef MORE_LANGUAGES
#include "Game.h" #include "Game.h"
#endif #endif

View file

@ -84,6 +84,16 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) {
} }
#endif #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 // Funcs/features from Windows that we need on other platforms
#ifndef _WIN32 #ifndef _WIN32
char *strupr(char *s) { char *strupr(char *s) {

View file

@ -67,6 +67,10 @@ void CapturePad(RwInt32 padID);
void joysChangeCB(int jid, int event); void joysChangeCB(int jid, int event);
#endif #endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
extern char gSelectedJoystickName[128];
#endif
enum eGameState enum eGameState
{ {
GS_START_UP = 0, GS_START_UP = 0,

View file

@ -41,7 +41,6 @@
#include "AnimViewer.h" #include "AnimViewer.h"
#include "Font.h" #include "Font.h"
#define MAX_SUBSYSTEMS (16) #define MAX_SUBSYSTEMS (16)
@ -81,12 +80,22 @@ DWORD _dwOperatingSystemVersion;
#include "resource.h" #include "resource.h"
#else #else
long _dwOperatingSystemVersion; long _dwOperatingSystemVersion;
#ifndef __APPLE__
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#else
#include <mach/mach_host.h>
#include <sys/sysctl.h>
#endif
#include <stddef.h> #include <stddef.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
char gSelectedJoystickName[128] = "";
#endif
/* /*
***************************************************************************** *****************************************************************************
*/ */
@ -424,6 +433,10 @@ psInitialize(void)
_dwOperatingSystemVersion = OS_WIN95; _dwOperatingSystemVersion = OS_WIN95;
} }
} }
#else
_dwOperatingSystemVersion = OS_WINXP; // To fool other classes
#endif
#ifndef PS2_MENU #ifndef PS2_MENU
@ -433,6 +446,8 @@ psInitialize(void)
#endif #endif
#ifdef _WIN32
MEMORYSTATUS memstats; MEMORYSTATUS memstats;
GlobalMemoryStatus(&memstats); GlobalMemoryStatus(&memstats);
@ -440,25 +455,43 @@ psInitialize(void)
debug("Physical memory size %u\n", memstats.dwTotalPhys); debug("Physical memory size %u\n", memstats.dwTotalPhys);
debug("Available physical memory %u\n", memstats.dwAvailPhys); 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 #else
#ifndef __APPLE__
#ifndef PS2_MENU
#ifdef GTA3_1_1_PATCH
FrontEndMenuManager.LoadSettings();
#endif
#endif
struct sysinfo systemInfo; struct sysinfo systemInfo;
sysinfo(&systemInfo); sysinfo(&systemInfo);
_dwMemAvailPhys = systemInfo.freeram; _dwMemAvailPhys = systemInfo.freeram;
_dwOperatingSystemVersion = OS_WINXP; // To fool other classes
debug("Physical memory size %u\n", systemInfo.totalram); debug("Physical memory size %u\n", systemInfo.totalram);
debug("Available physical memory %u\n", systemInfo.freeram); debug("Available physical memory %u\n", systemInfo.freeram);
#else
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);
#endif #endif
_dwOperatingSystemVersion = OS_WINXP; // To fool other classes
#endif
TheText.Unload(); TheText.Unload();
return TRUE; return TRUE;
@ -826,35 +859,26 @@ void joysChangeCB(int jid, int event);
bool IsThisJoystickBlacklisted(int i) bool IsThisJoystickBlacklisted(int i)
{ {
#ifndef DONT_TRUST_RECOGNIZED_JOYSTICKS
return false;
#else
if (glfwJoystickIsGamepad(i)) if (glfwJoystickIsGamepad(i))
return false; return false;
const char* joyname = glfwGetJoystickName(i); const char* joyname = glfwGetJoystickName(i);
// this is just a keyboard and mouse if (strncmp(joyname, gSelectedJoystickName, strlen(gSelectedJoystickName)) == 0)
// 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;
return false; return false;
return true;
#endif
} }
void _InputInitialiseJoys() void _InputInitialiseJoys()
{ {
PSGLOBAL(joy1id) = -1;
PSGLOBAL(joy2id) = -1;
for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) {
if (PSGLOBAL(joy1id) == -1) if (PSGLOBAL(joy1id) == -1)
@ -869,6 +893,9 @@ void _InputInitialiseJoys()
if (PSGLOBAL(joy1id) != -1) { if (PSGLOBAL(joy1id) != -1) {
int count; int count;
glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); glfwGetJoystickButtons(PSGLOBAL(joy1id), &count);
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id)));
#endif
ControlsManager.InitDefaultControlConfigJoyPad(count); ControlsManager.InitDefaultControlConfigJoyPad(count);
} }
} }
@ -1211,7 +1238,9 @@ void terminateHandler(int sig, siginfo_t *info, void *ucontext) {
} }
void dummyHandler(int sig){ void dummyHandler(int sig){
// Don't kill the app pls
} }
#endif #endif
void resizeCB(GLFWwindow* window, int width, int height) { void resizeCB(GLFWwindow* window, int width, int height) {
@ -1458,9 +1487,10 @@ main(int argc, char *argv[])
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL); sigaction(SIGTERM, &act, NULL);
struct sigaction sa; struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = dummyHandler; sa.sa_handler = dummyHandler;
sa.sa_flags = 0; sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL); // Needed for CdStreamPosix sigaction(SIGUSR1, &sa, NULL); // Needed for CdStreamPosix
#endif #endif
/* /*
@ -2084,18 +2114,19 @@ void CapturePad(RwInt32 padID)
void joysChangeCB(int jid, int event) void joysChangeCB(int jid, int event)
{ {
if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) {
{ if (PSGLOBAL(joy1id) == -1) {
if (PSGLOBAL(joy1id) == -1)
PSGLOBAL(joy1id) = jid; 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; PSGLOBAL(joy2id) = jid;
}
else if (event == GLFW_DISCONNECTED) } else if (event == GLFW_DISCONNECTED) {
{ if (PSGLOBAL(joy1id) == jid) {
if (PSGLOBAL(joy1id) == jid)
PSGLOBAL(joy1id) = -1; PSGLOBAL(joy1id) = -1;
else if (PSGLOBAL(joy2id) == jid) } else if (PSGLOBAL(joy2id) == jid)
PSGLOBAL(joy2id) = -1; PSGLOBAL(joy2id) = -1;
} }
} }

View file

@ -9,11 +9,12 @@
#include "Text.h" #include "Text.h"
#include "Timer.h" #include "Timer.h"
//--MIAMI: file done
static wchar WideErrorString[25]; static wchar WideErrorString[25];
CText TheText; CText TheText;
//--MIAMI: DONE
CText::CText(void) CText::CText(void)
{ {
encoding = 'e'; encoding = 'e';
@ -23,7 +24,6 @@ CText::CText(void)
memset(WideErrorString, 0, sizeof(WideErrorString)); memset(WideErrorString, 0, sizeof(WideErrorString));
} }
//--MIAMI: DONE
void void
CText::Load(void) CText::Load(void)
{ {
@ -95,7 +95,6 @@ CText::Load(void)
CFileMgr::SetDir(""); CFileMgr::SetDir("");
} }
//--MIAMI: DONE
void void
CText::Unload(void) CText::Unload(void)
{ {
@ -108,7 +107,6 @@ CText::Unload(void)
memset(szMissionTableName, 0, sizeof(szMissionTableName)); memset(szMissionTableName, 0, sizeof(szMissionTableName));
} }
//--MIAMI: DONE
wchar* wchar*
CText::Get(const char *key) CText::Get(const char *key)
{ {
@ -158,7 +156,6 @@ wchar FrenchUpperCaseTable[128] = {
253, 254, 255 253, 254, 255
}; };
//--MIAMI: TODO (check tables)
wchar wchar
CText::GetUpperCase(wchar c) CText::GetUpperCase(wchar c)
{ {
@ -190,7 +187,6 @@ CText::GetUpperCase(wchar c)
return c; return c;
} }
//--MIAMI: DONE
void void
CText::UpperCase(wchar *s) CText::UpperCase(wchar *s)
{ {
@ -200,27 +196,33 @@ CText::UpperCase(wchar *s)
} }
} }
//--MIAMI: DONE
void void
CText::GetNameOfLoadedMissionText(char *outName) CText::GetNameOfLoadedMissionText(char *outName)
{ {
strcpy(outName, szMissionTableName); strcpy(outName, szMissionTableName);
} }
//--MIAMI: DONE
void void
CText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset) 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 // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded
CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader)); CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader));
*offset += sizeof(ChunkHeader); *offset += sizeof(ChunkHeader);
#endif
} }
//--MIAMI: DONE
void void
CText::LoadMissionText(char *MissionTableName) CText::LoadMissionText(char *MissionTableName)
{ {
char filename[32]; char filename[32];
CMessages::ClearAllMessagesDisplayedByGame();
mission_keyArray.Unload(); mission_keyArray.Unload();
mission_data.Unload(); mission_data.Unload();
@ -306,7 +308,6 @@ CText::LoadMissionText(char *MissionTableName)
} }
//--MIAMI: DONE
void void
CKeyArray::Load(size_t length, int file, size_t* offset) 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; rawbytes = (char*)entries;
#if DUMB #if DUMB
for (uint32 i = 0; i < length; i++) for (uint32 i = 0; i < length; i++) {
CFileMgr::Read(file, &rawbytes[i], 1); CFileMgr::Read(file, &rawbytes[i], 1);
(*offset)++;
}
#else #else
CFileMgr::Read(file, rawbytes, length); CFileMgr::Read(file, rawbytes, length);
*offset += length;
#endif #endif
} }
//--MIAMI: DONE
void void
CKeyArray::Unload(void) CKeyArray::Unload(void)
{ {
@ -334,7 +337,6 @@ CKeyArray::Unload(void)
numEntries = 0; numEntries = 0;
} }
//--MIAMI: DONE
void void
CKeyArray::Update(wchar *chars) CKeyArray::Update(wchar *chars)
{ {
@ -345,7 +347,6 @@ CKeyArray::Update(wchar *chars)
#endif #endif
} }
//--MIAMI: DONE
CKeyEntry* CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) 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; return nil;
} }
//--MIAMI: DONE
wchar* wchar*
#ifdef FIX_BUGS #ifdef FIX_BUGS
CKeyArray::Search(const char *key, wchar *data, uint8 *result) CKeyArray::Search(const char *key, wchar *data, uint8 *result)
@ -402,7 +402,6 @@ CKeyArray::Search(const char *key, uint8 *result)
return WideErrorString; return WideErrorString;
} }
//--MIAMI: DONE
void void
CData::Load(size_t length, int file, size_t * offset) 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; rawbytes = (char*)chars;
#if DUMB #if DUMB
for(uint32 i = 0; i < length; i++) for(uint32 i = 0; i < length; i++){
CFileMgr::Read(file, &rawbytes[i], 1); CFileMgr::Read(file, &rawbytes[i], 1);
(*offset)++;
}
#else #else
CFileMgr::Read(file, rawbytes, length); CFileMgr::Read(file, rawbytes, length);
*offset += length;
#endif #endif
} }
//--MIAMI: DONE
void void
CData::Unload(void) CData::Unload(void)
{ {
@ -430,22 +431,31 @@ CData::Unload(void)
numChars = 0; numChars = 0;
} }
//--MIAMI: DONE
void void
CMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int) 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 // 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. // 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)); size = (uint16) (table_size / sizeof(CMissionTextOffsets::Entry));
CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size); CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size);
*offset += sizeof(CMissionTextOffsets::Entry) * size; *offset += sizeof(CMissionTextOffsets::Entry) * size;
} #endif
void
AsciiToUnicode(const char *src, wchar *dst)
{
while((*dst++ = (unsigned char)*src++) != '\0');
} }
char* char*
@ -460,8 +470,29 @@ UnicodeToAscii(wchar *src)
if(*src < 128) if(*src < 128)
#endif #endif
aStr[len] = *src; aStr[len] = *src;
else // convert to CP1252
aStr[len] = '#'; 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'; aStr[len] = '\0';
return aStr; return aStr;
} }
@ -471,7 +502,7 @@ UnicodeToAsciiForSaveLoad(wchar *src)
{ {
static char aStr[256]; static char aStr[256];
int len; int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++) for(len = 0; *src != '\0' && len < 256; len++, src++)
if(*src < 256) if(*src < 256)
aStr[len] = *src; aStr[len] = *src;
else else
@ -485,7 +516,7 @@ UnicodeToAsciiForMemoryCard(wchar *src)
{ {
static char aStr[256]; static char aStr[256];
int len; int len;
for(len = 0; *src != '\0' && len < 256-1; len++, src++) for(len = 0; *src != '\0' && len < 256; len++, src++)
if(*src < 256) if(*src < 256)
aStr[len] = *src; aStr[len] = *src;
else else
@ -494,40 +525,6 @@ UnicodeToAsciiForMemoryCard(wchar *src)
return aStr; return aStr;
} }
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 void
TextCopy(wchar *dst, const wchar *src) TextCopy(wchar *dst, const wchar *src)
{ {

View file

@ -1,14 +1,9 @@
#pragma once #pragma once
void AsciiToUnicode(const char *src, wchar *dst);
char *UnicodeToAscii(wchar *src); char *UnicodeToAscii(wchar *src);
char *UnicodeToAsciiForSaveLoad(wchar *src); char *UnicodeToAsciiForSaveLoad(wchar *src);
char *UnicodeToAsciiForMemoryCard(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 TextCopy(wchar *dst, const wchar *src);
void UnicodeMakeUpperCase(wchar *dst, wchar *src);
struct CKeyEntry struct CKeyEntry
{ {

View file

@ -27,10 +27,15 @@ uint8 CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter;
uint32 CTheCarGenerators::CurrentActiveCount; uint32 CTheCarGenerators::CurrentActiveCount;
void CCarGenerator::SwitchOff() void CCarGenerator::SwitchOff()
{
#ifdef FIX_BUGS
if (m_nUsesRemaining != 0)
#endif
{ {
m_nUsesRemaining = 0; m_nUsesRemaining = 0;
--CTheCarGenerators::CurrentActiveCount; --CTheCarGenerators::CurrentActiveCount;
} }
}
void CCarGenerator::SwitchOn() void CCarGenerator::SwitchOn()
{ {

View file

@ -1011,8 +1011,9 @@ CHeli::TestSniperCollision(CVector *line0, CVector *line1)
bool hit = false; bool hit = false;
for(i = 0; i < NUM_HELIS; i++){ for(i = 0; i < NUM_HELIS; i++){
if(pHelis[i] && !pHelis[i]->bBulletProof) {
CVector pilotPos = pHelis[i]->GetMatrix() * CVector(-0.43f, 1.49f, 1.5f); CVector pilotPos = pHelis[i]->GetMatrix() * CVector(-0.43f, 1.49f, 1.5f);
if(pHelis[i] && !pHelis[i]->bBulletProof && CCollision::DistToLine(line0, line1, &pilotPos) < 0.8f){ if(CCollision::DistToLine(line0, line1, &pilotPos) < 0.8f){
pHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f; pHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f;
pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN; pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;
pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 9999999; pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 9999999;
@ -1021,6 +1022,7 @@ CHeli::TestSniperCollision(CVector *line0, CVector *line1)
hit = true; hit = true;
} }
} }
}
return hit; return hit;
} }

View file

@ -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 #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 #else
if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed()) if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed())
#endif #endif

View file

@ -187,7 +187,7 @@ public:
CAutoPilot AutoPilot; CAutoPilot AutoPilot;
uint8 m_currentColour1; uint8 m_currentColour1;
uint8 m_currentColour2; uint8 m_currentColour2;
uint8 m_aExtras[2]; int8 m_aExtras[2];
int16 m_nAlarmState; int16 m_nAlarmState;
int16 m_nRouteSeed; int16 m_nRouteSeed;
CPed *pDriver; CPed *pDriver;

View file

@ -249,28 +249,28 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_nModelId = modelId; ms_apWeaponInfos[weaponType].m_nModelId = modelId;
ms_apWeaponInfos[weaponType].m_nModel2Id = modelId2; ms_apWeaponInfos[weaponType].m_nModel2Id = modelId2;
ms_apWeaponInfos[weaponType].m_bUseGravity = flags; ms_apWeaponInfos[weaponType].m_bUseGravity = flags & 1;
ms_apWeaponInfos[weaponType].m_bSlowsDown = flags >> 1; ms_apWeaponInfos[weaponType].m_bSlowsDown = (flags >> 1) & 1;
ms_apWeaponInfos[weaponType].m_bDissipates = flags >> 2; ms_apWeaponInfos[weaponType].m_bDissipates = (flags >> 2) & 1;
ms_apWeaponInfos[weaponType].m_bRandSpeed = flags >> 3; ms_apWeaponInfos[weaponType].m_bRandSpeed = (flags >> 3) & 1;
ms_apWeaponInfos[weaponType].m_bExpands = flags >> 4; ms_apWeaponInfos[weaponType].m_bExpands = (flags >> 4) & 1;
ms_apWeaponInfos[weaponType].m_bExplodes = flags >> 5; ms_apWeaponInfos[weaponType].m_bExplodes = (flags >> 5) & 1;
ms_apWeaponInfos[weaponType].m_bCanAim = flags >> 6; ms_apWeaponInfos[weaponType].m_bCanAim = (flags >> 6) & 1;
ms_apWeaponInfos[weaponType].m_bCanAimWithArm = flags >> 7; ms_apWeaponInfos[weaponType].m_bCanAimWithArm = (flags >> 7) & 1;
ms_apWeaponInfos[weaponType].m_b1stPerson = flags >> 8; ms_apWeaponInfos[weaponType].m_b1stPerson = (flags >> 8) & 1;
ms_apWeaponInfos[weaponType].m_bHeavy = flags >> 9; ms_apWeaponInfos[weaponType].m_bHeavy = (flags >> 9) & 1;
ms_apWeaponInfos[weaponType].m_bThrow = flags >> 10; ms_apWeaponInfos[weaponType].m_bThrow = (flags >> 10) & 1;
ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = flags >> 11; ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = (flags >> 11) & 1;
ms_apWeaponInfos[weaponType].m_bUse2nd = flags >> 12; ms_apWeaponInfos[weaponType].m_bUse2nd = (flags >> 12) & 1;
ms_apWeaponInfos[weaponType].m_bGround2nd = flags >> 13; ms_apWeaponInfos[weaponType].m_bGround2nd = (flags >> 13) & 1;
ms_apWeaponInfos[weaponType].m_bFinish3rd = flags >> 14; ms_apWeaponInfos[weaponType].m_bFinish3rd = (flags >> 14) & 1;
ms_apWeaponInfos[weaponType].m_bReload = flags >> 15; ms_apWeaponInfos[weaponType].m_bReload = (flags >> 15) & 1;
ms_apWeaponInfos[weaponType].m_bFightMode = flags >> 16; ms_apWeaponInfos[weaponType].m_bFightMode = (flags >> 16) & 1;
ms_apWeaponInfos[weaponType].m_bCrouchFire = flags >> 17; ms_apWeaponInfos[weaponType].m_bCrouchFire = (flags >> 17) & 1;
ms_apWeaponInfos[weaponType].m_bCop3rd = flags >> 18; ms_apWeaponInfos[weaponType].m_bCop3rd = (flags >> 18) & 1;
ms_apWeaponInfos[weaponType].m_bGround3rd = flags >> 19; ms_apWeaponInfos[weaponType].m_bGround3rd = (flags >> 19) & 1;
ms_apWeaponInfos[weaponType].m_bPartialAttack = flags >> 20; ms_apWeaponInfos[weaponType].m_bPartialAttack = (flags >> 20) & 1;
ms_apWeaponInfos[weaponType].m_bAnimDetonate = flags >> 21; ms_apWeaponInfos[weaponType].m_bAnimDetonate = (flags >> 21) & 1;
ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot; ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot;