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

This commit is contained in:
GaryOderNichts 2020-12-25 18:34:43 +01:00
commit 7e860c5c53
296 changed files with 44707 additions and 33841 deletions

View File

@ -1,54 +0,0 @@
version: 1.0.{build}
image: Visual Studio 2019
configuration:
- Debug
- Release
platform:
- win-x86-librw_d3d9-mss
- win-x86-librw_gl3_glfw-mss
environment:
APPVEYOR_SAVE_CACHE_ON_ERROR: true
GLEW_VER: "2.1.0"
GLFW_VER: "3.3.2"
GLEW_BASE: glew-%GLEW_VER%
GLFW_BASE: glfw-%GLFW_VER%.bin.WIN32
GLEW_FILE: "%GLEW_BASE%-win32.zip"
GLFW_FILE: "%GLFW_BASE%.zip"
GLEW_URL: https://github.com/nigels-com/glew/releases/download/%GLEW_BASE%/%GLEW_FILE%
GLFW_URL: https://github.com/glfw/glfw/releases/download/%GLFW_VER%/%GLFW_FILE%
install:
- IF [%PLATFORM%] == [win-x86-librw_gl3_glfw-mss] IF NOT EXIST %GLEW_FILE% appveyor DownloadFile %GLEW_URL% -FileName "%APPVEYOR_BUILD_FOLDER%/%GLEW_FILE%"
- IF [%PLATFORM%] == [win-x86-librw_gl3_glfw-mss] 7z x "%APPVEYOR_BUILD_FOLDER%/%GLEW_FILE%"
- IF [%PLATFORM%] == [win-x86-librw_gl3_glfw-mss] IF NOT EXIST %GLFW_FILE% appveyor DownloadFile %GLFW_URL% -FileName "%APPVEYOR_BUILD_FOLDER%/%GLFW_FILE%"
- IF [%PLATFORM%] == [win-x86-librw_gl3_glfw-mss] 7z x "%APPVEYOR_BUILD_FOLDER%/%GLFW_FILE%"
- cmd: >-
git submodule update --init --recursive
premake5 vs2019 --with-librw --glewdir=%APPVEYOR_BUILD_FOLDER%/%GLEW_BASE% --glfwdir32=%APPVEYOR_BUILD_FOLDER%/%GLFW_BASE%
build:
project: build/re3.sln
verbosity: minimal
after_build:
- 7z a "re3_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip" bin/%PLATFORM%/%CONFIGURATION%/re3.exe bin/%PLATFORM%/%CONFIGURATION%/re3.pdb
artifacts:
- path: "re3_%configuration%_%platform%_%APPVEYOR_BUILD_VERSION%.zip"
name: re3
deploy:
- provider: BinTray
username: shfil119
api_key:
secure: xWnYDfNWM87iPoBFbz6L1XAduxijJRWSpQLhMDOjznmzbMCsORtdx2tmWmFLTwf6
subject: gtamodding
repo: re3
package: "%configuration%_%platform%"
version: "%APPVEYOR_BUILD_VERSION%"
artifact: re3
publish: true
on:
branch: master
APPVEYOR_REPO_TAG: false
cache:
- "%GLEW_FILE%"
- "%GLFW_FILE%"

28
.clang-format Normal file
View File

@ -0,0 +1,28 @@
---
AllowShortBlocksOnASingleLine: 'true'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortIfStatementsOnASingleLine: 'true'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterReturnType: TopLevel
AccessModifierOffset: -8
BreakBeforeBraces: Linux
ColumnLimit: 160
IndentCaseLabels: 'false'
IndentWidth: '8'
Language: Cpp
PointerAlignment: Right
SpaceAfterCStyleCast: 'false'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeCtorInitializerColon: 'true'
SpaceBeforeInheritanceColon: 'true'
SpaceBeforeParens: Never
SpaceInEmptyParentheses: 'false'
SpacesInAngles: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
TabWidth: '8'
UseTab: ForIndentation
...

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

44
CMakeLists.txt Normal file
View File

@ -0,0 +1,44 @@
cmake_minimum_required(VERSION 3.8)
project(re3 C CXX)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if(WIN32)
set(RE3_AUDIOS "NULL" "OAL" "MSS")
else()
set(RE3_AUDIOS "NULL" "OAL")
endif()
set(RE3_AUDIO "OAL" CACHE STRING "Audio")
set_property(CACHE RE3_AUDIO PROPERTY STRINGS ${RE3_AUDIOS})
message(STATUS "RE3_AUDIO = ${RE3_AUDIO} (choices=${RE3_AUDIOS})")
set("RE3_AUDIO_${RE3_AUDIO}" ON)
if(NOT RE3_AUDIO IN_LIST RE3_AUDIOS)
message(FATAL_ERROR "Illegal RE3_AUDIO=${RE3_AUDIO}")
endif()
if(RE3_INSTALL)
include(GNUInstallDirs)
set(RE3_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/re3")
endif()
add_subdirectory("vendor/librw")
add_subdirectory(src)
if(RE3_INSTALL)
include(CMakePackageConfigHelpers)
configure_package_config_file(re3-config.cmake.in re3-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}"
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/re3-config.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(
EXPORT re3-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
include(CMakeCPack.cmake)
endif()

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

147
README.md
View File

@ -1,10 +1,6 @@
# re3 # re3
[![Build status](https://ci.appveyor.com/api/projects/status/hyiwgegks122h8jg/branch/master?svg=true)](https://ci.appveyor.com/project/aap/re3/branch/master) [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FGTAmodding%2Fre3%2Fbadge%3Fref%3Dmaster&style=flat)](https://actions-badge.atrox.dev/GTAmodding/re3/goto?ref=master)
<a href="https://discord.gg/jYpXxTm"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a> <a href="https://discord.gg/aKYAwCx92H"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a>
| Platform | Debug | Release |
|------------------|-------------|-------------|
| Windows Direct3D9 | [![Download](https://api.bintray.com/packages/gtamodding/re3/Debug_win-x86-librw_d3d9-mss/images/download.svg)](https://bintray.com/gtamodding/re3/Debug_win-x86-librw_d3d9-mss/_latestVersion) | [![Download](https://api.bintray.com/packages/gtamodding/re3/Release_win-x86-librw_d3d9-mss/images/download.svg)](https://bintray.com/gtamodding/re3/Release_win-x86-librw_d3d9-mss/_latestVersion) |
| Windows OpenGL3.3 | [![Download](https://api.bintray.com/packages/gtamodding/re3/Debug_win-x86-librw_gl3_glfw-mss/images/download.svg)](https://bintray.com/gtamodding/re3/Debug_win-x86-librw_gl3_glfw-mss/_latestVersion) | [![Download](https://api.bintray.com/packages/gtamodding/re3/Release_win-x86-librw_gl3_glfw-mss/images/download.svg)](https://bintray.com/gtamodding/re3/Release_win-x86-librw_gl3_glfw-mss/_latestVersion) |
## Intro ## Intro
@ -21,133 +17,38 @@ such that we have a working game at all times.
## Preparing the environment for building ## Preparing the environment for building
- Clone the repo. You may want to point GTA_III_RE_DIR environment variable to GTA3 root folder if you want executable to be moved there via post-build script.
- Run `git submodule init` and `git submodule update`.
- Point GTA_III_RE_DIR environment variable to GTA3 root folder.
- Run premake
- On Windows: one of the `premake-vsXXXX.cmd` variants on root folder
- On Linux: proceed to [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux).
- There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/master/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across.
- **If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version)
- For Linux, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux)
- For FreeBSD, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD)
- For Windows, assuming you have Visual Studio:
- Clone the repo using the argument `--recursive`.
- Run one of the `premake-vsXXXX.cmd` variants on root folder.
- Open the project via Visual Studio
**If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version)
There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/master/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across.
> :information_source: **If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows). > :information_source: **If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows).
> :information_source: **Did you notice librw?** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. > :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:
``` ```
CCullZone - only mobile stuff CMemoryHeap - only on PS2
CCullZones - only mobile stuff NameGrid.cpp - only on mobile (a player name grid, either a very early player name code ala GTA1 or a multiplayer leftover)
PedDebug.cpp - only on mobile (debug code)
HandlingMgr.cpp - debug functions from mobile
CVehicle::ProcessBikeWheel - early bike code (only on mobile)
CAutomobile::DebugCode - debug function from mobile
CBoat::DebugCode - debug function from mobile
CBoat::ModifyHandlingValue - debug function from mobile
CBoat::DisplayHandlingData - debug function from mobile
TexturePools - only on PC (slight RW modification that we don't actually need)
``` ```
### 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

28
cmake/FindMPG123.cmake Normal file
View File

@ -0,0 +1,28 @@
# - Find mpg123
# Find the native mpg123 includes and library
#
# MPG123_INCLUDE_DIR - where to find mpg123.h
# MPG123_LIBRARIES - List of libraries when using mpg123.
# MPG123_FOUND - True if mpg123 found.
IF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
# Already in cache, be silent
SET(MPG123_FIND_QUIETLY TRUE)
ENDIF(MPG123_INCLUDE_DIR AND MPG123_LIBRARIES)
FIND_PATH(MPG123_INCLUDE_DIR mpg123.h
PATHS "${MPG123_DIR}"
PATH_SUFFIXES include
)
FIND_LIBRARY(MPG123_LIBRARIES NAMES mpg123 mpg123-0
PATHS "${MPG123_DIR}"
PATH_SUFFIXES lib
)
# MARK_AS_ADVANCED(MPG123_LIBRARIES MPG123_INCLUDE_DIR)
# handle the QUIETLY and REQUIRED arguments and set MPG123_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MPG123 DEFAULT_MSG MPG123_LIBRARIES MPG123_INCLUDE_DIR)

67
cmake/FindSndFile.cmake Normal file
View File

@ -0,0 +1,67 @@
# Found on http://hg.kvats.net
#
# - Try to find libsndfile
#
# Once done this will define
#
# SNDFILE_FOUND - system has libsndfile
# SNDFILE_INCLUDE_DIRS - the libsndfile include directory
# SNDFILE_LIBRARIES - Link these to use libsndfile
#
# Copyright (C) 2006 Wengo
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS)
# in cache already
set(SNDFILE_FOUND TRUE)
else (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS)
find_path(SNDFILE_INCLUDE_DIR
NAMES
sndfile.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(SNDFILE_LIBRARY
NAMES
sndfile
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(SNDFILE_INCLUDE_DIRS
${SNDFILE_INCLUDE_DIR}
)
set(SNDFILE_LIBRARIES
${SNDFILE_LIBRARY}
)
if (SNDFILE_INCLUDE_DIRS AND SNDFILE_LIBRARIES)
set(SNDFILE_FOUND TRUE)
endif (SNDFILE_INCLUDE_DIRS AND SNDFILE_LIBRARIES)
if (SNDFILE_FOUND)
if (NOT SndFile_FIND_QUIETLY)
message(STATUS "Found libsndfile: ${SNDFILE_LIBRARIES}")
endif (NOT SndFile_FIND_QUIETLY)
else (SNDFILE_FOUND)
if (SndFile_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libsndfile")
endif (SndFile_FIND_REQUIRED)
endif (SNDFILE_FOUND)
# show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view
mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)
endif (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,199 @@
# Windows - DINPUT
8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,
4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,
00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,
8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,
79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,
4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,
d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,
4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,
10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,
4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows,
0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows,
10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows,
63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,
341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,
c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,
100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows,
4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,
4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,
# OS X
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,
8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,
83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,
5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,
79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,
2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,
0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,
5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,
4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,
5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,
81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,
bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,
03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
# Linux
050000004c0500006802000000000000,Sony PLAYSTATION(R)3 Controller,platform:Linux,a:b14,b:b13,x:b15,y:b12,back:b0,guide:b16,start:b3,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpdown:b6,dpleft:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a12,righttrigger:a13,
03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,
030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,
030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,
0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,
030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,
030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,
05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,
03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,
030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,
030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7
03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
03000000f0250000c283000010010000,Goodbetterbest Ltd PC USB Controller,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7
0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,
03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,
03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux,
03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,
030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,
030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,
030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,
05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,
030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,
030000000d0f00006700000001010000,HORIPAD ONE,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,
03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,
05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
06000000adde0000efbe000002010000,Hidromancer Game Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,platform:Linux,a:b12,b:b10,x:b13,y:b11,back:b4,start:b5,leftstick:b14,rightstick:b15,leftshoulder:b9,rightshoulder:b8,dpup:b0,dpdown:b2,dpleft:b3,dpright:b1,leftx:a1,lefty:a0,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,
03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,
03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,
030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux,
030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,
03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,
050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,
030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
030000004c050000cc09000011810000,Sony Interactive Entertainment Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,
050000004c050000cc09000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,
050000004c0500006802000000810000,PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,
05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
030000005e040000a102000000010000,Xbox 360 Wireless Receiver,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpdown:b14,dpleft:b11,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,
050000004c050000cc09000001000000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
03000000bc2000006412000011010000,BETOP CONTROLLER,a:b2,b:b1,y:b0,x:b3,start:b9,guide:b30,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
05000000c82d00000161000000010000,8Bitdo SN30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
03000000380700008532000010010000,MadCatz Madcatz Fightpad,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:b5,righttrigger:b7,
030000000d0f0000ee00000011010000,HORI CO.,LTD. HORIPAD mini4,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
030000000d0f0000c100000011010000,HORI CO.,LTD. HORIPAD S,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
03000000ad1b000003f5000033050000,Hori Fighting Stick VX,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,-leftx:h0.8,+leftx:h0.2,-lefty:h0.1,+lefty:h0.4,lefttrigger:b6,righttrigger:b7,
03000000c82d00000260000011010000,8Bitdo SF30 Pro 8BitDo SN30 Pro+,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:b14,dpdown:b15,dpleft:b16,dpright:b17,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,

Binary file not shown.

View File

@ -19,6 +19,11 @@ newoption {
default = "vendor/glfw-3.3.2.bin.WIN32", default = "vendor/glfw-3.3.2.bin.WIN32",
} }
newoption {
trigger = "with-asan",
description = "Build with address sanitizer"
}
newoption { newoption {
trigger = "with-librw", trigger = "with-librw",
description = "Build and use librw from this solution" description = "Build and use librw from this solution"
@ -60,6 +65,11 @@ workspace "re3"
symbols "Full" symbols "Full"
staticruntime "off" staticruntime "off"
if _OPTIONS["with-asan"] then
buildoptions { "-fsanitize=address -g3 -fno-omit-frame-pointer" }
linkoptions { "-fsanitize=address" }
end
filter { "system:windows" } filter { "system:windows" }
platforms { platforms {
"win-x86-RW33_d3d8-mss", "win-x86-RW33_d3d8-mss",
@ -82,7 +92,16 @@ workspace "re3"
filter { "system:bsd" } filter { "system:bsd" }
platforms { platforms {
"bsd-amd64-librw_gl3_glfw-oal" "bsd-x86-librw_gl3_glfw-oal",
"bsd-amd64-librw_gl3_glfw-oal",
"bsd-arm-librw_gl3_glfw-oal",
"bsd-arm64-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"
@ -101,15 +120,26 @@ workspace "re3"
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"
floatingpoint "Fast"
filter { "platforms:*amd64*" } filter { "platforms:*amd64*" }
architecture "amd64" architecture "amd64"
floatingpoint "Fast"
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
@ -159,10 +189,32 @@ project "librw"
files { path.join(Librw, "src/*.*") } files { path.join(Librw, "src/*.*") }
files { path.join(Librw, "src/*/*.*") } files { path.join(Librw, "src/*/*.*") }
filter { "platforms:*x86*" }
architecture "x86"
floatingpoint "Fast"
filter { "platforms:*amd64*" }
architecture "amd64"
floatingpoint "Fast"
filter "platforms:win*"
staticruntime "on"
buildoptions { "/Zc:sizedDealloc-" }
filter "platforms:bsd*" filter "platforms:bsd*"
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:*gl3_glfw*"
staticruntime "off"
filter "platforms:*RW33*" filter "platforms:*RW33*"
flags { "ExcludeFromBuild" } flags { "ExcludeFromBuild" }
filter {} filter {}
@ -182,6 +234,8 @@ project "re3"
files { addSrcFiles("src/audio") } files { addSrcFiles("src/audio") }
files { addSrcFiles("src/audio/eax") } files { addSrcFiles("src/audio/eax") }
files { addSrcFiles("src/audio/oal") } files { addSrcFiles("src/audio/oal") }
files { addSrcFiles("src/buildings") }
files { addSrcFiles("src/collision") }
files { addSrcFiles("src/control") } files { addSrcFiles("src/control") }
files { addSrcFiles("src/core") } files { addSrcFiles("src/core") }
files { addSrcFiles("src/entities") } files { addSrcFiles("src/entities") }
@ -204,6 +258,8 @@ project "re3"
includedirs { "src/audio" } includedirs { "src/audio" }
includedirs { "src/audio/eax" } includedirs { "src/audio/eax" }
includedirs { "src/audio/oal" } includedirs { "src/audio/oal" }
includedirs { "src/buildings" }
includedirs { "src/collision" }
includedirs { "src/control" } includedirs { "src/control" }
includedirs { "src/core" } includedirs { "src/core" }
includedirs { "src/entities" } includedirs { "src/entities" }
@ -252,9 +308,17 @@ project "re3"
filter "platforms:win*" filter "platforms:win*"
files { addSrcFiles("src/skel/win") } files { addSrcFiles("src/skel/win") }
includedirs { "src/skel/win" } includedirs { "src/skel/win" }
buildoptions { "/Zc:sizedDealloc-" }
linkoptions "/SAFESEH:NO" linkoptions "/SAFESEH:NO"
characterset ("MBCS") characterset ("MBCS")
targetextension ".exe" targetextension ".exe"
if(_OPTIONS["with-librw"]) then
-- external librw is dynamic
staticruntime "on"
end
filter "platforms:win*glfw*"
staticruntime "off"
filter "platforms:win*oal" filter "platforms:win*oal"
includedirs { "vendor/openal-soft/include" } includedirs { "vendor/openal-soft/include" }
@ -277,6 +341,11 @@ project "re3"
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" }
@ -285,7 +354,6 @@ project "re3"
end end
filter "platforms:*RW33*" filter "platforms:*RW33*"
staticruntime "on"
includedirs { "sdk/rwsdk/include/d3d8" } includedirs { "sdk/rwsdk/include/d3d8" }
libdirs { "sdk/rwsdk/lib/d3d8/release" } libdirs { "sdk/rwsdk/lib/d3d8/release" }
links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtcharse" } links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtcharse" }
@ -303,15 +371,13 @@ project "re3"
links { "rw" } links { "rw" }
filter "platforms:*d3d9*" filter "platforms:*d3d9*"
defines { "USE_D3D9" }
links { "d3d9" } links { "d3d9" }
filter "platforms:*x86*d3d*" filter "platforms:*x86*d3d*"
includedirs { "sdk/dx8sdk/include" } includedirs { "sdk/dx8sdk/include" }
libdirs { "sdk/dx8sdk/lib" } libdirs { "sdk/dx8sdk/lib" }
filter "platforms:*amd64*d3d9*"
defines { "USE_D3D9" }
filter "platforms:win-x86*gl3_glfw*" filter "platforms:win-x86*gl3_glfw*"
libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/Win32") } libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/Win32") }
libdirs { path.join(_OPTIONS["glfwdir32"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) } libdirs { path.join(_OPTIONS["glfwdir32"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) }
@ -329,3 +395,11 @@ project "re3"
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" }

113
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,113 @@
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(${RE3_AUDIO} STREQUAL "OAL")
find_package(OpenAL REQUIRED)
find_package(MPG123 REQUIRED)
find_package(SndFile REQUIRED)
endif()
file(GLOB_RECURSE Sources "*.cpp" "*.h")
MACRO(HEADER_DIRECTORIES return_list)
FILE(GLOB_RECURSE new_list *.cpp)
SET(dir_list "animation"
"audio"
"collision"
"control"
"core"
"entities"
"extras"
"fakerw"
"math"
"modelinfo"
"objects"
"peds"
"render"
"rw"
"save"
"skel"
"text"
"vehicles"
"weapons")
FOREACH(file_path ${new_list})
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
SET(dir_list ${dir_list} ${dir_path})
ENDFOREACH()
LIST(REMOVE_DUPLICATES dir_list)
SET(${return_list} ${dir_list})
ENDMACRO()
HEADER_DIRECTORIES(header_list)
include_directories(${header_list})
add_executable(re3 ${Sources})
target_link_libraries(re3 librw)
target_link_libraries(re3 Threads::Threads)
if(${RE3_AUDIO} STREQUAL "OAL")
target_link_libraries(re3 ${OPENAL_LIBRARY})
target_link_libraries(re3 ${MPG123_LIBRARIES})
target_link_libraries(re3 ${SNDFILE_LIBRARIES})
endif()
target_include_directories(re3
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
)
target_compile_definitions(re3
PRIVATE
"$<IF:$<CONFIG:DEBUG>,DEBUG,NDEBUG>"
PUBLIC
"RW_${RE3_PLATFORM}"
)
target_compile_definitions(re3 PRIVATE LIBRW=1 AUDIO_OAL=1)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
target_compile_options(re3
PRIVATE
"-Wall"
)
if (NOT RE3_PLATFORM_PS2)
target_compile_options(re3
PRIVATE
"-Wextra"
"-Wdouble-promotion"
"-Wpedantic"
)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(re3
PUBLIC
/wd4996 /wd4244
)
endif()
set_target_properties(re3
PROPERTIES
C_STANDARD 11
C_EXTENSIONS OFF
C_STANDARD_REQUIRED ON
CXX_STANDARD 11
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
PREFIX ""
)
if(RE3_INSTALL)
target_include_directories(re3
INTERFACE
$<INSTALL_INTERFACE:${RE3_INSTALL_INCLUDEDIR}>
)
install(
TARGETS re3
EXPORT re3-targets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
endif()

View File

@ -5,7 +5,7 @@
#include "RpAnimBlend.h" #include "RpAnimBlend.h"
#include "AnimManager.h" #include "AnimManager.h"
#include "AnimBlendAssociation.h" #include "AnimBlendAssociation.h"
#include "RwHelper.h" #include "MemoryMgr.h"
CAnimBlendAssociation::CAnimBlendAssociation(void) CAnimBlendAssociation::CAnimBlendAssociation(void)
{ {

View File

@ -13,7 +13,7 @@ enum {
ASSOC_MOVEMENT = 0x20, // ??? ASSOC_MOVEMENT = 0x20, // ???
ASSOC_HAS_TRANSLATION = 0x40, ASSOC_HAS_TRANSLATION = 0x40,
ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void) ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void)
ASSOC_FLAG_XPRESS = 0x100, // only used by xpress scratch, see CPed::Chat(void) ASSOC_IDLE = 0x100, // only used by xpress scratch, see CPed::Chat(void)
ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void) ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void)
ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played
ASSOC_FRONTAL = 0x800, // anims that we fall to front ASSOC_FRONTAL = 0x800, // anims that we fall to front

View File

@ -1,7 +1,7 @@
#include "common.h" #include "common.h"
#include "AnimBlendClumpData.h" #include "AnimBlendClumpData.h"
#include "RwHelper.h" #include "MemoryMgr.h"
CAnimBlendClumpData::CAnimBlendClumpData(void) CAnimBlendClumpData::CAnimBlendClumpData(void)

View File

@ -30,15 +30,14 @@ void
CAnimBlendHierarchy::CalcTotalTime(void) CAnimBlendHierarchy::CalcTotalTime(void)
{ {
int i, j; int i, j;
float totalTime = 0.0f; totalLength = 0.0f;
for(i = 0; i < numSequences; i++){ for(i = 0; i < numSequences; i++){
float seqTime = 0.0f; float seqTime = 0.0f;
for(j = 0; j < sequences[i].numFrames; j++) for(j = 0; j < sequences[i].numFrames; j++)
seqTime += sequences[i].GetKeyFrame(j)->deltaTime; seqTime += sequences[i].GetKeyFrame(j)->deltaTime;
totalTime = Max(totalTime, seqTime); totalLength = Max(totalLength, seqTime);
} }
totalLength = totalTime;
} }
void void
@ -53,7 +52,6 @@ CAnimBlendHierarchy::RemoveQuaternionFlips(void)
void void
CAnimBlendHierarchy::RemoveAnimSequences(void) CAnimBlendHierarchy::RemoveAnimSequences(void)
{ {
if(sequences)
delete[] sequences; delete[] sequences;
numSequences = 0; numSequences = 0;
} }
@ -61,6 +59,12 @@ CAnimBlendHierarchy::RemoveAnimSequences(void)
void void
CAnimBlendHierarchy::Uncompress(void) CAnimBlendHierarchy::Uncompress(void)
{ {
#ifdef ANIM_COMPRESSION
int i;
assert(compressed);
for(i = 0; i < numSequences; i++)
sequences[i].Uncompress();
#endif
if(totalLength == 0.0f) if(totalLength == 0.0f)
CalcTotalTime(); CalcTotalTime();
compressed = 0; compressed = 0;
@ -69,6 +73,22 @@ CAnimBlendHierarchy::Uncompress(void)
void void
CAnimBlendHierarchy::RemoveUncompressedData(void) CAnimBlendHierarchy::RemoveUncompressedData(void)
{ {
// useless #ifdef ANIM_COMPRESSION
int i;
assert(!compressed);
for(i = 0; i < numSequences; i++)
sequences[i].RemoveUncompressedData();
#endif
compressed = 1; compressed = 1;
} }
#ifdef USE_CUSTOM_ALLOCATOR
void
CAnimBlendHierarchy::MoveMemory(bool onlyone)
{
int i;
for(i = 0; i < numSequences; i++)
if(sequences[i].MoveMemory() && onlyone)
return;
}
#endif

View File

@ -2,6 +2,10 @@
#include "templates.h" #include "templates.h"
#ifdef MoveMemory
#undef MoveMemory // windows shit
#endif
class CAnimBlendSequence; class CAnimBlendSequence;
// A collection of sequences // A collection of sequences
@ -11,7 +15,7 @@ public:
char name[24]; char name[24];
CAnimBlendSequence *sequences; CAnimBlendSequence *sequences;
int16 numSequences; int16 numSequences;
int16 compressed; // not really used int16 compressed;
float totalLength; float totalLength;
CLink<CAnimBlendHierarchy*> *linkPtr; CLink<CAnimBlendHierarchy*> *linkPtr;
@ -23,6 +27,7 @@ public:
void RemoveAnimSequences(void); void RemoveAnimSequences(void);
void Uncompress(void); void Uncompress(void);
void RemoveUncompressedData(void); void RemoveUncompressedData(void);
void MoveMemory(bool onlyone = false);
}; };
VALIDATE_SIZE(CAnimBlendHierarchy, 0x28); VALIDATE_SIZE(CAnimBlendHierarchy, 0x28);

View File

@ -1,6 +1,7 @@
#include "common.h" #include "common.h"
#include "AnimBlendSequence.h" #include "AnimBlendSequence.h"
#include "MemoryHeap.h"
CAnimBlendSequence::CAnimBlendSequence(void) CAnimBlendSequence::CAnimBlendSequence(void)
{ {
@ -17,6 +18,8 @@ CAnimBlendSequence::~CAnimBlendSequence(void)
{ {
if(keyFrames) if(keyFrames)
RwFree(keyFrames); RwFree(keyFrames);
if(keyFramesCompressed)
RwFree(keyFramesCompressed);
} }
void void
@ -60,3 +63,138 @@ CAnimBlendSequence::RemoveQuaternionFlips(void)
last = frame->rotation; last = frame->rotation;
} }
} }
void
CAnimBlendSequence::Uncompress(void)
{
int i;
if(numFrames == 0)
return;
PUSH_MEMID(MEMID_ANIMATION);
float rotScale = 1.0f/4096.0f;
float timeScale = 1.0f/60.0f;
float transScale = 1.0f/128.0f;
if(type & KF_TRANS){
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans));
KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed;
KeyFrameTrans *kf = (KeyFrameTrans*)newKfs;
for(i = 0; i < numFrames; i++){
kf->rotation.x = ckf->rot[0]*rotScale;
kf->rotation.y = ckf->rot[1]*rotScale;
kf->rotation.z = ckf->rot[2]*rotScale;
kf->rotation.w = ckf->rot[3]*rotScale;
kf->deltaTime = ckf->deltaTime*timeScale;
kf->translation.x = ckf->trans[0]*transScale;
kf->translation.y = ckf->trans[1]*transScale;
kf->translation.z = ckf->trans[2]*transScale;
kf++;
ckf++;
}
keyFrames = newKfs;
}else{
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrame));
KeyFrameCompressed *ckf = (KeyFrameCompressed*)keyFramesCompressed;
KeyFrame *kf = (KeyFrame*)newKfs;
for(i = 0; i < numFrames; i++){
kf->rotation.x = ckf->rot[0]*rotScale;
kf->rotation.y = ckf->rot[1]*rotScale;
kf->rotation.z = ckf->rot[2]*rotScale;
kf->rotation.w = ckf->rot[3]*rotScale;
kf->deltaTime = ckf->deltaTime*timeScale;
kf++;
ckf++;
}
keyFrames = newKfs;
}
REGISTER_MEMPTR(&keyFrames);
RwFree(keyFramesCompressed);
keyFramesCompressed = nil;
POP_MEMID();
}
void
CAnimBlendSequence::CompressKeyframes(void)
{
int i;
if(numFrames == 0)
return;
PUSH_MEMID(MEMID_ANIMATION);
float rotScale = 4096.0f;
float timeScale = 60.0f;
float transScale = 128.0f;
if(type & KF_TRANS){
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed));
KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs;
KeyFrameTrans *kf = (KeyFrameTrans*)keyFrames;
for(i = 0; i < numFrames; i++){
ckf->rot[0] = kf->rotation.x*rotScale;
ckf->rot[1] = kf->rotation.y*rotScale;
ckf->rot[2] = kf->rotation.z*rotScale;
ckf->rot[3] = kf->rotation.w*rotScale;
ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
ckf->trans[0] = kf->translation.x*transScale;
ckf->trans[1] = kf->translation.y*transScale;
ckf->trans[2] = kf->translation.z*transScale;
kf++;
ckf++;
}
keyFramesCompressed = newKfs;
}else{
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameCompressed));
KeyFrameCompressed *ckf = (KeyFrameCompressed*)newKfs;
KeyFrame *kf = (KeyFrame*)keyFrames;
for(i = 0; i < numFrames; i++){
ckf->rot[0] = kf->rotation.x*rotScale;
ckf->rot[1] = kf->rotation.y*rotScale;
ckf->rot[2] = kf->rotation.z*rotScale;
ckf->rot[3] = kf->rotation.w*rotScale;
ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
kf++;
ckf++;
}
keyFramesCompressed = newKfs;
}
REGISTER_MEMPTR(&keyFramesCompressed);
POP_MEMID();
}
void
CAnimBlendSequence::RemoveUncompressedData(void)
{
if(numFrames == 0)
return;
CompressKeyframes();
RwFree(keyFrames);
keyFrames = nil;
}
#ifdef USE_CUSTOM_ALLOCATOR
bool
CAnimBlendSequence::MoveMemory(void)
{
if(keyFrames){
void *newaddr = gMainHeap.MoveMemory(keyFrames);
if(newaddr != keyFrames){
keyFrames = newaddr;
return true;
}
}else if(keyFramesCompressed){
void *newaddr = gMainHeap.MoveMemory(keyFramesCompressed);
if(newaddr != keyFramesCompressed){
keyFramesCompressed = newaddr;
return true;
}
}
return false;
}
#endif

View File

@ -2,6 +2,10 @@
#include "Quaternion.h" #include "Quaternion.h"
#ifdef MoveMemory
#undef MoveMemory // windows shit
#endif
// TODO: put them somewhere else? // TODO: put them somewhere else?
struct KeyFrame { struct KeyFrame {
CQuaternion rotation; CQuaternion rotation;
@ -12,6 +16,15 @@ struct KeyFrameTrans : KeyFrame {
CVector translation; CVector translation;
}; };
struct KeyFrameCompressed {
int16 rot[4]; // 4096
int16 deltaTime; // 60
};
struct KeyFrameTransCompressed : KeyFrameCompressed {
int16 trans[3]; // 128
};
// The sequence of key frames of one animated node // The sequence of key frames of one animated node
class CAnimBlendSequence class CAnimBlendSequence
@ -41,10 +54,10 @@ public:
&((KeyFrame*)keyFrames)[n]; &((KeyFrame*)keyFrames)[n];
} }
bool HasTranslation(void) { return !!(type & KF_TRANS); } bool HasTranslation(void) { return !!(type & KF_TRANS); }
// TODO? these are unused void Uncompress(void);
// void Uncompress(void); void CompressKeyframes(void);
// void CompressKeyframes(void); void RemoveUncompressedData(void);
// void RemoveUncompressedData(void); bool MoveMemory(void);
#ifdef PED_SKIN #ifdef PED_SKIN
void SetBoneTag(int tag) { boneTag = tag; } void SetBoneTag(int tag) { boneTag = tag; }

View File

@ -57,6 +57,9 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_HIT_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FLOOR_HIT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_FLOOR_HIT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
#if GTA_VERSION <= GTA3_PS2_160
{ ANIM_HIT_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
#endif
{ ANIM_HIT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_CHEST, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_CHEST, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@ -78,6 +81,8 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, { ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, { ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK }, { ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
#ifdef PC_PLAYER_CONTROLS
// maybe wrong define, but unused anyway
{ ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
@ -85,6 +90,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
#endif
{ ANIM_FIGHT_IDLE, ASSOC_REPEAT }, { ANIM_FIGHT_IDLE, ASSOC_REPEAT },
{ ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@ -176,7 +182,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
{ ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG_XPRESS }, { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE },
{ ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@ -193,6 +199,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },
}; };
#ifdef PC_PLAYER_CONTROLS
AnimAssocDesc aStdAnimDescsSide[] = { AnimAssocDesc aStdAnimDescsSide[] = {
{ ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION }, { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION },
{ ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION }, { ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK | ASSOC_HAS_X_TRANSLATION },
@ -200,6 +207,7 @@ AnimAssocDesc aStdAnimDescsSide[] = {
{ ANIM_IDLE_STANCE, ASSOC_REPEAT }, { ANIM_IDLE_STANCE, ASSOC_REPEAT },
{ ANIM_WALK_START, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, { ANIM_WALK_START, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },
}; };
#endif
char const *aStdAnimations[] = { char const *aStdAnimations[] = {
"walk_civi", "walk_civi",
"run_civi", "run_civi",
@ -239,6 +247,9 @@ char const *aStdAnimations[] = {
"HIT_back", "HIT_back",
"HIT_R", "HIT_R",
"FLOOR_hit", "FLOOR_hit",
#if GTA_VERSION <= GTA3_PS2_160
"HIT_body",
#endif
"HIT_bodyblow", "HIT_bodyblow",
"HIT_chest", "HIT_chest",
"HIT_head", "HIT_head",
@ -260,6 +271,8 @@ char const *aStdAnimations[] = {
"bomber", "bomber",
"WEAPON_hgun_rload", "WEAPON_hgun_rload",
"WEAPON_AK_rload", "WEAPON_AK_rload",
#ifdef PC_PLAYER_CONTROLS
// maybe wrong define, but unused anyway
"FPS_PUNCH", "FPS_PUNCH",
"FPS_BAT", "FPS_BAT",
"FPS_UZI", "FPS_UZI",
@ -267,6 +280,7 @@ char const *aStdAnimations[] = {
"FPS_AK", "FPS_AK",
"FPS_M16", "FPS_M16",
"FPS_ROCKET", "FPS_ROCKET",
#endif
"FIGHTIDLE", "FIGHTIDLE",
"FIGHT2IDLE", "FIGHT2IDLE",
"FIGHTsh_F", "FIGHTsh_F",
@ -488,6 +502,7 @@ char const *aPanicChunkyAnimations[] = {
"woman_runpanic", "woman_runpanic",
"idle_stance", "idle_stance",
}; };
#ifdef PC_PLAYER_CONTROLS
char const *aPlayerStrafeBackAnimations[] = { char const *aPlayerStrafeBackAnimations[] = {
"walk_player_back", "walk_player_back",
"run_player_back", "run_player_back",
@ -530,6 +545,7 @@ char const *aRocketStrafeRightAnimations[] = {
"idle_rocket", "idle_rocket",
"walkst_rocket_right", "walkst_rocket_right",
}; };
#endif
#define awc(a) ARRAY_SIZE(a), a #define awc(a) ARRAY_SIZE(a), a
const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = { const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = {
@ -552,12 +568,14 @@ const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_
{ "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs }, { "oldwoman", "ped", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs },
{ "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs }, { "fatwoman", "ped", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs },
{ "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs }, { "panicchunky", "ped", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs },
#ifdef PC_PLAYER_CONTROLS
{ "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs }, { "playerback", "ped", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs },
{ "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide }, { "playerleft", "ped", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide },
{ "playerright", "ped", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide }, { "playerright", "ped", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide },
{ "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs }, { "rocketback", "ped", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs },
{ "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide }, { "rocketleft", "ped", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide },
{ "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide }, { "rocketright", "ped", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide },
#endif
}; };
#undef awc #undef awc
@ -795,7 +813,7 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
#ifdef BIGENDIAN #ifdef BIGENDIAN
anpk.size = BSWAP32(anpk.size); anpk.size = BSWAP32(anpk.size);
#endif #endif
if(strncmp(anpk.ident, "ANLF", 4) == 0){ if(!CGeneral::faststrncmp(anpk.ident, "ANLF", 4)) {
ROUNDSIZE(anpk.size); ROUNDSIZE(anpk.size);
CFileMgr::Read(fd, buf, anpk.size); CFileMgr::Read(fd, buf, anpk.size);
#ifndef BIGENDIAN #ifndef BIGENDIAN
@ -803,7 +821,7 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
#else #else
numANPK = BSWAP32(*(int*)buf); numANPK = BSWAP32(*(int*)buf);
#endif #endif
}else if(strncmp(anpk.ident, "ANPK", 4) == 0){ } else if(!CGeneral::faststrncmp(anpk.ident, "ANPK", 4)) {
CFileMgr::Seek(fd, -8, 1); CFileMgr::Seek(fd, -8, 1);
numANPK = 1; numANPK = 1;
} }
@ -881,6 +899,7 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
#else #else
int numFrames = BSWAP32(*(int*)(buf+28)); int numFrames = BSWAP32(*(int*)(buf+28));
#endif #endif
seq->SetName(buf);
#ifdef PED_SKIN #ifdef PED_SKIN
if(anim.size == 44) if(anim.size == 44)
#ifndef BIGENDIAN #ifndef BIGENDIAN
@ -889,84 +908,52 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
seq->SetBoneTag(BSWAP32(*(int*)(buf+40))); seq->SetBoneTag(BSWAP32(*(int*)(buf+40)));
#endif #endif
#endif #endif
seq->SetName(buf);
if(numFrames == 0) if(numFrames == 0)
continue; continue;
bool hasScale = false;
bool hasTranslation = false;
CFileMgr::Read(fd, (char*)&info, sizeof(info)); CFileMgr::Read(fd, (char*)&info, sizeof(info));
#ifdef BIGENDIAN if(!CGeneral::faststrncmp(info.ident, "KRTS", 4)) {
info.size = BSWAP32(info.size); hasScale = true;
#endif seq->SetNumFrames(numFrames, true);
if(strncmp(info.ident, "KR00", 4) == 0){ }else if(!CGeneral::faststrncmp(info.ident, "KRT0", 4)) {
hasTranslation = true;
seq->SetNumFrames(numFrames, true);
}else if(!CGeneral::faststrncmp(info.ident, "KR00", 4)){
seq->SetNumFrames(numFrames, false); seq->SetNumFrames(numFrames, false);
KeyFrame *kf = seq->GetKeyFrame(0);
for(l = 0; l < numFrames; l++, kf++){
CFileMgr::Read(fd, buf, 0x14);
#ifndef BIGENDIAN
kf->rotation.x = -fbuf[0];
kf->rotation.y = -fbuf[1];
kf->rotation.z = -fbuf[2];
kf->rotation.w = fbuf[3];
kf->deltaTime = fbuf[4]; // absolute time here
#else
kf->rotation.x = -FLOATSWAP32(fbuf[0]);
kf->rotation.y = -FLOATSWAP32(fbuf[1]);
kf->rotation.z = -FLOATSWAP32(fbuf[2]);
kf->rotation.w = FLOATSWAP32(fbuf[3]);
kf->deltaTime = FLOATSWAP32(fbuf[4]); // absolute time here
#endif
} }
}else if(strncmp(info.ident, "KRT0", 4) == 0){
seq->SetNumFrames(numFrames, true); for(l = 0; l < numFrames; l++){
KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0); if(hasScale){
for(l = 0; l < numFrames; l++, kf++){
CFileMgr::Read(fd, buf, 0x20);
#ifndef BIGENDIAN
kf->rotation.x = -fbuf[0];
kf->rotation.y = -fbuf[1];
kf->rotation.z = -fbuf[2];
kf->rotation.w = fbuf[3];
kf->translation.x = fbuf[4];
kf->translation.y = fbuf[5];
kf->translation.z = fbuf[6];
kf->deltaTime = fbuf[7]; // absolute time here
#else
kf->rotation.x = -FLOATSWAP32(fbuf[0]);
kf->rotation.y = -FLOATSWAP32(fbuf[1]);
kf->rotation.z = -FLOATSWAP32(fbuf[2]);
kf->rotation.w = FLOATSWAP32(fbuf[3]);
kf->translation.x = FLOATSWAP32(fbuf[4]);
kf->translation.y = FLOATSWAP32(fbuf[5]);
kf->translation.z = FLOATSWAP32(fbuf[6]);
kf->deltaTime = FLOATSWAP32(fbuf[7]); // absolute time here
#endif
}
}else if(strncmp(info.ident, "KRTS", 4) == 0){
seq->SetNumFrames(numFrames, true);
KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
for(l = 0; l < numFrames; l++, kf++){
CFileMgr::Read(fd, buf, 0x2C); CFileMgr::Read(fd, buf, 0x2C);
#ifndef BIGENDIAN CQuaternion rot(FLOATSWAP32(fbuf[0]), FLOATSWAP32(fbuf[1]), FLOATSWAP32(fbuf[2]), FLOATSWAP32(fbuf[3]));
kf->rotation.x = -fbuf[0]; rot.Invert();
kf->rotation.y = -fbuf[1]; CVector trans(FLOATSWAP32(fbuf[4]), FLOATSWAP32(fbuf[5]), FLOATSWAP32(fbuf[6]));
kf->rotation.z = -fbuf[2];
kf->rotation.w = fbuf[3]; KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l);
kf->translation.x = fbuf[4]; kf->rotation = rot;
kf->translation.y = fbuf[5]; kf->translation = trans;
kf->translation.z = fbuf[6];
// scaling ignored
kf->deltaTime = fbuf[10]; // absolute time here
#else
kf->rotation.x = -FLOATSWAP32(fbuf[0]);
kf->rotation.y = -FLOATSWAP32(fbuf[1]);
kf->rotation.z = -FLOATSWAP32(fbuf[2]);
kf->rotation.w = FLOATSWAP32(fbuf[3]);
kf->translation.x = FLOATSWAP32(fbuf[4]);
kf->translation.y = FLOATSWAP32(fbuf[5]);
kf->translation.z = FLOATSWAP32(fbuf[6]);
// scaling ignored // scaling ignored
kf->deltaTime = FLOATSWAP32(fbuf[10]); // absolute time here kf->deltaTime = FLOATSWAP32(fbuf[10]); // absolute time here
#endif }else if(hasTranslation){
CFileMgr::Read(fd, buf, 0x20);
CQuaternion rot(FLOATSWAP32(fbuf[0]), FLOATSWAP32(fbuf[1]), FLOATSWAP32(fbuf[2]), FLOATSWAP32(fbuf[3]));
rot.Invert();
CVector trans(FLOATSWAP32(fbuf[4]), FLOATSWAP32(fbuf[5]), FLOATSWAP32(fbuf[6]));
KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l);
kf->rotation = rot;
kf->translation = trans;
kf->deltaTime = FLOATSWAP32(fbuf[7]); // absolute time here
}else{
CFileMgr::Read(fd, buf, 0x14);
CQuaternion rot(FLOATSWAP32(fbuf[0]), FLOATSWAP32(fbuf[1]), FLOATSWAP32(fbuf[2]), FLOATSWAP32(fbuf[3]));
rot.Invert();
KeyFrame *kf = (KeyFrame*)seq->GetKeyFrame(l);
kf->rotation = rot;
kf->deltaTime = FLOATSWAP32(fbuf[4]); // absolute time here
} }
} }

View File

@ -24,12 +24,14 @@ enum AssocGroupId
ASSOCGRP_OLDWOMAN, ASSOCGRP_OLDWOMAN,
ASSOCGRP_FATWOMAN, ASSOCGRP_FATWOMAN,
ASSOCGRP_PANICCHUNKY, ASSOCGRP_PANICCHUNKY,
#ifdef PC_PLAYER_CONTROLS
ASSOCGRP_PLAYERBACK, ASSOCGRP_PLAYERBACK,
ASSOCGRP_PLAYERLEFT, ASSOCGRP_PLAYERLEFT,
ASSOCGRP_PLAYERRIGHT, ASSOCGRP_PLAYERRIGHT,
ASSOCGRP_ROCKETBACK, ASSOCGRP_ROCKETBACK,
ASSOCGRP_ROCKETLEFT, ASSOCGRP_ROCKETLEFT,
ASSOCGRP_ROCKETRIGHT, ASSOCGRP_ROCKETRIGHT,
#endif
NUM_ANIM_ASSOC_GROUPS NUM_ANIM_ASSOC_GROUPS
}; };

View File

@ -40,6 +40,9 @@ enum AnimationId
ANIM_HIT_BACK, ANIM_HIT_BACK,
ANIM_HIT_RIGHT, ANIM_HIT_RIGHT,
ANIM_FLOOR_HIT, ANIM_FLOOR_HIT,
#if GTA_VERSION <= GTA3_PS2_160
ANIM_HIT_BODY,
#endif
ANIM_HIT_BODYBLOW, ANIM_HIT_BODYBLOW,
ANIM_HIT_CHEST, ANIM_HIT_CHEST,
ANIM_HIT_HEAD, ANIM_HIT_HEAD,
@ -61,6 +64,8 @@ enum AnimationId
ANIM_BOMBER, ANIM_BOMBER,
ANIM_HGUN_RELOAD, ANIM_HGUN_RELOAD,
ANIM_AK_RELOAD, ANIM_AK_RELOAD,
#ifdef PC_PLAYER_CONTROLS
// maybe wrong define, but unused anyway
ANIM_FPS_PUNCH, ANIM_FPS_PUNCH,
ANIM_FPS_BAT, ANIM_FPS_BAT,
ANIM_FPS_UZI, ANIM_FPS_UZI,
@ -68,6 +73,7 @@ enum AnimationId
ANIM_FPS_AK, ANIM_FPS_AK,
ANIM_FPS_M16, ANIM_FPS_M16,
ANIM_FPS_ROCKET, ANIM_FPS_ROCKET,
#endif
ANIM_FIGHT_IDLE, ANIM_FIGHT_IDLE,
ANIM_FIGHT2_IDLE, ANIM_FIGHT2_IDLE,
ANIM_FIGHT_SH_F, ANIM_FIGHT_SH_F,

View File

@ -8,6 +8,7 @@
#include "AnimBlendClumpData.h" #include "AnimBlendClumpData.h"
#include "AnimBlendHierarchy.h" #include "AnimBlendHierarchy.h"
#include "AnimBlendAssociation.h" #include "AnimBlendAssociation.h"
#include "AnimManager.h"
#include "RpAnimBlend.h" #include "RpAnimBlend.h"
#ifdef PED_SKIN #ifdef PED_SKIN
#include "PedModelInfo.h" #include "PedModelInfo.h"
@ -441,7 +442,7 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
next = link->next; next = link->next;
CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link); CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);
if(assoc->UpdateBlend(timeDelta)){ if(assoc->UpdateBlend(timeDelta)){
// CAnimManager::UncompressAnimation(v6->hierarchy) CAnimManager::UncompressAnimation(assoc->hierarchy);
updateData.nodes[i++] = assoc->GetNode(0); updateData.nodes[i++] = assoc->GetNode(0);
if(assoc->flags & ASSOC_MOVEMENT){ if(assoc->flags & ASSOC_MOVEMENT){
totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount; totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;

File diff suppressed because it is too large Load Diff

View File

@ -128,7 +128,7 @@ cAudioManager::CreateEntity(eAudioType type, void *entity)
for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) { for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) {
if (!m_asAudioEntities[i].m_bIsUsed) { if (!m_asAudioEntities[i].m_bIsUsed) {
m_asAudioEntities[i].m_bIsUsed = true; m_asAudioEntities[i].m_bIsUsed = true;
m_asAudioEntities[i].m_nStatus = 0; m_asAudioEntities[i].m_bStatus = false;
m_asAudioEntities[i].m_nType = type; m_asAudioEntities[i].m_nType = type;
m_asAudioEntities[i].m_pEntity = entity; m_asAudioEntities[i].m_pEntity = entity;
m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND; m_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND;
@ -163,11 +163,11 @@ void
cAudioManager::SetEntityStatus(int32 id, uint8 status) cAudioManager::SetEntityStatus(int32 id, uint8 status)
{ {
if (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed) if (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed)
m_asAudioEntities[id].m_nStatus = status; m_asAudioEntities[id].m_bStatus = status;
} }
void void
cAudioManager::PlayOneShot(int32 index, int16 sound, float vol) cAudioManager::PlayOneShot(int32 index, uint16 sound, float vol)
{ {
static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1, static const uint8 OneShotPriority[] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 4, 4, 3, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 3, 2, 2, 2, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -321,8 +321,13 @@ cAudioManager::Get3DProviderName(uint8 id) const
{ {
if (!m_bIsInitialised) if (!m_bIsInitialised)
return nil; return nil;
#ifdef AUDIO_OAL
id = clamp(id, 0, SampleManager.GetNum3DProvidersAvailable() - 1);
#else
// We don't want that either since it will crash the game, but skipping for now
if (id >= SampleManager.GetNum3DProvidersAvailable()) if (id >= SampleManager.GetNum3DProvidersAvailable())
return nil; return nil;
#endif
return SampleManager.Get3DProviderName(id); return SampleManager.Get3DProviderName(id);
} }

View File

@ -46,7 +46,7 @@ public:
eAudioType m_nType; eAudioType m_nType;
void *m_pEntity; void *m_pEntity;
bool m_bIsUsed; bool m_bIsUsed;
uint8 m_nStatus; uint8 m_bStatus;
int16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS]; int16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS];
float m_afVolume[NUM_AUDIOENTITY_EVENTS]; float m_afVolume[NUM_AUDIOENTITY_EVENTS];
uint8 m_AudioEvents; uint8 m_AudioEvents;
@ -132,6 +132,13 @@ public:
bool m_bDistanceCalculated; bool m_bDistanceCalculated;
float m_fDistance; float m_fDistance;
CPed *m_pPed; CPed *m_pPed;
cPedParams()
{
m_pPed = nil;
m_bDistanceCalculated = false;
m_fDistance = 0.0f;
}
}; };
class cVehicleParams class cVehicleParams
@ -332,7 +339,7 @@ public:
int8 GetMissionScriptPoliceAudioPlayingStatus() const; int8 GetMissionScriptPoliceAudioPlayingStatus() const;
uint8 GetNum3DProvidersAvailable() const; uint8 GetNum3DProvidersAvailable() const;
int32 GetPedCommentSfx(CPed *ped, int32 sound); int32 GetPedCommentSfx(CPed *ped, int32 sound);
void GetPhrase(uint32 *phrase, uint32 *prevPhrase, uint32 sample, uint32 maxOffset) const; void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const;
float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, float GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
cTransmission *transmission, float velocityChange); cTransmission *transmission, float velocityChange);
float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile, float GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automobile,
@ -351,7 +358,7 @@ public:
bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; bool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const;
void PlayLoadedMissionAudio(); void PlayLoadedMissionAudio();
void PlayOneShot(int32 index, int16 sound, float vol); void PlayOneShot(int32 index, uint16 sound, float vol);
void PlaySuspectLastSeen(float x, float y, float z); void PlaySuspectLastSeen(float x, float y, float z);
void PlayerJustGotInCar() const; void PlayerJustGotInCar() const;
void PlayerJustLeftCar() const; void PlayerJustLeftCar() const;
@ -362,29 +369,29 @@ public:
void PreTerminateGameSpecificShutdown(); void PreTerminateGameSpecificShutdown();
/// processX - main logic of adding new sounds /// processX - main logic of adding new sounds
void ProcessActiveQueues(); void ProcessActiveQueues();
bool ProcessAirBrakes(cVehicleParams *params); bool ProcessAirBrakes(cVehicleParams& params);
void ProcessAirportScriptObject(uint8 sound); void ProcessAirportScriptObject(uint8 sound);
bool ProcessBoatEngine(cVehicleParams *params); bool ProcessBoatEngine(cVehicleParams& params);
bool ProcessBoatMovingOverWater(cVehicleParams *params); bool ProcessBoatMovingOverWater(cVehicleParams& params);
void ProcessBridge(); void ProcessBridge();
void ProcessBridgeMotor(); void ProcessBridgeMotor();
void ProcessBridgeOneShots(); void ProcessBridgeOneShots();
void ProcessBridgeWarning(); void ProcessBridgeWarning();
bool ProcessCarBombTick(cVehicleParams *params); bool ProcessCarBombTick(cVehicleParams& params);
void ProcessCesna(cVehicleParams *params); void ProcessCesna(cVehicleParams& params);
void ProcessCinemaScriptObject(uint8 sound); void ProcessCinemaScriptObject(uint8 sound);
void ProcessCrane(); void ProcessCrane();
void ProcessDocksScriptObject(uint8 sound); void ProcessDocksScriptObject(uint8 sound);
bool ProcessEngineDamage(cVehicleParams *params); bool ProcessEngineDamage(cVehicleParams& params);
void ProcessEntity(int32 sound); void ProcessEntity(int32 sound);
void ProcessExplosions(int32 explosion); void ProcessExplosions(int32 explosion);
void ProcessFireHydrant(); void ProcessFireHydrant();
void ProcessFires(int32 entity); void ProcessFires(int32 entity);
void ProcessFrontEnd(); void ProcessFrontEnd();
void ProcessGarages(); void ProcessGarages();
bool ProcessHelicopter(cVehicleParams *params); bool ProcessHelicopter(cVehicleParams& params);
void ProcessHomeScriptObject(uint8 sound); void ProcessHomeScriptObject(uint8 sound);
void ProcessJumbo(cVehicleParams *); void ProcessJumbo(cVehicleParams& params);
void ProcessJumboAccel(CPlane *plane); void ProcessJumboAccel(CPlane *plane);
void ProcessJumboDecel(CPlane *plane); void ProcessJumboDecel(CPlane *plane);
void ProcessJumboFlying(); void ProcessJumboFlying();
@ -394,37 +401,37 @@ public:
void ProcessLaunderetteScriptObject(uint8 sound); void ProcessLaunderetteScriptObject(uint8 sound);
void ProcessLoopingScriptObject(uint8 sound); void ProcessLoopingScriptObject(uint8 sound);
void ProcessMissionAudio(); void ProcessMissionAudio();
void ProcessModelCarEngine(cVehicleParams *params); void ProcessModelCarEngine(cVehicleParams& params);
void ProcessOneShotScriptObject(uint8 sound); void ProcessOneShotScriptObject(uint8 sound);
void ProcessPed(CPhysical *ped); void ProcessPed(CPhysical *ped);
void ProcessPedHeadphones(cPedParams *params); void ProcessPedHeadphones(cPedParams &params);
void ProcessPedOneShots(cPedParams *params); void ProcessPedOneShots(cPedParams &params);
void ProcessPhysical(int32 id); void ProcessPhysical(int32 id);
void ProcessPlane(cVehicleParams *params); void ProcessPlane(cVehicleParams& params);
void ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile *automobile); void ProcessPlayersVehicleEngine(cVehicleParams& params, CAutomobile *automobile);
void ProcessPoliceCellBeatingScriptObject(uint8 sound); void ProcessPoliceCellBeatingScriptObject(uint8 sound);
void ProcessPornCinema(uint8 sound); void ProcessPornCinema(uint8 sound);
void ProcessProjectiles(); void ProcessProjectiles();
void ProcessRainOnVehicle(cVehicleParams *params); void ProcessRainOnVehicle(cVehicleParams& params);
void ProcessReverb() const; void ProcessReverb() const;
bool ProcessReverseGear(cVehicleParams *params); bool ProcessReverseGear(cVehicleParams& params);
void ProcessSawMillScriptObject(uint8 sound); void ProcessSawMillScriptObject(uint8 sound);
void ProcessScriptObject(int32 id); void ProcessScriptObject(int32 id);
void ProcessShopScriptObject(uint8 sound); void ProcessShopScriptObject(uint8 sound);
void ProcessSpecial(); void ProcessSpecial();
bool ProcessTrainNoise(cVehicleParams *params); bool ProcessTrainNoise(cVehicleParams& params);
void ProcessVehicle(CVehicle *vehicle); void ProcessVehicle(CVehicle *vehicle);
bool ProcessVehicleDoors(cVehicleParams *params); bool ProcessVehicleDoors(cVehicleParams& params);
void ProcessVehicleEngine(cVehicleParams *params); void ProcessVehicleEngine(cVehicleParams& params);
void ProcessVehicleHorn(cVehicleParams *params); void ProcessVehicleHorn(cVehicleParams& params);
void ProcessVehicleOneShots(cVehicleParams *params); void ProcessVehicleOneShots(cVehicleParams& params);
bool ProcessVehicleReverseWarning(cVehicleParams *params); bool ProcessVehicleReverseWarning(cVehicleParams& params);
bool ProcessVehicleRoadNoise(cVehicleParams *params); bool ProcessVehicleRoadNoise(cVehicleParams& params);
bool ProcessVehicleSirenOrAlarm(cVehicleParams *params); bool ProcessVehicleSirenOrAlarm(cVehicleParams& params);
bool ProcessVehicleSkidding(cVehicleParams *params); bool ProcessVehicleSkidding(cVehicleParams& params);
void ProcessWaterCannon(int32); void ProcessWaterCannon(int32);
void ProcessWeather(int32 id); void ProcessWeather(int32 id);
bool ProcessWetRoadNoise(cVehicleParams *params); bool ProcessWetRoadNoise(cVehicleParams& params);
void ProcessWorkShopScriptObject(uint8 sound); void ProcessWorkShopScriptObject(uint8 sound);
int32 RandomDisplacement(uint32 seed) const; int32 RandomDisplacement(uint32 seed) const;
@ -432,7 +439,7 @@ public:
void ReleaseDigitalHandle() const; void ReleaseDigitalHandle() const;
void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2,
float collisionPower, float intensity2); float collisionPower, float intensity2);
void ReportCrime(int32 crime, const CVector *pos); void ReportCrime(eCrimeType crime, const CVector &pos);
void ResetAudioLogicTimers(uint32 timer); void ResetAudioLogicTimers(uint32 timer);
void ResetPoliceRadio(); void ResetPoliceRadio();
void ResetTimers(uint32 time); void ResetTimers(uint32 time);
@ -440,7 +447,7 @@ public:
void Service(); void Service();
void ServiceCollisions(); void ServiceCollisions();
void ServicePoliceRadio(); void ServicePoliceRadio();
void ServicePoliceRadioChannel(int32 wantedLevel); void ServicePoliceRadioChannel(uint8 wantedLevel);
void ServiceSoundEffects(); void ServiceSoundEffects();
int8 SetCurrent3DProvider(uint8 which); int8 SetCurrent3DProvider(uint8 which);
void SetDynamicAcousticModelingStatus(uint8 status); void SetDynamicAcousticModelingStatus(uint8 status);
@ -462,7 +469,7 @@ public:
bool SetupJumboRumbleSound(uint8 emittingVol); bool SetupJumboRumbleSound(uint8 emittingVol);
bool SetupJumboTaxiSound(uint8 vol); bool SetupJumboTaxiSound(uint8 vol);
bool SetupJumboWhineSound(uint8 emittingVol, uint32 freq); bool SetupJumboWhineSound(uint8 emittingVol, uint32 freq);
void SetupPedComments(cPedParams *params, uint32 sound); void SetupPedComments(cPedParams &params, uint16 sound);
void SetupSuspectLastSeenReport(); void SetupSuspectLastSeenReport();
void Terminate(); void Terminate();

View File

@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
enum eSfxSample : uint32 enum eSfxSample
{ {
SFX_CAR_HORN_JEEP = 0, SFX_CAR_HORN_JEEP = 0,
SFX_CAR_HORN_BMW328, SFX_CAR_HORN_BMW328,

View File

@ -5,8 +5,6 @@
#include "AudioManager.h" #include "AudioManager.h"
#include "AudioScriptObject.h" #include "AudioScriptObject.h"
#include "sampman.h" #include "sampman.h"
#include "Text.h"
#include "crossplatform.h"
cDMAudio DMAudio; cDMAudio DMAudio;
@ -112,28 +110,6 @@ cDMAudio::Get3DProviderName(uint8 id)
return AudioManager.Get3DProviderName(id); return AudioManager.Get3DProviderName(id);
} }
int8 cDMAudio::AutoDetect3DProviders(void)
{
for ( int32 i = 0; i < GetNum3DProvidersAvailable(); i++ )
{
wchar buff[64];
char *name = Get3DProviderName(i);
AsciiToUnicode(name, buff);
char *providername = UnicodeToAscii(buff);
strupr(providername);
#if defined(AUDIO_MSS)
if ( !strcmp(providername, "MILES FAST 2D POSITIONAL AUDIO") )
return i;
#elif defined(AUDIO_OAL)
if ( !strcmp(providername, "OPENAL SOFT") )
return i;
#endif
}
return -1;
}
int8 int8
cDMAudio::GetCurrent3DProviderIndex(void) cDMAudio::GetCurrent3DProviderIndex(void)
{ {
@ -197,7 +173,7 @@ cDMAudio::IsAudioInitialised(void)
void void
cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos) cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos)
{ {
AudioManager.ReportCrime(crime, &pos); AudioManager.ReportCrime(crime, pos);
} }
int32 int32
@ -344,7 +320,7 @@ cDMAudio::SetRadioInCar(uint32 radio)
} }
void void
cDMAudio::SetRadioChannel(int8 radio, int32 pos) cDMAudio::SetRadioChannel(uint8 radio, int32 pos)
{ {
MusicManager.SetRadioChannelByScript(radio, pos); MusicManager.SetRadioChannelByScript(radio, pos);
} }

View File

@ -35,8 +35,6 @@ public:
uint8 GetNum3DProvidersAvailable(void); uint8 GetNum3DProvidersAvailable(void);
char *Get3DProviderName(uint8 id); char *Get3DProviderName(uint8 id);
int8 AutoDetect3DProviders(void);
int8 GetCurrent3DProviderIndex(void); int8 GetCurrent3DProviderIndex(void);
int8 SetCurrent3DProvider(uint8 which); int8 SetCurrent3DProvider(uint8 which);
@ -86,6 +84,6 @@ public:
uint8 GetRadioInCar(void); uint8 GetRadioInCar(void);
void SetRadioInCar(uint32 radio); void SetRadioInCar(uint32 radio);
void SetRadioChannel(int8 radio, int32 pos); void SetRadioChannel(uint8 radio, int32 pos);
}; };
extern cDMAudio DMAudio; extern cDMAudio DMAudio;

View File

@ -83,18 +83,40 @@ cMusicManager::DisplayRadioStationName()
if(m_bPlayerInCar && !m_bPreviousPlayerInCar) if(m_bPlayerInCar && !m_bPreviousPlayerInCar)
pCurrentStation = nil; pCurrentStation = nil;
#ifdef RADIO_SCROLL_TO_PREV_STATION
if(gNumRetunePresses < 0) {
gStreamedSound = m_nCurrentStreamedSound;
if(gStreamedSound == STREAMED_SOUND_CITY_AMBIENT ||
gStreamedSound == STREAMED_SOUND_WATER_AMBIENT) {
gStreamedSound = POLICE_RADIO; // which means OFF
} else if(gStreamedSound > STREAMED_SOUND_RADIO_MP3_PLAYER)
return;
gRetuneCounter = gNumRetunePresses;
pRetune = gStreamedSound;
while(gRetuneCounter < 0) {
if(pRetune == HEAD_RADIO) {
pRetune = RADIO_OFF;
} else if(pRetune == RADIO_OFF || pRetune == POLICE_RADIO) {
pRetune = SampleManager.IsMP3RadioChannelAvailable() ? USERTRACK : USERTRACK - 1;
} else
pRetune--;
++gRetuneCounter;
}
} else
#endif
if(SampleManager.IsMP3RadioChannelAvailable()) { if(SampleManager.IsMP3RadioChannelAvailable()) {
gStreamedSound = m_nCurrentStreamedSound; gStreamedSound = m_nCurrentStreamedSound;
if(gStreamedSound == STREAMED_SOUND_CITY_AMBIENT || if(gStreamedSound == STREAMED_SOUND_CITY_AMBIENT ||
gStreamedSound == STREAMED_SOUND_WATER_AMBIENT) { gStreamedSound == STREAMED_SOUND_WATER_AMBIENT) {
gStreamedSound = STREAMED_SOUND_RADIO_POLICE; gStreamedSound = POLICE_RADIO; // which means OFF
} else { } else if(gStreamedSound > STREAMED_SOUND_RADIO_MP3_PLAYER)
if(gStreamedSound >
STREAMED_SOUND_RADIO_MP3_PLAYER)
return; return;
}
pRetune = gNumRetunePresses + gStreamedSound; pRetune = gNumRetunePresses + gStreamedSound;
@ -140,10 +162,17 @@ cMusicManager::DisplayRadioStationName()
case FLASHBACK: string = TheText.Get("FEA_FM7"); break; case FLASHBACK: string = TheText.Get("FEA_FM7"); break;
case CHATTERBOX: string = TheText.Get("FEA_FM8"); break; case CHATTERBOX: string = TheText.Get("FEA_FM8"); break;
case USERTRACK: string = TheText.Get("FEA_FM9"); break; case USERTRACK: string = TheText.Get("FEA_FM9"); break;
#ifdef RADIO_OFF_TEXT
case RADIO_OFF: case POLICE_RADIO: string = TheText.Get("FEM_OFF"); break;
#endif
default: return; default: return;
}; };
#ifdef RADIO_OFF_TEXT
if(pRetune == USERTRACK && !SampleManager.IsMP3RadioChannelAvailable()) { string = TheText.Get("FEM_OFF"); }
#else
if(pRetune > CHATTERBOX && !SampleManager.IsMP3RadioChannelAvailable()) { return; } if(pRetune > CHATTERBOX && !SampleManager.IsMP3RadioChannelAvailable()) { return; }
#endif
if(string && pCurrentStation != string || if(string && pCurrentStation != string ||
m_nCurrentStreamedSound == STREAMED_SOUND_RADIO_MP3_PLAYER && m_nCurrentStreamedSound == STREAMED_SOUND_RADIO_MP3_PLAYER &&
@ -161,9 +190,15 @@ cMusicManager::DisplayRadioStationName()
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_STRETCH_X(640.0f)); // Reminder: Game doesn't have "scaling" at all, it just stretches, and it's team's decision here to not let centered text occupy all the screen.
// Disable ASPECT_RATIO_SCALE and it'll go back to default behaviour; stretching.
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(CRGBA(0, 0, 0, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation); CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation);
#else
CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, SCREEN_SCALE_Y(22.0f) + 2.0f, pCurrentStation);
#endif
if(gNumRetunePresses) if(gNumRetunePresses)
CFont::SetColor(CRGBA(102, 133, 143, 255)); CFont::SetColor(CRGBA(102, 133, 143, 255));
@ -442,10 +477,11 @@ cMusicManager::ServiceGameMode()
if (m_bPlayerInCar) { if (m_bPlayerInCar) {
if (FindPlayerPed() != nil if (FindPlayerPed() != nil
&& !FindPlayerPed()->DyingOrDead() && !FindPlayerPed()->DyingOrDead()
&& CPad::GetPad(0)->ChangeStationJustDown()
&& !CReplay::IsPlayingBack() && !CReplay::IsPlayingBack()
&& FindPlayerVehicle() != nil && FindPlayerVehicle() != nil
&& !UsesPoliceRadio(FindPlayerVehicle())) { && !UsesPoliceRadio(FindPlayerVehicle())) {
if (CPad::GetPad(0)->ChangeStationJustDown()) {
gRetuneCounter = 30; gRetuneCounter = 30;
gNumRetunePresses++; gNumRetunePresses++;
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_CHANGE, 1.0f); AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_CHANGE, 1.0f);
@ -454,6 +490,19 @@ cMusicManager::ServiceGameMode()
gNumRetunePresses -= RADIO_OFF; gNumRetunePresses -= RADIO_OFF;
} }
} }
#ifdef RADIO_SCROLL_TO_PREV_STATION
else if(CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustDown()) {
int scrollNext = ControlsManager.GetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, MOUSE);
int scrollPrev = scrollNext == rsMOUSEWHEELUPBUTTON ? rsMOUSEWHEELDOWNBUTTON : scrollNext == rsMOUSEWHEELDOWNBUTTON ? rsMOUSEWHEELUPBUTTON : -1;
if (scrollPrev != -1 && !ControlsManager.IsAnyVehicleActionAssignedToMouseKey(scrollPrev)) {
gRetuneCounter = 30;
gNumRetunePresses--;
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_CHANGE, 1.0f);
}
}
#endif
}
} else { } else {
nFramesSinceCutsceneEnded = -1; nFramesSinceCutsceneEnded = -1;
} }
@ -494,10 +543,22 @@ cMusicManager::ServiceGameMode()
gNumRetunePresses = 0; gNumRetunePresses = 0;
m_bSetNextStation = false; m_bSetNextStation = false;
} }
// Because when you switch radio back and forth, gNumRetunePresses will be 0 but gRetuneCounter won't.
#ifdef RADIO_SCROLL_TO_PREV_STATION
if (gRetuneCounter != 0) {
if (gRetuneCounter > 1) gRetuneCounter--;
else if (gRetuneCounter == 1) gRetuneCounter = -1;
else if (gRetuneCounter == -1) {
m_bSetNextStation = true;
gRetuneCounter = 0;
}
}
#else
if (gNumRetunePresses) { if (gNumRetunePresses) {
if (gRetuneCounter != 0) gRetuneCounter--; if (gRetuneCounter != 0) gRetuneCounter--;
else m_bSetNextStation = true; else m_bSetNextStation = true;
} }
#endif
if (gRetuneCounter) if (gRetuneCounter)
AudioManager.DoPoliceRadioCrackle(); AudioManager.DoPoliceRadioCrackle();
if (m_bSetNextStation) { if (m_bSetNextStation) {
@ -863,6 +924,20 @@ cMusicManager::GetNextCarTuning()
if (veh == nil) return RADIO_OFF; if (veh == nil) return RADIO_OFF;
if (UsesPoliceRadio(veh)) return POLICE_RADIO; if (UsesPoliceRadio(veh)) return POLICE_RADIO;
if (gNumRetunePresses != 0) { if (gNumRetunePresses != 0) {
#ifdef RADIO_SCROLL_TO_PREV_STATION
if (gNumRetunePresses < 0) {
while (gNumRetunePresses < 0) {
if(veh->m_nRadioStation == HEAD_RADIO) {
veh->m_nRadioStation = RADIO_OFF;
} else if(veh->m_nRadioStation == RADIO_OFF || veh->m_nRadioStation == POLICE_RADIO) {
veh->m_nRadioStation = SampleManager.IsMP3RadioChannelAvailable() ? USERTRACK : USERTRACK - 1;
} else
veh->m_nRadioStation--;
++gNumRetunePresses;
}
} else
#endif
if (SampleManager.IsMP3RadioChannelAvailable()) { if (SampleManager.IsMP3RadioChannelAvailable()) {
if (veh->m_nRadioStation == RADIO_OFF) if (veh->m_nRadioStation == RADIO_OFF)
veh->m_nRadioStation = POLICE_RADIO; veh->m_nRadioStation = POLICE_RADIO;

View File

@ -91,9 +91,9 @@ cAudioManager::InitialisePoliceRadio()
m_sPoliceRadioQueue.policeChannelTimerSeconds = 0; m_sPoliceRadioQueue.policeChannelTimerSeconds = 0;
m_sPoliceRadioQueue.policeChannelCounterSeconds = 0; m_sPoliceRadioQueue.policeChannelCounterSeconds = 0;
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)
m_sPoliceRadioQueue.crimes[i].type = 0; m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
SampleManager.SetChannelReverbFlag(policeChannel, 0); SampleManager.SetChannelReverbFlag(policeChannel, false);
gSpecialSuspectLastSeenReport = false; gSpecialSuspectLastSeenReport = false;
for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++) for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
gMinTimeToNextReport[i] = m_FrameCounter; gMinTimeToNextReport[i] = m_FrameCounter;
@ -154,7 +154,7 @@ cAudioManager::ServicePoliceRadio()
if(!m_bIsInitialised) return; if(!m_bIsInitialised) return;
if(!m_nUserPause) { if(m_nUserPause == 0) {
bool crimeReport = SetupCrimeReport(); bool crimeReport = SetupCrimeReport();
#ifdef FIX_BUGS // Crash at 0x5fe6ef #ifdef FIX_BUGS // Crash at 0x5fe6ef
if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted) if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted)
@ -162,8 +162,8 @@ cAudioManager::ServicePoliceRadio()
#endif #endif
wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel; wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel;
if(!crimeReport) { if(!crimeReport) {
if(wantedLevel) { if(wantedLevel != 0) {
if(nLastSeen) { if(nLastSeen != 0) {
--nLastSeen; --nLastSeen;
} else { } else {
nLastSeen = m_anRandomTable[1] % 1000 + 2000; nLastSeen = m_anRandomTable[1] % 1000 + 2000;
@ -176,7 +176,7 @@ cAudioManager::ServicePoliceRadio()
} }
void void
cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel) cAudioManager::ServicePoliceRadioChannel(uint8 wantedLevel)
{ {
bool processed = false; bool processed = false;
uint32 sample; uint32 sample;
@ -189,7 +189,7 @@ cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel)
if (!m_bIsInitialised) return; if (!m_bIsInitialised) return;
if (m_nUserPause) { if (m_nUserPause != 0) {
if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel); if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 && if (g_nMissionAudioSfx != TOTAL_AUDIO_SAMPLES && bMissionAudioPhysicalPlayingStatus == 1 &&
SampleManager.IsStreamPlaying(1)) { SampleManager.IsStreamPlaying(1)) {
@ -241,7 +241,7 @@ cAudioManager::ServicePoliceRadioChannel(int32 wantedLevel)
} else { } else {
sample = TOTAL_AUDIO_SAMPLES; sample = TOTAL_AUDIO_SAMPLES;
} }
if (!wantedLevel) { if (wantedLevel == 0) {
if (gSpecialSuspectLastSeenReport) { if (gSpecialSuspectLastSeenReport) {
gSpecialSuspectLastSeenReport = 0; gSpecialSuspectLastSeenReport = 0;
} else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) { } else if (((sample >= SFX_POLICE_RADIO_MESSAGE_NOISE_1) && (sample <= SFX_POLICE_RADIO_MESSAGE_NOISE_3)) || sample == TOTAL_AUDIO_SAMPLES) {
@ -675,7 +675,7 @@ cAudioManager::SetupSuspectLastSeenReport()
void void
cAudioManager::ReportCrime(int32 type, const CVector *pos) cAudioManager::ReportCrime(eCrimeType type, const CVector &pos)
{ {
int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes); int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);
if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 &&
@ -683,7 +683,7 @@ cAudioManager::ReportCrime(int32 type, const CVector *pos)
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) { for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
if (m_sPoliceRadioQueue.crimes[i].type) { if (m_sPoliceRadioQueue.crimes[i].type) {
if (m_sPoliceRadioQueue.crimes[i].type == type) { if (m_sPoliceRadioQueue.crimes[i].type == type) {
m_sPoliceRadioQueue.crimes[i].position = *pos; m_sPoliceRadioQueue.crimes[i].position = pos;
m_sPoliceRadioQueue.crimes[i].timer = 0; m_sPoliceRadioQueue.crimes[i].timer = 0;
return; return;
} }
@ -694,7 +694,7 @@ cAudioManager::ReportCrime(int32 type, const CVector *pos)
if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) { if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {
m_sPoliceRadioQueue.crimes[lastCrime].type = type; m_sPoliceRadioQueue.crimes[lastCrime].type = type;
m_sPoliceRadioQueue.crimes[lastCrime].position = *pos; m_sPoliceRadioQueue.crimes[lastCrime].position = pos;
m_sPoliceRadioQueue.crimes[lastCrime].timer = 0; m_sPoliceRadioQueue.crimes[lastCrime].timer = 0;
gMinTimeToNextReport[type] = m_FrameCounter + 500; gMinTimeToNextReport[type] = m_FrameCounter + 500;
} }

View File

@ -235,7 +235,7 @@ enum AudioEntityHandle {
AEHANDLE_ERROR_BADAUDIOTYPE = -1, AEHANDLE_ERROR_BADAUDIOTYPE = -1,
}; };
enum eAudioType : int32 enum eAudioType
{ {
AUDIOTYPE_PHYSICAL = 0, AUDIOTYPE_PHYSICAL = 0,
AUDIOTYPE_EXPLOSION, AUDIOTYPE_EXPLOSION,

View File

@ -10,17 +10,49 @@
extern bool IsFXSupported(); extern bool IsFXSupported();
ALuint alSources[MAXCHANNELS+MAX2DCHANNELS];
ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];
ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];
bool bChannelsCreated = false;
void
CChannel::InitChannels()
{
alGenSources(MAXCHANNELS+MAX2DCHANNELS, alSources);
alGenBuffers(MAXCHANNELS+MAX2DCHANNELS, alBuffers);
if (IsFXSupported())
alGenFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
bChannelsCreated = true;
}
void
CChannel::DestroyChannels()
{
if (bChannelsCreated)
{
alDeleteSources(MAXCHANNELS + MAX2DCHANNELS, alSources);
memset(alSources, 0, sizeof(alSources));
alDeleteBuffers(MAXCHANNELS + MAX2DCHANNELS, alBuffers);
memset(alBuffers, 0, sizeof(alBuffers));
if (IsFXSupported())
{
alDeleteFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
memset(alFilters, 0, sizeof(alFilters));
}
bChannelsCreated = false;
}
}
CChannel::CChannel() CChannel::CChannel()
{ {
alSource = AL_NONE; Data = nil;
alFilter = AL_FILTER_NULL; DataSize = 0;
SetDefault(); SetDefault();
} }
void CChannel::SetDefault() void CChannel::SetDefault()
{ {
alBuffer = AL_NONE;
Pitch = 1.0f; Pitch = 1.0f;
Gain = 1.0f; Gain = 1.0f;
Mix = 0.0f; Mix = 0.0f;
@ -39,25 +71,19 @@ void CChannel::Reset()
SetDefault(); SetDefault();
} }
void CChannel::Init(bool Is2D) void CChannel::Init(uint32 _id, bool Is2D)
{ {
ASSERT(!HasSource()); id = _id;
alGenSources(1, &alSource);
if ( HasSource() ) if ( HasSource() )
{ {
alSourcei(alSource, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(alSources[id], AL_SOURCE_RELATIVE, AL_TRUE);
if ( IsFXSupported() ) if ( IsFXSupported() )
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
if ( Is2D ) if ( Is2D )
{ {
alSource3f(alSource, AL_POSITION, 0.0f, 0.0f, 0.0f); alSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f);
alSourcef (alSource, AL_GAIN, 1.0f); alSourcef(alSources[id], AL_GAIN, 1.0f);
}
else
{
if ( IsFXSupported() )
alGenFilters(1,&alFilter);
} }
} }
} }
@ -69,39 +95,34 @@ void CChannel::Term()
{ {
if ( IsFXSupported() ) if ( IsFXSupported() )
{ {
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);
if(alFilter != AL_FILTER_NULL)
alDeleteFilters(1,&alFilter);
} }
alDeleteSources(1, &alSource);
} }
alSource = AL_NONE;
alFilter = AL_FILTER_NULL;
} }
void CChannel::Start() void CChannel::Start()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( !Data ) return;
alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);
if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 ) if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )
alBufferiv(alBuffer, AL_LOOP_POINTS_SOFT, LoopPoints); alBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints);
alSourcei (alSource, AL_BUFFER, alBuffer); alSourcei(alSources[id], AL_BUFFER, alBuffers[id]);
alSourcePlay(alSource); alSourcePlay(alSources[id]);
} }
void CChannel::Stop() void CChannel::Stop()
{ {
if ( HasSource() ) if ( HasSource() )
alSourceStop(alSource); alSourceStop(alSources[id]);
Reset(); Reset();
} }
bool CChannel::HasSource() bool CChannel::HasSource()
{ {
return alSource != AL_NONE; return alSources[id] != AL_NONE;
} }
bool CChannel::IsUsed() bool CChannel::IsUsed()
@ -109,7 +130,7 @@ bool CChannel::IsUsed()
if ( HasSource() ) if ( HasSource() )
{ {
ALint sourceState; ALint sourceState;
alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState); alGetSourcei(alSources[id], AL_SOURCE_STATE, &sourceState);
return sourceState == AL_PLAYING; return sourceState == AL_PLAYING;
} }
return false; return false;
@ -118,13 +139,13 @@ bool CChannel::IsUsed()
void CChannel::SetPitch(float pitch) void CChannel::SetPitch(float pitch)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef(alSource, AL_PITCH, pitch); alSourcef(alSources[id], AL_PITCH, pitch);
} }
void CChannel::SetGain(float gain) void CChannel::SetGain(float gain)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef(alSource, AL_GAIN, gain); alSourcef(alSources[id], AL_GAIN, gain);
} }
void CChannel::SetVolume(int32 vol) void CChannel::SetVolume(int32 vol)
@ -132,14 +153,20 @@ void CChannel::SetVolume(int32 vol)
SetGain(ALfloat(vol) / MAX_VOLUME); SetGain(ALfloat(vol) / MAX_VOLUME);
} }
void CChannel::SetSampleID(uint32 nSfx) void CChannel::SetSampleData(void *_data, size_t _DataSize, int32 freq)
{
Sample = nSfx;
}
void CChannel::SetFreq(int32 freq)
{ {
DataSize = _DataSize;
Frequency = freq; Frequency = freq;
#ifdef BIGENDIAN
Data = malloc(DataSize);
memcpy(Data, _data, DataSize);
for (int i = 0; i < DataSize / sizeof(uint16); i++) {
((uint16*)Data)[i] = BSWAP16(((uint16*)Data)[i]);
}
#else
Data = _data;
#endif
} }
void CChannel::SetCurrentFreq(uint32 freq) void CChannel::SetCurrentFreq(uint32 freq)
@ -150,7 +177,7 @@ void CChannel::SetCurrentFreq(uint32 freq)
void CChannel::SetLoopCount(int32 loopCount) // fake. TODO: void CChannel::SetLoopCount(int32 loopCount) // fake. TODO:
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSource, AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE); alSourcei(alSources[id], AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
} }
void CChannel::SetLoopPoints(ALint start, ALint end) void CChannel::SetLoopPoints(ALint start, ALint end)
@ -162,53 +189,54 @@ void CChannel::SetLoopPoints(ALint start, ALint end)
void CChannel::SetPosition(float x, float y, float z) void CChannel::SetPosition(float x, float y, float z)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSource3f(alSource, AL_POSITION, x, y, z); alSource3f(alSources[id], AL_POSITION, x, y, z);
} }
void CChannel::SetDistances(float max, float min) void CChannel::SetDistances(float max, float min)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcef (alSource, AL_MAX_DISTANCE, max); alSourcef (alSources[id], AL_MAX_DISTANCE, max);
alSourcef (alSource, AL_REFERENCE_DISTANCE, min); alSourcef (alSources[id], AL_REFERENCE_DISTANCE, min);
alSourcef (alSource, AL_MAX_GAIN, 1.0f); alSourcef (alSources[id], AL_MAX_GAIN, 1.0f);
alSourcef (alSource, AL_ROLLOFF_FACTOR, 1.0f); alSourcef (alSources[id], AL_ROLLOFF_FACTOR, 1.0f);
} }
void CChannel::SetPan(uint32 pan) void CChannel::SetPan(int32 pan)
{ {
SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f))); SetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f)));
} }
void CChannel::SetBuffer(ALuint buffer)
{
alBuffer = buffer;
}
void CChannel::ClearBuffer() void CChannel::ClearBuffer()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
SetBuffer(AL_NONE); alSourcei(alSources[id], AL_BUFFER, AL_NONE);
alSourcei(alSource, AL_BUFFER, AL_NONE);
#ifdef BIGENDIAN
free(Data);
#endif
Data = nil;
DataSize = 0;
} }
void CChannel::SetReverbMix(ALuint slot, float mix) void CChannel::SetReverbMix(ALuint slot, float mix)
{ {
if ( !IsFXSupported() ) return; if ( !IsFXSupported() ) return;
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( alFilter == AL_FILTER_NULL ) return; if ( alFilters[id] == AL_FILTER_NULL ) return;
Mix = mix; Mix = mix;
EAX3_SetReverbMix(alFilter, mix); EAX3_SetReverbMix(alFilters[id], mix);
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
} }
void CChannel::UpdateReverb(ALuint slot) void CChannel::UpdateReverb(ALuint slot)
{ {
if ( !IsFXSupported() ) return; if ( !IsFXSupported() ) return;
if ( !HasSource() ) return; if ( !HasSource() ) return;
if ( alFilter == AL_FILTER_NULL ) return; if ( alFilters[id] == AL_FILTER_NULL ) return;
EAX3_SetReverbMix(alFilter, Mix); EAX3_SetReverbMix(alFilters[id], Mix);
alSource3i(alSource, AL_AUXILIARY_SEND_FILTER, slot, 0, alFilter); alSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);
} }
#endif #endif

View File

@ -9,22 +9,24 @@
class CChannel class CChannel
{ {
ALuint alSource; uint32 id;
ALuint alFilter;
ALuint alBuffer;
float Pitch, Gain; float Pitch, Gain;
float Mix; float Mix;
void *Data;
size_t DataSize;
int32 Frequency; int32 Frequency;
float Position[3]; float Position[3];
float Distances[2]; float Distances[2];
int32 LoopCount; int32 LoopCount;
ALint LoopPoints[2]; ALint LoopPoints[2];
uint32 Sample;
public: public:
static void InitChannels();
static void DestroyChannels();
CChannel(); CChannel();
void SetDefault(); void SetDefault();
void Reset(); void Reset();
void Init(bool Is2D = false); void Init(uint32 _id, bool Is2D = false);
void Term(); void Term();
void Start(); void Start();
void Stop(); void Stop();
@ -33,15 +35,13 @@ public:
void SetPitch(float pitch); void SetPitch(float pitch);
void SetGain(float gain); void SetGain(float gain);
void SetVolume(int32 vol); void SetVolume(int32 vol);
void SetSampleID(uint32 nSfx); void SetSampleData(void *_data, size_t _DataSize, int32 freq);
void SetFreq(int32 freq);
void SetCurrentFreq(uint32 freq); void SetCurrentFreq(uint32 freq);
void SetLoopCount(int32 loopCount); // fake void SetLoopCount(int32 loopCount); // fake
void SetLoopPoints(ALint start, ALint end); void SetLoopPoints(ALint start, ALint end);
void SetPosition(float x, float y, float z); void SetPosition(float x, float y, float z);
void SetDistances(float max, float min); void SetDistances(float max, float min);
void SetPan(uint32 pan); void SetPan(int32 pan);
void SetBuffer(ALuint buffer);
void ClearBuffer(); void ClearBuffer();
void SetReverbMix(ALuint slot, float mix); void SetReverbMix(ALuint slot, float mix);
void UpdateReverb(ALuint slot); void UpdateReverb(ALuint slot);

View File

@ -4,6 +4,14 @@
#ifdef AUDIO_OAL #ifdef AUDIO_OAL
#ifndef __WIIU__ #ifndef __WIIU__
/*
* When linking to a static openal-soft library,
* the extension function inside the openal library conflict with the variables here.
* Therefore declare these re3 owned symbols in a private namespace.
*/
namespace re3_openal {
LPALGENEFFECTS alGenEffects; LPALGENEFFECTS alGenEffects;
LPALDELETEEFFECTS alDeleteEffects; LPALDELETEEFFECTS alDeleteEffects;
LPALISEFFECT alIsEffect; LPALISEFFECT alIsEffect;
@ -37,8 +45,12 @@ LPALGETFILTERI alGetFilteri;
LPALGETFILTERIV alGetFilteriv; LPALGETFILTERIV alGetFilteriv;
LPALGETFILTERF alGetFilterf; LPALGETFILTERF alGetFilterf;
LPALGETFILTERFV alGetFilterfv; LPALGETFILTERFV alGetFilterfv;
#endif
}
using namespace re3_openal;
#endif
void EFXInit() void EFXInit()
{ {

View File

@ -11,6 +11,8 @@ void EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props);
void EAX3_SetReverbMix(ALuint filter, float mix); void EAX3_SetReverbMix(ALuint filter, float mix);
void SetEffectsLevel(ALuint uiFilter, float level); void SetEffectsLevel(ALuint uiFilter, float level);
namespace re3_openal {
extern LPALGENEFFECTS alGenEffects; extern LPALGENEFFECTS alGenEffects;
extern LPALDELETEEFFECTS alDeleteEffects; extern LPALDELETEEFFECTS alDeleteEffects;
extern LPALISEFFECT alIsEffect; extern LPALISEFFECT alIsEffect;
@ -44,4 +46,9 @@ extern LPALGETFILTERI alGetFilteri;
extern LPALGETFILTERIV alGetFilteriv; extern LPALGETFILTERIV alGetFilteriv;
extern LPALGETFILTERF alGetFilterf; extern LPALGETFILTERF alGetFilterf;
extern LPALGETFILTERFV alGetFilterfv; extern LPALGETFILTERFV alGetFilterfv;
}
using namespace re3_openal;
#endif #endif

View File

@ -10,13 +10,15 @@
#ifdef _WIN32 #ifdef _WIN32
#pragma comment( lib, "libsndfile-1.lib" ) #pragma comment( lib, "libsndfile-1.lib" )
#pragma comment( lib, "libmpg123-0.lib" ) #pragma comment( lib, "libmpg123-0.lib" )
#else
#include "crossplatform.h"
#endif #endif
#include <sndfile.h> #include <sndfile.h>
#include <mpg123.h> #include <mpg123.h>
#endif #endif
#ifndef _WIN32
#include "crossplatform.h"
#endif
#ifndef AUDIO_OPUS #ifndef AUDIO_OPUS
class CSndFile : public IDecoder class CSndFile : public IDecoder
{ {
@ -155,13 +157,13 @@ public:
void Seek(uint32 milliseconds) void Seek(uint32 milliseconds)
{ {
if ( !IsOpened() ) return; if ( !IsOpened() ) return;
mpg123_seek(m_pMH, ms2samples(milliseconds)*GetSampleSize(), SEEK_SET); mpg123_seek(m_pMH, ms2samples(milliseconds), SEEK_SET);
} }
uint32 Tell() uint32 Tell()
{ {
if ( !IsOpened() ) return 0; if ( !IsOpened() ) return 0;
return samples2ms(mpg123_tell(m_pMH)/GetSampleSize()); return samples2ms(mpg123_tell(m_pMH));
} }
uint32 Decode(void *buffer) uint32 Decode(void *buffer)
@ -195,7 +197,7 @@ public:
if (m_FileH) { if (m_FileH) {
m_nChannels = op_head(m_FileH, 0)->channel_count; m_nChannels = op_head(m_FileH, 0)->channel_count;
m_nRate = op_head(m_FileH, 0)->input_sample_rate; m_nRate = 48000;
const OpusTags *tags = op_tags(m_FileH, 0); const OpusTags *tags = op_tags(m_FileH, 0);
for (int i = 0; i < tags->comments; i++) { for (int i = 0; i < tags->comments; i++) {
if (strncmp(tags->user_comments[i], "SAMPLERATE", sizeof("SAMPLERATE")-1) == 0) if (strncmp(tags->user_comments[i], "SAMPLERATE", sizeof("SAMPLERATE")-1) == 0)
@ -247,13 +249,13 @@ public:
void Seek(uint32 milliseconds) void Seek(uint32 milliseconds)
{ {
if ( !IsOpened() ) return; if ( !IsOpened() ) return;
op_pcm_seek(m_FileH, ms2samples(milliseconds) * GetSampleSize()); op_pcm_seek(m_FileH, ms2samples(milliseconds) / GetChannels());
} }
uint32 Tell() uint32 Tell()
{ {
if ( !IsOpened() ) return 0; if ( !IsOpened() ) return 0;
return samples2ms(op_pcm_tell(m_FileH)/GetSampleSize()); return samples2ms(op_pcm_tell(m_FileH) * GetChannels());
} }
uint32 Decode(void *buffer) uint32 Decode(void *buffer)
@ -323,8 +325,8 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF
#endif #endif
else else
m_pSoundFile = nil; m_pSoundFile = nil;
ASSERT(m_pSoundFile != nil);
if (m_pSoundFile && m_pSoundFile->IsOpened() ) if ( IsOpened() )
{ {
m_pBuffer = malloc(m_pSoundFile->GetBufferSize()); m_pBuffer = malloc(m_pSoundFile->GetBufferSize());
ASSERT(m_pBuffer!=nil); ASSERT(m_pBuffer!=nil);
@ -371,14 +373,14 @@ bool CStream::HasSource()
bool CStream::IsOpened() bool CStream::IsOpened()
{ {
return m_pSoundFile->IsOpened(); return m_pSoundFile && m_pSoundFile->IsOpened();
} }
bool CStream::IsPlaying() bool CStream::IsPlaying()
{ {
if ( !HasSource() || !IsOpened() ) return false; if ( !HasSource() || !IsOpened() ) return false;
if ( m_pSoundFile->IsOpened() && !m_bPaused ) if ( !m_bPaused )
{ {
ALint sourceState; ALint sourceState;
alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState); alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState);
@ -446,7 +448,7 @@ void CStream::SetPan(uint8 nPan)
void CStream::SetPosMS(uint32 nPos) void CStream::SetPosMS(uint32 nPos)
{ {
if ( !m_pSoundFile->IsOpened() ) return; if ( !IsOpened() ) return;
m_pSoundFile->Seek(nPos); m_pSoundFile->Seek(nPos);
ClearBuffers(); ClearBuffers();
} }
@ -454,20 +456,20 @@ void CStream::SetPosMS(uint32 nPos)
uint32 CStream::GetPosMS() uint32 CStream::GetPosMS()
{ {
if ( !HasSource() ) return 0; if ( !HasSource() ) return 0;
if ( !m_pSoundFile->IsOpened() ) return 0; if ( !IsOpened() ) return 0;
ALint offset; ALint offset;
//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset); //alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);
alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset); alGetSourcei(m_alSource, AL_BYTE_OFFSET, &offset);
return m_pSoundFile->Tell() return m_pSoundFile->Tell()
- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) - m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS-1)) / m_pSoundFile->GetChannels()
+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()); + m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels();
} }
uint32 CStream::GetLengthMS() uint32 CStream::GetLengthMS()
{ {
if ( !m_pSoundFile->IsOpened() ) return 0; if ( !IsOpened() ) return 0;
return m_pSoundFile->GetLength(); return m_pSoundFile->GetLength();
} }
@ -475,7 +477,7 @@ bool CStream::FillBuffer(ALuint alBuffer)
{ {
if ( !HasSource() ) if ( !HasSource() )
return false; return false;
if ( !m_pSoundFile->IsOpened() ) if ( !IsOpened() )
return false; return false;
if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) ) if ( !(alBuffer != AL_NONE && alIsBuffer(alBuffer)) )
return false; return false;
@ -517,7 +519,7 @@ void CStream::ClearBuffers()
bool CStream::Setup() bool CStream::Setup()
{ {
if ( m_pSoundFile->IsOpened() ) if ( IsOpened() )
{ {
m_pSoundFile->Seek(0); m_pSoundFile->Seek(0);
alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE); alSourcei(m_alSource, AL_SOURCE_RELATIVE, AL_TRUE);

View File

@ -24,12 +24,12 @@ public:
uint32 ms2samples(uint32 ms) uint32 ms2samples(uint32 ms)
{ {
return float(ms) / 1000.0f * float(GetChannels()) * float(GetSampleRate()); return float(ms) / 1000.0f * float(GetSampleRate());
} }
uint32 samples2ms(uint32 sm) uint32 samples2ms(uint32 sm)
{ {
return float(sm) * 1000.0f / float(GetChannels()) / float(GetSampleRate()); return float(sm) * 1000.0f / float(GetSampleRate());
} }
uint32 GetBufferSamples() uint32 GetBufferSamples()

View File

@ -158,10 +158,6 @@ public:
bool Initialise(void); bool Initialise(void);
void Terminate (void); void Terminate (void);
#ifdef AUDIO_OAL
void UpdateSoundBuffers(void);
#endif
bool CheckForAnAudioFileOnCD(void); bool CheckForAnAudioFileOnCD(void);
char GetCDAudioDriveLetter (void); char GetCDAudioDriveLetter (void);
@ -222,6 +218,10 @@ public:
extern cSampleManager SampleManager; extern cSampleManager SampleManager;
extern uint32 BankStartOffset[MAX_SFX_BANKS]; extern uint32 BankStartOffset[MAX_SFX_BANKS];
#ifdef AUDIO_OAL
extern int defaultProvider;
#endif
#ifdef AUDIO_OPUS #ifdef AUDIO_OPUS
static char StreamedNameTable[][25] = { static char StreamedNameTable[][25] = {
"AUDIO\\HEAD.OPUS", "AUDIO\\CLASS.OPUS", "AUDIO\\KJAH.OPUS", "AUDIO\\RISE.OPUS", "AUDIO\\LIPS.OPUS", "AUDIO\\GAME.OPUS", "AUDIO\\HEAD.OPUS", "AUDIO\\CLASS.OPUS", "AUDIO\\KJAH.OPUS", "AUDIO\\RISE.OPUS", "AUDIO\\LIPS.OPUS", "AUDIO\\GAME.OPUS",

View File

@ -65,7 +65,7 @@ uint32 _CurMP3Index;
int32 _CurMP3Pos; int32 _CurMP3Pos;
bool _bIsMp3Active; bool _bIsMp3Active;
#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) #if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
bool _bUseHDDAudio; bool _bUseHDDAudio;
char _aHDDPath[MAX_PATH]; char _aHDDPath[MAX_PATH];
#endif #endif
@ -1043,7 +1043,7 @@ cSampleManager::Initialise(void)
if ( !m_bInitialised ) if ( !m_bInitialised )
{ {
#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
FrontEndMenuManager.WaitForUserCD(); FrontEndMenuManager.WaitForUserCD();
if ( FrontEndMenuManager.m_bQuitGameNoCD ) if ( FrontEndMenuManager.m_bQuitGameNoCD )
{ {
@ -1060,7 +1060,7 @@ cSampleManager::Initialise(void)
} }
} }
#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) #if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
// hddaudio // hddaudio
/** /**
Option for user to play audio files directly from hard disk. Option for user to play audio files directly from hard disk.
@ -1297,17 +1297,17 @@ cSampleManager::Terminate(void)
bool bool
cSampleManager::CheckForAnAudioFileOnCD(void) cSampleManager::CheckForAnAudioFileOnCD(void)
{ {
#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
char filepath[MAX_PATH]; char filepath[MAX_PATH];
#if defined(GTA3_1_1_PATCH) #if GTA_VERSION >= GTA3_PC_11
if (_bUseHDDAudio) if (_bUseHDDAudio)
strcpy(filepath, _aHDDPath); strcpy(filepath, _aHDDPath);
else else
strcpy(filepath, m_szCDRomRootPath); strcpy(filepath, m_szCDRomRootPath);
#else #else
strcpy(filepath, m_szCDRomRootPath); strcpy(filepath, m_szCDRomRootPath);
#endif // #if defined(GTA3_1_1_PATCH) #endif // #if GTA_VERSION >= GTA3_PC_11
strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]);
@ -1324,13 +1324,13 @@ cSampleManager::CheckForAnAudioFileOnCD(void)
#else #else
return true; return true;
#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) #endif // #if GTA_VERSION < GTA3_PC_STEAM && !defined(NO_CDCHECK)
} }
char char
cSampleManager::GetCDAudioDriveLetter(void) cSampleManager::GetCDAudioDriveLetter(void)
{ {
#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) #if GTA_VERSION >= GTA3_PC_11 || defined(NO_CDCHECK)
if (_bUseHDDAudio) if (_bUseHDDAudio)
{ {
if ( strlen(_aHDDPath) != 0 ) if ( strlen(_aHDDPath) != 0 )

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
enum eSound : uint16 enum eSound
{ {
SOUND_CAR_DOOR_CLOSE_BONNET = 0, SOUND_CAR_DOOR_CLOSE_BONNET = 0,
SOUND_CAR_DOOR_CLOSE_BUMPER, SOUND_CAR_DOOR_CLOSE_BUMPER,
@ -173,7 +173,7 @@ enum eSound : uint16
}; };
enum eScriptSounds : uint16 { enum eScriptSounds {
SCRIPT_SOUND_0 = 0, SCRIPT_SOUND_0 = 0,
SCRIPT_SOUND_1, SCRIPT_SOUND_1,
SCRIPT_SOUND_2, SCRIPT_SOUND_2,

21
src/collision/ColBox.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "common.h"
#include "ColBox.h"
void
CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
{
this->min = min;
this->max = max;
this->surface = surf;
this->piece = piece;
}
CColBox&
CColBox::operator=(const CColBox& other)
{
min = other.min;
max = other.max;
surface = other.surface;
piece = other.piece;
return *this;
}

16
src/collision/ColBox.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "SurfaceTable.h"
struct CColBox
{
CVector min;
CVector max;
uint8 surface;
uint8 piece;
void Set(const CVector &min, const CVector &max, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
CVector GetSize(void) { return max - min; }
CColBox& operator=(const CColBox &other);
};

View File

@ -0,0 +1,9 @@
#include "common.h"
#include "ColLine.h"
void
CColLine::Set(const CVector &p0, const CVector &p1)
{
this->p0 = p0;
this->p1 = p1;
}

14
src/collision/ColLine.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
struct CColLine
{
// NB: this has to be compatible with two CVuVectors
CVector p0;
int pad0;
CVector p1;
int pad1;
CColLine(void) { };
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
void Set(const CVector &p0, const CVector &p1);
};

190
src/collision/ColModel.cpp Normal file
View File

@ -0,0 +1,190 @@
#include "common.h"
#include "ColModel.h"
#include "Game.h"
#include "MemoryHeap.h"
CColModel::CColModel(void)
{
numSpheres = 0;
spheres = nil;
numLines = 0;
lines = nil;
numBoxes = 0;
boxes = nil;
numTriangles = 0;
vertices = nil;
triangles = nil;
trianglePlanes = nil;
level = CGame::currLevel;
ownsCollisionVolumes = true;
}
CColModel::~CColModel(void)
{
RemoveCollisionVolumes();
RemoveTrianglePlanes();
}
void
CColModel::RemoveCollisionVolumes(void)
{
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
}
numSpheres = 0;
numLines = 0;
numBoxes = 0;
numTriangles = 0;
spheres = nil;
lines = nil;
boxes = nil;
vertices = nil;
triangles = nil;
}
void
CColModel::CalculateTrianglePlanes(void)
{
PUSH_MEMID(MEMID_COLLISION);
// HACK: allocate space for one more element to stuff the link pointer into
trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
REGISTER_MEMPTR(&trianglePlanes);
for(int i = 0; i < numTriangles; i++)
trianglePlanes[i].Set(vertices, triangles[i]);
POP_MEMID();
}
void
CColModel::RemoveTrianglePlanes(void)
{
RwFree(trianglePlanes);
trianglePlanes = nil;
}
void
CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
{
assert(trianglePlanes);
*(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
}
CLink<CColModel*>*
CColModel::GetLinkPtr(void)
{
assert(trianglePlanes);
return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
}
void
CColModel::GetTrianglePoint(CVector &v, int i) const
{
v = vertices[i].Get();
}
CColModel&
CColModel::operator=(const CColModel &other)
{
int i;
int numVerts;
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
// copy spheres
if(other.numSpheres){
if(numSpheres != other.numSpheres){
numSpheres = other.numSpheres;
if(spheres)
RwFree(spheres);
spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
}
for(i = 0; i < numSpheres; i++)
spheres[i] = other.spheres[i];
}else{
numSpheres = 0;
if(spheres)
RwFree(spheres);
spheres = nil;
}
// copy lines
if(other.numLines){
if(numLines != other.numLines){
numLines = other.numLines;
if(lines)
RwFree(lines);
lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
}
for(i = 0; i < numLines; i++)
lines[i] = other.lines[i];
}else{
numLines = 0;
if(lines)
RwFree(lines);
lines = nil;
}
// copy boxes
if(other.numBoxes){
if(numBoxes != other.numBoxes){
numBoxes = other.numBoxes;
if(boxes)
RwFree(boxes);
boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
}
for(i = 0; i < numBoxes; i++)
boxes[i] = other.boxes[i];
}else{
numBoxes = 0;
if(boxes)
RwFree(boxes);
boxes = nil;
}
// copy mesh
if(other.numTriangles){
// copy vertices
numVerts = 0;
for(i = 0; i < other.numTriangles; i++){
if(other.triangles[i].a > numVerts)
numVerts = other.triangles[i].a;
if(other.triangles[i].b > numVerts)
numVerts = other.triangles[i].b;
if(other.triangles[i].c > numVerts)
numVerts = other.triangles[i].c;
}
numVerts++;
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
// copy triangles
if(numTriangles != other.numTriangles){
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];
}else{
numTriangles = 0;
if(triangles)
RwFree(triangles);
triangles = nil;
if(vertices)
RwFree(vertices);
vertices = nil;
}
return *this;
}

37
src/collision/ColModel.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include "templates.h"
#include "ColBox.h"
#include "ColSphere.h"
#include "ColLine.h"
#include "ColPoint.h"
#include "ColTriangle.h"
struct CColModel
{
CColSphere boundingSphere;
CColBox boundingBox;
int16 numSpheres;
int16 numLines;
int16 numBoxes;
int16 numTriangles;
int32 level;
bool ownsCollisionVolumes; // missing on PS2
CColSphere *spheres;
CColLine *lines;
CColBox *boxes;
CompressedVector *vertices;
CColTriangle *triangles;
CColTrianglePlane *trianglePlanes;
CColModel(void);
~CColModel(void);
void RemoveCollisionVolumes(void);
void CalculateTrianglePlanes(void);
void RemoveTrianglePlanes(void);
CLink<CColModel*> *GetLinkPtr(void);
void SetLinkPtr(CLink<CColModel*>*);
void GetTrianglePoint(CVector &v, int i) const;
CColModel& operator=(const CColModel& other);
};

View File

@ -0,0 +1,16 @@
#include "common.h"
#include "ColPoint.h"
CColPoint&
CColPoint::operator=(const CColPoint &other)
{
point = other.point;
normal = other.normal;
surfaceA = other.surfaceA;
pieceA = other.pieceA;
surfaceB = other.surfaceB;
pieceB = other.pieceB;
// no depth?
return *this;
}

34
src/collision/ColPoint.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
struct CColPoint
{
CVector point;
int pad1;
// the surface normal on the surface of point
CVector normal;
int pad2;
uint8 surfaceA;
uint8 pieceA;
uint8 surfaceB;
uint8 pieceB;
float depth;
const CVector &GetNormal() { return normal; }
float GetDepth() { return depth; }
void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
this->depth = depth;
this->surfaceA = surfA;
this->pieceA = pieceA;
this->surfaceB = surfB;
this->pieceB = pieceB;
}
void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
this->surfaceA = surfA;
this->pieceA = pieceA;
this->surfaceB = surfB;
this->pieceB = pieceB;
}
CColPoint &operator=(const CColPoint &other);
};

View File

@ -0,0 +1,11 @@
#include "common.h"
#include "ColSphere.h"
void
CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
{
this->radius = radius;
this->center = center;
this->surface = surf;
this->piece = piece;
}

13
src/collision/ColSphere.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "SurfaceTable.h"
struct CColSphere
{
// NB: this has to be compatible with a CVuVector
CVector center;
float radius;
uint8 surface;
uint8 piece;
void Set(float radius, const CVector &center, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
};

View File

@ -0,0 +1,41 @@
#include "common.h"
#include "ColTriangle.h"
void
CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
{
this->a = a;
this->b = b;
this->c = c;
this->surface = surf;
}
#ifdef VU_COLLISION
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
CVector norm = CrossProduct(vc-va, vb-va);
norm.Normalise();
float d = DotProduct(norm, va);
normal.x = norm.x*4096.0f;
normal.y = norm.y*4096.0f;
normal.z = norm.z*4096.0f;
dist = d*128.0f;
}
#else
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
normal = CrossProduct(vc-va, vb-va);
normal.Normalise();
dist = DotProduct(normal, va);
CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
// find out largest component and its direction
if(an.x > an.y && an.x > an.z)
dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
else if(an.y > an.z)
dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
else
dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
}
#endif

View File

@ -0,0 +1,68 @@
#pragma once
#include "CompressedVector.h"
enum Direction {
DIR_X_POS,
DIR_X_NEG,
DIR_Y_POS,
DIR_Y_NEG,
DIR_Z_POS,
DIR_Z_NEG,
};
struct CColTriangle
{
uint16 a;
uint16 b;
uint16 c;
uint8 surface;
void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
};
struct CColTrianglePlane
{
#ifdef VU_COLLISION
CompressedVector normal;
int16 dist;
void Set(const CVector &va, const CVector &vb, const CVector &vc);
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
#ifdef GTA_PS2
void Unpack(uint128 &qword) const {
__asm__ volatile (
"lh $8, 0(%1)\n"
"lh $9, 2(%1)\n"
"lh $10, 4(%1)\n"
"lh $11, 6(%1)\n"
"pextlw $10, $8\n"
"pextlw $11, $9\n"
"pextlw $2, $11, $10\n"
"sq $2, %0\n"
: "=m" (qword)
: "r" (this)
: "$8", "$9", "$10", "$11", "$2"
);
}
#else
void Unpack(int32 *qword) const {
qword[0] = normal.x;
qword[1] = normal.y;
qword[2] = normal.z;
qword[3] = dist;
}
#endif
#else
CVector normal;
float dist;
uint8 dir;
void Set(const CVector &va, const CVector &vb, const CVector &vc);
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
void GetNormal(CVector &n) const { n = normal; }
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
#endif
};

View File

@ -23,303 +23,8 @@
#include "Collision.h" #include "Collision.h"
#include "Frontend.h" #include "Frontend.h"
// TODO: where do these go?
#ifdef VU_COLLISION #ifdef VU_COLLISION
#include "VuCollision.h"
struct VuTriangle
{
// Compressed int16 but unpacked
#ifdef GTA_PS2
uint128 v0;
uint128 v1;
uint128 v2;
uint128 plane;
#else
int32 v0[4];
int32 v1[4];
int32 v2[4];
int32 plane[4];
#endif
};
#ifndef GTA_PS2
static int16 vi01;
static CVuVector vf01;
static CVuVector vf02;
static CVuVector vf03;
CVuVector
DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
{
// center VF12
// p0 VF14
// line VF15
CVuVector ret; // VF16
CVuVector p1 = p0+line;
CVuVector dist0 = center - p0; // VF20
CVuVector dist1 = center - p1; // VF25
float lenSq = line.MagnitudeSqr(); // VF21
float distSq0 = dist0.MagnitudeSqr(); // VF22
float distSq1 = dist1.MagnitudeSqr();
float dot = DotProduct(dist0, line); // VF23
if(dot < 0.0f){
// not above line, closest to p0
ret = p0;
ret.w = distSq0;
return ret;
}
float t = dot/lenSq; // param of nearest point on infinite line
if(t > 1.0f){
// not above line, closest to p1
ret = p1;
ret.w = distSq1;
return ret;
}
// closest to line
ret = p0 + line*t;
ret.w = (ret - center).MagnitudeSqr();
return ret;
}
inline int SignFlags(const CVector &v)
{
int f = 0;
if(v.x < 0.0f) f |= 1;
if(v.y < 0.0f) f |= 2;
if(v.z < 0.0f) f |= 4;
return f;
}
#endif
extern "C" void
LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
const CVuVector &plane)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf13, 0x0(%1)\n"
"lqc2 vf14, 0x0(%2)\n"
"lqc2 vf15, 0x0(%3)\n"
"lqc2 vf16, 0x0(%4)\n"
"lqc2 vf17, 0x0(%5)\n"
"vcallms Vu0LineToTriangleCollisionStart\n"
".set reorder\n"
:
: "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
);
#else
float dot0 = DotProduct(plane, p0);
float dot1 = DotProduct(plane, p1);
float dist0 = plane.w - dot0;
float dist1 = plane.w - dot1;
// if points are on the same side, no collision
if(dist0 * dist1 > 0.0f){
vi01 = 0;
return;
}
CVuVector diff = p1 - p0;
float t = dist0/(dot1 - dot0);
CVuVector p = p0 + diff*t;
p.w = 0.0f;
vf01 = p;
vf03.x = t;
// Check if point is inside
CVector cross1 = CrossProduct(p-v0, v1-v0);
CVector cross2 = CrossProduct(p-v1, v2-v1);
CVector cross3 = CrossProduct(p-v2, v0-v2);
// Only check relevant directions
int flagmask = 0;
if(Abs(plane.x) > 0.5f) flagmask |= 1;
if(Abs(plane.y) > 0.5f) flagmask |= 2;
if(Abs(plane.z) > 0.5f) flagmask |= 4;
int flags1 = SignFlags(cross1) & flagmask;
int flags2 = SignFlags(cross2) & flagmask;
int flags3 = SignFlags(cross3) & flagmask;
// inside if on the same side of all edges
if(flags1 != flags2 || flags1 != flags3){
vi01 = 0;
return;
}
vi01 = 1;
vf02 = plane;
return;
#endif
}
extern "C" void
LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf13, 0x0(%1)\n"
"lqc2 vf14, 0x0(%2)\n"
"lqc2 vf15, 0x10(%2)\n"
"lqc2 vf16, 0x20(%2)\n"
"lqc2 vf17, 0x30(%2)\n"
"vcallms Vu0LineToTriangleCollisionCompressedStart\n"
".set reorder\n"
:
: "r" (&p0), "r" (&p1), "r" (&tri)
);
#else
CVuVector v0, v1, v2, plane;
v0.x = tri.v0[0]/128.0f;
v0.y = tri.v0[1]/128.0f;
v0.z = tri.v0[2]/128.0f;
v0.w = tri.v0[3]/128.0f;
v1.x = tri.v1[0]/128.0f;
v1.y = tri.v1[1]/128.0f;
v1.z = tri.v1[2]/128.0f;
v1.w = tri.v1[3]/128.0f;
v2.x = tri.v2[0]/128.0f;
v2.y = tri.v2[1]/128.0f;
v2.z = tri.v2[2]/128.0f;
v2.w = tri.v2[3]/128.0f;
plane.x = tri.plane[0]/4096.0f;
plane.y = tri.plane[1]/4096.0f;
plane.z = tri.plane[2]/4096.0f;
plane.w = tri.plane[3]/128.0f;
LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
#endif
}
extern "C" void
SphereToTriangleCollision(const CVuVector &sph,
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
const CVuVector &plane)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf14, 0x0(%1)\n"
"lqc2 vf15, 0x0(%2)\n"
"lqc2 vf16, 0x0(%3)\n"
"lqc2 vf17, 0x0(%4)\n"
"vcallms Vu0SphereToTriangleCollisionStart\n"
".set reorder\n"
:
: "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
);
#else
float planedist = DotProduct(plane, sph) - plane.w; // VF02
if(Abs(planedist) > sph.w){
vi01 = 0;
return;
}
// point on plane
CVuVector p = sph - planedist*plane;
p.w = 0.0f;
vf01 = p;
planedist = Abs(planedist);
// edges
CVuVector v01 = v1 - v0;
CVuVector v12 = v2 - v1;
CVuVector v20 = v0 - v2;
// VU code calculates normal again for some weird reason...
// Check sides of point
CVector cross1 = CrossProduct(p-v0, v01);
CVector cross2 = CrossProduct(p-v1, v12);
CVector cross3 = CrossProduct(p-v2, v20);
// Only check relevant directions
int flagmask = 0;
if(Abs(plane.x) > 0.1f) flagmask |= 1;
if(Abs(plane.y) > 0.1f) flagmask |= 2;
if(Abs(plane.z) > 0.1f) flagmask |= 4;
int nflags = SignFlags(plane) & flagmask;
int flags1 = SignFlags(cross1) & flagmask;
int flags2 = SignFlags(cross2) & flagmask;
int flags3 = SignFlags(cross3) & flagmask;
int testcase = 0;
CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
if(flags1 == nflags){
closest += v2;
testcase++;
}
if(flags2 == nflags){
closest += v0;
testcase++;
}
if(flags3 == nflags){
closest += v1;
testcase++;
}
if(testcase == 3){
// inside triangle - dist to plane already checked
vf02 = plane;
vf02.w = vf03.x = planedist;
vi01 = 1;
}else if(testcase == 1){
// outside two sides - closest to point opposide inside edge
vf01 = closest;
vf02 = sph - closest;
float distSq = vf02.MagnitudeSqr();
vi01 = sph.w*sph.w > distSq;
vf03.x = Sqrt(distSq);
vf02 *= 1.0f/vf03.x;
}else{
// inside two sides - closest to third edge
if(flags1 != nflags)
closest = DistanceBetweenSphereAndLine(sph, v0, v01);
else if(flags2 != nflags)
closest = DistanceBetweenSphereAndLine(sph, v1, v12);
else
closest = DistanceBetweenSphereAndLine(sph, v2, v20);
vi01 = sph.w*sph.w > closest.w;
vf01 = closest;
vf02 = sph - closest;
vf03.x = Sqrt(closest.w);
vf02 *= 1.0f/vf03.x;
}
#endif
}
extern "C" void
SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf14, 0x0(%1)\n"
"lqc2 vf15, 0x10(%1)\n"
"lqc2 vf16, 0x20(%1)\n"
"lqc2 vf17, 0x30(%1)\n"
"vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
".set reorder\n"
:
: "r" (&sph), "r" (&tri)
);
#else
CVuVector v0, v1, v2, plane;
v0.x = tri.v0[0]/128.0f;
v0.y = tri.v0[1]/128.0f;
v0.z = tri.v0[2]/128.0f;
v0.w = tri.v0[3]/128.0f;
v1.x = tri.v1[0]/128.0f;
v1.y = tri.v1[1]/128.0f;
v1.z = tri.v1[2]/128.0f;
v1.w = tri.v1[3]/128.0f;
v2.x = tri.v2[0]/128.0f;
v2.y = tri.v2[1]/128.0f;
v2.z = tri.v2[2]/128.0f;
v2.w = tri.v2[3]/128.0f;
plane.x = tri.plane[0]/4096.0f;
plane.y = tri.plane[1]/4096.0f;
plane.z = tri.plane[2]/4096.0f;
plane.w = tri.plane[3]/128.0f;
SphereToTriangleCollision(sph, v0, v1, v2, plane);
#endif
}
inline int inline int
GetVUresult(void) GetVUresult(void)
@ -362,17 +67,6 @@ GetVUresult(CVuVector &point, CVuVector &normal, float &dist)
#endif #endif
enum Direction
{
DIR_X_POS,
DIR_X_NEG,
DIR_Y_POS,
DIR_Y_NEG,
DIR_Z_POS,
DIR_Z_NEG,
};
eLevelName CCollision::ms_collisionInMemory; eLevelName CCollision::ms_collisionInMemory;
CLinkList<CColModel*> CCollision::ms_colModelCache; CLinkList<CColModel*> CCollision::ms_colModelCache;
@ -971,7 +665,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
// transform line to model space // transform line to model space
Invert(matrix, matTransform); Invert(matrix, matTransform);
CVuVector newline[2]; CVuVector newline[2];
TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);
// If we don't intersect with the bounding box, no chance on the rest // If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(*(CColLine*)newline, model.boundingBox)) if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
@ -1780,7 +1474,7 @@ CCollision::ProcessLineOfSight(const CColLine &line,
// transform line to model space // transform line to model space
Invert(matrix, matTransform); Invert(matrix, matTransform);
CVuVector newline[2]; CVuVector newline[2];
TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);
if(mindist < 1.0f) if(mindist < 1.0f)
newline[1] = newline[0] + (newline[1] - newline[0])*mindist; newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
@ -1912,7 +1606,7 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space // transform line to model space
Invert(matrix, matTransform); Invert(matrix, matTransform);
CVuVector newline[2]; CVuVector newline[2];
TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2); TransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);
if(mindist < 1.0f) if(mindist < 1.0f)
newline[1] = newline[0] + (newline[1] - newline[0])*mindist; newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
@ -2112,16 +1806,16 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
matAB *= matrixA; matAB *= matrixA;
CVuVector bsphereAB; // bounding sphere of A in B space CVuVector bsphereAB; // bounding sphere of A in B space
TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined TransformPoint(bsphereAB, matAB, modelA.boundingSphere.center); // inlined
bsphereAB.w = modelA.boundingSphere.radius; bsphereAB.w = modelA.boundingSphere.radius;
if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox)) if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox))
return 0; return 0;
// transform modelA's spheres and lines to B space // transform modelA's spheres and lines to B space
TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere)); TransformPoints(aSpheresA, modelA.numSpheres, matAB, &modelA.spheres->center, sizeof(CColSphere));
for(i = 0; i < modelA.numSpheres; i++) for(i = 0; i < modelA.numSpheres; i++)
aSpheresA[i].w = modelA.spheres[i].radius; aSpheresA[i].w = modelA.spheres[i].radius;
TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2); TransformPoints(aLinesA, modelA.numLines*2, matAB, &modelA.lines->p0, sizeof(CColLine)/2);
// Test them against model B's bounding volumes // Test them against model B's bounding volumes
int numSpheresA = 0; int numSpheresA = 0;
@ -2138,7 +1832,7 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
matBA *= matrixB; matBA *= matrixB;
// transform modelB's spheres to A space // transform modelB's spheres to A space
TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere)); TransformPoints(aSpheresB, modelB.numSpheres, matBA, &modelB.spheres->center, sizeof(CColSphere));
for(i = 0; i < modelB.numSpheres; i++) for(i = 0; i < modelB.numSpheres; i++)
aSpheresB[i].w = modelB.spheres[i].radius; aSpheresB[i].w = modelB.spheres[i].radius;
@ -2412,11 +2106,12 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES); assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space // From model A space to model B space
Invert(matrixB, matAB); matAB = Invert(matrixB, matAB);
matAB *= matrixA; matAB *= matrixA;
CColSphere bsphereAB; // bounding sphere of A in B space CColSphere bsphereAB; // bounding sphere of A in B space
bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center); bsphereAB.radius = modelA.boundingSphere.radius;
bsphereAB.center = matAB * modelA.boundingSphere.center;
if(!TestSphereBox(bsphereAB, modelB.boundingBox)) if(!TestSphereBox(bsphereAB, modelB.boundingBox))
return 0; return 0;
// B to A space // B to A space
@ -2449,7 +2144,8 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
int numBoxesB = 0; int numBoxesB = 0;
int numTrianglesB = 0; int numTrianglesB = 0;
for(i = 0; i < modelB.numSpheres; i++){ for(i = 0; i < modelB.numSpheres; i++){
s.Set(modelB.spheres[i].radius, matBA * modelB.spheres[i].center); s.radius = modelB.spheres[i].radius;
s.center = matBA * modelB.spheres[i].center;
if(TestSphereBox(s, modelA.boundingBox)) if(TestSphereBox(s, modelA.boundingBox))
aSphereIndicesB[numSpheresB++] = i; aSphereIndicesB[numSpheresB++] = i;
} }
@ -3038,253 +2734,3 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
} }
/*
* ColModel code
*/
void
CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
{
this->radius = radius;
this->center = center;
this->surface = surf;
this->piece = piece;
}
void
CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
{
this->min = min;
this->max = max;
this->surface = surf;
this->piece = piece;
}
void
CColLine::Set(const CVector &p0, const CVector &p1)
{
this->p0 = p0;
this->p1 = p1;
}
void
CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
{
this->a = a;
this->b = b;
this->c = c;
this->surface = surf;
}
#ifdef VU_COLLISION
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
CVector norm = CrossProduct(vc-va, vb-va);
norm.Normalise();
float d = DotProduct(norm, va);
normal.x = norm.x*4096.0f;
normal.y = norm.y*4096.0f;
normal.z = norm.z*4096.0f;
dist = d*128.0f;
}
#else
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
normal = CrossProduct(vc-va, vb-va);
normal.Normalise();
dist = DotProduct(normal, va);
CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
// find out largest component and its direction
if(an.x > an.y && an.x > an.z)
dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
else if(an.y > an.z)
dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
else
dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
}
#endif
CColModel::CColModel(void)
{
numSpheres = 0;
spheres = nil;
numLines = 0;
lines = nil;
numBoxes = 0;
boxes = nil;
numTriangles = 0;
vertices = nil;
triangles = nil;
trianglePlanes = nil;
level = CGame::currLevel;
ownsCollisionVolumes = true;
}
CColModel::~CColModel(void)
{
RemoveCollisionVolumes();
RemoveTrianglePlanes();
}
void
CColModel::RemoveCollisionVolumes(void)
{
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
}
numSpheres = 0;
numLines = 0;
numBoxes = 0;
numTriangles = 0;
spheres = nil;
lines = nil;
boxes = nil;
vertices = nil;
triangles = nil;
}
void
CColModel::CalculateTrianglePlanes(void)
{
// HACK: allocate space for one more element to stuff the link pointer into
trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
for(int i = 0; i < numTriangles; i++)
trianglePlanes[i].Set(vertices, triangles[i]);
}
void
CColModel::RemoveTrianglePlanes(void)
{
RwFree(trianglePlanes);
trianglePlanes = nil;
}
void
CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
{
assert(trianglePlanes);
*(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
}
CLink<CColModel*>*
CColModel::GetLinkPtr(void)
{
assert(trianglePlanes);
return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
}
void
CColModel::GetTrianglePoint(CVector &v, int i) const
{
v = vertices[i].Get();
}
CColModel&
CColModel::operator=(const CColModel &other)
{
int i;
int numVerts;
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
// copy spheres
if(other.numSpheres){
if(numSpheres != other.numSpheres){
numSpheres = other.numSpheres;
if(spheres)
RwFree(spheres);
spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
}
for(i = 0; i < numSpheres; i++)
spheres[i] = other.spheres[i];
}else{
numSpheres = 0;
if(spheres)
RwFree(spheres);
spheres = nil;
}
// copy lines
if(other.numLines){
if(numLines != other.numLines){
numLines = other.numLines;
if(lines)
RwFree(lines);
lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
}
for(i = 0; i < numLines; i++)
lines[i] = other.lines[i];
}else{
numLines = 0;
if(lines)
RwFree(lines);
lines = nil;
}
// copy boxes
if(other.numBoxes){
if(numBoxes != other.numBoxes){
numBoxes = other.numBoxes;
if(boxes)
RwFree(boxes);
boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
}
for(i = 0; i < numBoxes; i++)
boxes[i] = other.boxes[i];
}else{
numBoxes = 0;
if(boxes)
RwFree(boxes);
boxes = nil;
}
// copy mesh
if(other.numTriangles){
// copy vertices
numVerts = 0;
for(i = 0; i < other.numTriangles; i++){
if(other.triangles[i].a > numVerts)
numVerts = other.triangles[i].a;
if(other.triangles[i].b > numVerts)
numVerts = other.triangles[i].b;
if(other.triangles[i].c > numVerts)
numVerts = other.triangles[i].c;
}
numVerts++;
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
// copy triangles
if(numTriangles != other.numTriangles){
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];
}else{
numTriangles = 0;
if(triangles)
RwFree(triangles);
triangles = nil;
if(vertices)
RwFree(vertices);
vertices = nil;
}
return *this;
}

70
src/collision/Collision.h Normal file
View File

@ -0,0 +1,70 @@
#pragma once
#include "ColModel.h"
#include "Game.h" // for eLevelName
#ifdef VU_COLLISION
#include "VuVector.h"
#endif
struct CStoredCollPoly
{
#ifdef VU_COLLISION
CVuVector verts[3];
#else
CVector verts[3];
#endif
bool valid;
};
// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
#define MAX_COLLISION_POINTS 64
#else
#define MAX_COLLISION_POINTS 32
#endif
class CCollision
{
public:
static eLevelName ms_collisionInMemory;
static CLinkList<CColModel*> ms_colModelCache;
#ifdef NO_ISLAND_LOADING
static bool bAlreadyLoaded;
#endif
static void Init(void);
static void Shutdown(void);
static void Update(void);
static void LoadCollisionWhenINeedIt(bool changeLevel);
static void SortOutCollisionAfterLoad(void);
static void LoadCollisionScreen(eLevelName level);
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
static void CalculateTrianglePlanes(CColModel *model);
// all these return true if there's a collision
static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2);
static bool TestSphereBox(const CColSphere &sph, const CColBox &box);
static bool TestLineBox(const CColLine &line, const CColBox &box);
static bool TestVerticalLineBox(const CColLine &line, const CColBox &box);
static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
};

View File

@ -0,0 +1,36 @@
#pragma once
struct CompressedVector
{
#ifdef COMPRESSED_COL_VECTORS
int16 x, y, z;
CVector Get(void) const { return CVector(x, y, z)/128.0f; };
void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
#ifdef GTA_PS2
void Unpack(uint128 &qword) const {
__asm__ volatile (
"lh $8, 0(%1)\n"
"lh $9, 2(%1)\n"
"lh $10, 4(%1)\n"
"pextlw $10, $8\n"
"pextlw $2, $9, $10\n"
"sq $2, %0\n"
: "=m" (qword)
: "r" (this)
: "$8", "$9", "$10", "$2"
);
}
#else
void Unpack(int32 *qword) const {
qword[0] = x;
qword[1] = y;
qword[2] = z;
qword[3] = 0; // junk
}
#endif
#else
float x, y, z;
CVector Get(void) const { return CVector(x, y, z); };
void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };
#endif
};

View File

@ -1,7 +1,6 @@
#include "common.h" #include "common.h"
#include "TempColModels.h" #include "TempColModels.h"
#include "SurfaceTable.h"
CColModel CTempColModels::ms_colModelPed1; CColModel CTempColModels::ms_colModelPed1;
CColModel CTempColModels::ms_colModelPed2; CColModel CTempColModels::ms_colModelPed2;
@ -21,7 +20,11 @@ CColModel CTempColModels::ms_colModelBonnet1;
CColSphere s_aPedSpheres[3]; CColSphere s_aPedSpheres[3];
CColSphere s_aPed2Spheres[3]; CColSphere s_aPed2Spheres[3];
CColSphere s_aPedGSpheres[4]; CColSphere s_aPedGSpheres[4];
#ifdef FIX_BUGS
CColSphere s_aDoorSpheres[3];
#else
CColSphere s_aDoorSpheres[4]; CColSphere s_aDoorSpheres[4];
#endif
CColSphere s_aBumperSpheres[4]; CColSphere s_aBumperSpheres[4];
CColSphere s_aPanelSpheres[4]; CColSphere s_aPanelSpheres[4];
CColSphere s_aBonnetSpheres[4]; CColSphere s_aBonnetSpheres[4];
@ -37,17 +40,17 @@ CTempColModels::Initialise(void)
colmodel.numSpheres = ARRAY_SIZE(sphrs);\ colmodel.numSpheres = ARRAY_SIZE(sphrs);\
colmodel.spheres = sphrs;\ colmodel.spheres = sphrs;\
colmodel.level = LEVEL_GENERIC;\ colmodel.level = LEVEL_GENERIC;\
colmodel.ownsCollisionVolumes = false;\ colmodel.ownsCollisionVolumes = false;
int i; int i;
ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
ms_colModelBBox.level = LEVEL_GENERIC; ms_colModelBBox.level = LEVEL_GENERIC;
for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {
ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
ms_colModelCutObj[i].level = LEVEL_GENERIC; ms_colModelCutObj[i].level = LEVEL_GENERIC;
} }
@ -69,8 +72,8 @@ CTempColModels::Initialise(void)
s_aPedSpheres[i].piece = 0; s_aPedSpheres[i].piece = 0;
} }
ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f), SURFACE_DEFAULT, 0); ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f));
SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres); SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);
// Ped 2 Spheres // Ped 2 Spheres
@ -88,8 +91,8 @@ CTempColModels::Initialise(void)
s_aPed2Spheres[i].piece = 0; s_aPed2Spheres[i].piece = 0;
} }
ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f));
SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres); SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres);
@ -114,8 +117,8 @@ CTempColModels::Initialise(void)
s_aPedGSpheres[2].piece = 0; s_aPedGSpheres[2].piece = 0;
s_aPedGSpheres[3].piece = 6; s_aPedGSpheres[3].piece = 6;
ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f), SURFACE_DEFAULT, 0); ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f));
SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres); SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres);
@ -129,13 +132,17 @@ CTempColModels::Initialise(void)
s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f); s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f);
s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f);
#ifdef FIX_BUGS
for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) {
#else
for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {
#endif
s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL; s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL;
s_aDoorSpheres[i].piece = 0; s_aDoorSpheres[i].piece = 0;
} }
ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f));
ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f), SURFACE_DEFAULT, 0); ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f));
SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres); SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres);
@ -154,8 +161,8 @@ CTempColModels::Initialise(void)
s_aBumperSpheres[i].piece = 0; s_aBumperSpheres[i].piece = 0;
} }
ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f));
ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f), SURFACE_DEFAULT, 0); ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f));
SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres); SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres);
@ -174,8 +181,8 @@ CTempColModels::Initialise(void)
s_aPanelSpheres[i].piece = 0; s_aPanelSpheres[i].piece = 0;
} }
ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f), SURFACE_DEFAULT, 0); ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f));
SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres); SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres);
@ -194,8 +201,8 @@ CTempColModels::Initialise(void)
s_aBonnetSpheres[i].piece = 0; s_aBonnetSpheres[i].piece = 0;
} }
ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f));
ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f), SURFACE_DEFAULT, 0); ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres); SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres);
@ -214,8 +221,8 @@ CTempColModels::Initialise(void)
s_aBootSpheres[i].piece = 0; s_aBootSpheres[i].piece = 0;
} }
ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f));
ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f), SURFACE_DEFAULT, 0); ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres); SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres);
@ -236,8 +243,8 @@ CTempColModels::Initialise(void)
s_aWheelSpheres[i].piece = 0; s_aWheelSpheres[i].piece = 0;
} }
ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));
ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f), SURFACE_DEFAULT, 0); ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f));
SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres); SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres);
@ -258,8 +265,8 @@ CTempColModels::Initialise(void)
s_aBodyPartSpheres1[i].piece = 0; s_aBodyPartSpheres1[i].piece = 0;
} }
ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f));
ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f), SURFACE_DEFAULT, 0); ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f));
SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1); SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1);
@ -280,8 +287,8 @@ CTempColModels::Initialise(void)
s_aBodyPartSpheres2[i].piece = 0; s_aBodyPartSpheres2[i].piece = 0;
} }
ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f));
ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f), SURFACE_DEFAULT, 0); ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f));
SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2); SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);

View File

@ -0,0 +1,282 @@
#include "common.h"
#ifdef VU_COLLISION
#include "VuVector.h"
#include "VuCollision.h"
#ifndef GTA_PS2
int16 vi01;
CVuVector vf01;
CVuVector vf02;
CVuVector vf03;
CVuVector
DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
{
// center VF12
// p0 VF14
// line VF15
CVuVector ret; // VF16
CVuVector p1 = p0+line;
CVuVector dist0 = center - p0; // VF20
CVuVector dist1 = center - p1; // VF25
float lenSq = line.MagnitudeSqr(); // VF21
float distSq0 = dist0.MagnitudeSqr(); // VF22
float distSq1 = dist1.MagnitudeSqr();
float dot = DotProduct(dist0, line); // VF23
if(dot < 0.0f){
// not above line, closest to p0
ret = p0;
ret.w = distSq0;
return ret;
}
float t = dot/lenSq; // param of nearest point on infinite line
if(t > 1.0f){
// not above line, closest to p1
ret = p1;
ret.w = distSq1;
return ret;
}
// closest to line
ret = p0 + line*t;
ret.w = (ret - center).MagnitudeSqr();
return ret;
}
inline int SignFlags(const CVector &v)
{
int f = 0;
if(v.x < 0.0f) f |= 1;
if(v.y < 0.0f) f |= 2;
if(v.z < 0.0f) f |= 4;
return f;
}
#endif
extern "C" void
LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
const CVuVector &plane)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf13, 0x0(%1)\n"
"lqc2 vf14, 0x0(%2)\n"
"lqc2 vf15, 0x0(%3)\n"
"lqc2 vf16, 0x0(%4)\n"
"lqc2 vf17, 0x0(%5)\n"
"vcallms Vu0LineToTriangleCollisionStart\n"
".set reorder\n"
:
: "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
);
#else
float dot0 = DotProduct(plane, p0);
float dot1 = DotProduct(plane, p1);
float dist0 = plane.w - dot0;
float dist1 = plane.w - dot1;
// if points are on the same side, no collision
if(dist0 * dist1 > 0.0f){
vi01 = 0;
return;
}
CVuVector diff = p1 - p0;
float t = dist0/(dot1 - dot0);
CVuVector p = p0 + diff*t;
p.w = 0.0f;
vf01 = p;
vf03.x = t;
// Check if point is inside
CVector cross1 = CrossProduct(p-v0, v1-v0);
CVector cross2 = CrossProduct(p-v1, v2-v1);
CVector cross3 = CrossProduct(p-v2, v0-v2);
// Only check relevant directions
int flagmask = 0;
if(Abs(plane.x) > 0.5f) flagmask |= 1;
if(Abs(plane.y) > 0.5f) flagmask |= 2;
if(Abs(plane.z) > 0.5f) flagmask |= 4;
int flags1 = SignFlags(cross1) & flagmask;
int flags2 = SignFlags(cross2) & flagmask;
int flags3 = SignFlags(cross3) & flagmask;
// inside if on the same side of all edges
if(flags1 != flags2 || flags1 != flags3){
vi01 = 0;
return;
}
vi01 = 1;
vf02 = plane;
return;
#endif
}
extern "C" void
LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf13, 0x0(%1)\n"
"lqc2 vf14, 0x0(%2)\n"
"lqc2 vf15, 0x10(%2)\n"
"lqc2 vf16, 0x20(%2)\n"
"lqc2 vf17, 0x30(%2)\n"
"vcallms Vu0LineToTriangleCollisionCompressedStart\n"
".set reorder\n"
:
: "r" (&p0), "r" (&p1), "r" (&tri)
);
#else
CVuVector v0, v1, v2, plane;
v0.x = tri.v0[0]/128.0f;
v0.y = tri.v0[1]/128.0f;
v0.z = tri.v0[2]/128.0f;
v0.w = tri.v0[3]/128.0f;
v1.x = tri.v1[0]/128.0f;
v1.y = tri.v1[1]/128.0f;
v1.z = tri.v1[2]/128.0f;
v1.w = tri.v1[3]/128.0f;
v2.x = tri.v2[0]/128.0f;
v2.y = tri.v2[1]/128.0f;
v2.z = tri.v2[2]/128.0f;
v2.w = tri.v2[3]/128.0f;
plane.x = tri.plane[0]/4096.0f;
plane.y = tri.plane[1]/4096.0f;
plane.z = tri.plane[2]/4096.0f;
plane.w = tri.plane[3]/128.0f;
LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
#endif
}
extern "C" void
SphereToTriangleCollision(const CVuVector &sph,
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
const CVuVector &plane)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf14, 0x0(%1)\n"
"lqc2 vf15, 0x0(%2)\n"
"lqc2 vf16, 0x0(%3)\n"
"lqc2 vf17, 0x0(%4)\n"
"vcallms Vu0SphereToTriangleCollisionStart\n"
".set reorder\n"
:
: "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
);
#else
float planedist = DotProduct(plane, sph) - plane.w; // VF02
if(Abs(planedist) > sph.w){
vi01 = 0;
return;
}
// point on plane
CVuVector p = sph - planedist*plane;
p.w = 0.0f;
vf01 = p;
planedist = Abs(planedist);
// edges
CVuVector v01 = v1 - v0;
CVuVector v12 = v2 - v1;
CVuVector v20 = v0 - v2;
// VU code calculates normal again for some weird reason...
// Check sides of point
CVector cross1 = CrossProduct(p-v0, v01);
CVector cross2 = CrossProduct(p-v1, v12);
CVector cross3 = CrossProduct(p-v2, v20);
// Only check relevant directions
int flagmask = 0;
if(Abs(plane.x) > 0.1f) flagmask |= 1;
if(Abs(plane.y) > 0.1f) flagmask |= 2;
if(Abs(plane.z) > 0.1f) flagmask |= 4;
int nflags = SignFlags(plane) & flagmask;
int flags1 = SignFlags(cross1) & flagmask;
int flags2 = SignFlags(cross2) & flagmask;
int flags3 = SignFlags(cross3) & flagmask;
int testcase = 0;
CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
if(flags1 == nflags){
closest += v2;
testcase++;
}
if(flags2 == nflags){
closest += v0;
testcase++;
}
if(flags3 == nflags){
closest += v1;
testcase++;
}
if(testcase == 3){
// inside triangle - dist to plane already checked
vf02 = plane;
vf02.w = vf03.x = planedist;
vi01 = 1;
}else if(testcase == 1){
// outside two sides - closest to point opposide inside edge
vf01 = closest;
vf02 = sph - closest;
float distSq = vf02.MagnitudeSqr();
vi01 = sph.w*sph.w > distSq;
vf03.x = Sqrt(distSq);
vf02 *= 1.0f/vf03.x;
}else{
// inside two sides - closest to third edge
if(flags1 != nflags)
closest = DistanceBetweenSphereAndLine(sph, v0, v01);
else if(flags2 != nflags)
closest = DistanceBetweenSphereAndLine(sph, v1, v12);
else
closest = DistanceBetweenSphereAndLine(sph, v2, v20);
vi01 = sph.w*sph.w > closest.w;
vf01 = closest;
vf02 = sph - closest;
vf03.x = Sqrt(closest.w);
vf02 *= 1.0f/vf03.x;
}
#endif
}
extern "C" void
SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
{
#ifdef GTA_PS2
__asm__ volatile (
".set noreorder\n"
"lqc2 vf12, 0x0(%0)\n"
"lqc2 vf14, 0x0(%1)\n"
"lqc2 vf15, 0x10(%1)\n"
"lqc2 vf16, 0x20(%1)\n"
"lqc2 vf17, 0x30(%1)\n"
"vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
".set reorder\n"
:
: "r" (&sph), "r" (&tri)
);
#else
CVuVector v0, v1, v2, plane;
v0.x = tri.v0[0]/128.0f;
v0.y = tri.v0[1]/128.0f;
v0.z = tri.v0[2]/128.0f;
v0.w = tri.v0[3]/128.0f;
v1.x = tri.v1[0]/128.0f;
v1.y = tri.v1[1]/128.0f;
v1.z = tri.v1[2]/128.0f;
v1.w = tri.v1[3]/128.0f;
v2.x = tri.v2[0]/128.0f;
v2.y = tri.v2[1]/128.0f;
v2.z = tri.v2[2]/128.0f;
v2.w = tri.v2[3]/128.0f;
plane.x = tri.plane[0]/4096.0f;
plane.y = tri.plane[1]/4096.0f;
plane.z = tri.plane[2]/4096.0f;
plane.w = tri.plane[3]/128.0f;
SphereToTriangleCollision(sph, v0, v1, v2, plane);
#endif
}
#endif

View File

@ -0,0 +1,32 @@
#pragma once
struct VuTriangle
{
// Compressed int16 but unpacked
#ifdef GTA_PS2
uint128 v0;
uint128 v1;
uint128 v2;
uint128 plane;
#else
int32 v0[4];
int32 v1[4];
int32 v2[4];
int32 plane[4];
#endif
};
#ifndef GTA_PS2
extern int16 vi01;
extern CVuVector vf01;
extern CVuVector vf02;
extern CVuVector vf03;
#endif
extern "C" {
void LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
void LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri);
void SphereToTriangleCollision(const CVuVector &sph, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
void SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri);
}

View File

@ -103,9 +103,9 @@ void CAutoPilot::Load(uint8*& buf)
m_nNextDirection = ReadSaveBuf<int8>(buf); m_nNextDirection = ReadSaveBuf<int8>(buf);
m_nCurrentLane = ReadSaveBuf<int8>(buf); m_nCurrentLane = ReadSaveBuf<int8>(buf);
m_nNextLane = ReadSaveBuf<int8>(buf); m_nNextLane = ReadSaveBuf<int8>(buf);
m_nDrivingStyle = (eCarDrivingStyle)ReadSaveBuf<uint8>(buf); m_nDrivingStyle = ReadSaveBuf<uint8>(buf);
m_nCarMission = (eCarMission)ReadSaveBuf<uint8>(buf); m_nCarMission = ReadSaveBuf<uint8>(buf);
m_nTempAction = (eCarTempAction)ReadSaveBuf<uint8>(buf); m_nTempAction = ReadSaveBuf<uint8>(buf);
m_nTimeTempAction = ReadSaveBuf<uint32>(buf); m_nTimeTempAction = ReadSaveBuf<uint32>(buf);
m_fMaxTrafficSpeed = ReadSaveBuf<float>(buf); m_fMaxTrafficSpeed = ReadSaveBuf<float>(buf);
m_nCruiseSpeed = ReadSaveBuf<uint8>(buf); m_nCruiseSpeed = ReadSaveBuf<uint8>(buf);

View File

@ -4,7 +4,7 @@
class CVehicle; class CVehicle;
struct CPathNode; struct CPathNode;
enum eCarMission : uint8 enum eCarMission
{ {
MISSION_NONE, MISSION_NONE,
MISSION_CRUISE, MISSION_CRUISE,
@ -28,7 +28,7 @@ enum eCarMission : uint8
MISSION_BLOCKCAR_HANDBRAKESTOP, MISSION_BLOCKCAR_HANDBRAKESTOP,
}; };
enum eCarTempAction : uint8 enum eCarTempAction
{ {
TEMPACT_NONE, TEMPACT_NONE,
TEMPACT_WAIT, TEMPACT_WAIT,
@ -43,7 +43,7 @@ enum eCarTempAction : uint8
TEMPACT_SWERVERIGHT TEMPACT_SWERVERIGHT
}; };
enum eCarDrivingStyle : uint8 enum eCarDrivingStyle
{ {
DRIVINGSTYLE_STOP_FOR_CARS, DRIVINGSTYLE_STOP_FOR_CARS,
DRIVINGSTYLE_SLOW_DOWN_FOR_CARS, DRIVINGSTYLE_SLOW_DOWN_FOR_CARS,
@ -69,9 +69,9 @@ public:
int8 m_nNextDirection; int8 m_nNextDirection;
int8 m_nCurrentLane; int8 m_nCurrentLane;
int8 m_nNextLane; int8 m_nNextLane;
eCarDrivingStyle m_nDrivingStyle; uint8 m_nDrivingStyle;
eCarMission m_nCarMission; uint8 m_nCarMission;
eCarTempAction m_nTempAction; uint8 m_nTempAction;
uint32 m_nTimeTempAction; uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed; float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed; uint8 m_nCruiseSpeed;

View File

@ -539,7 +539,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
} }
eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() uint8 CCarAI::FindPoliceCarMissionForWantedLevel()
{ {
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){
case 0: case 0:

View File

@ -19,7 +19,7 @@ public:
static void TellOccupantsToLeaveCar(CVehicle*); static void TellOccupantsToLeaveCar(CVehicle*);
static void TellCarToRamOtherCar(CVehicle*, CVehicle*); static void TellCarToRamOtherCar(CVehicle*, CVehicle*);
static void TellCarToBlockOtherCar(CVehicle*, CVehicle*); static void TellCarToBlockOtherCar(CVehicle*, CVehicle*);
static eCarMission FindPoliceCarMissionForWantedLevel(); static uint8 FindPoliceCarMissionForWantedLevel();
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*); static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static void MellowOutChaseSpeed(CVehicle*); static void MellowOutChaseSpeed(CVehicle*);
static void MakeWayForCarWithSiren(CVehicle *veh); static void MakeWayForCarWithSiren(CVehicle *veh);

View File

@ -408,11 +408,6 @@ CCarCtrl::GenerateOneRandomCar()
float directionNextLinkX; float directionNextLinkX;
float directionNextLinkY; float directionNextLinkY;
if (positionBetweenNodes < 0.5f) { if (positionBetweenNodes < 0.5f) {
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
positionOnCurrentLinkIncludingLane = CVector( positionOnCurrentLinkIncludingLane = CVector(
@ -442,11 +437,6 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(uint32)((positionBetweenNodes - 0.5f) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); (uint32)((positionBetweenNodes - 0.5f) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
positionOnCurrentLinkIncludingLane = CVector( positionOnCurrentLinkIncludingLane = CVector(
@ -2348,7 +2338,11 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
switch (pVehicle->AutoPilot.m_nDrivingStyle) { switch (pVehicle->AutoPilot.m_nDrivingStyle) {
case DRIVINGSTYLE_STOP_FOR_CARS: case DRIVINGSTYLE_STOP_FOR_CARS:
case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS: case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:
speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle) / pVehicle->AutoPilot.m_nCruiseSpeed; speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle);
#ifdef FIX_BUGS
if (pVehicle->AutoPilot.m_nCruiseSpeed != 0)
#endif
speedStyleMultiplier /= pVehicle->AutoPilot.m_nCruiseSpeed;
break; break;
default: default:
speedStyleMultiplier = 1.0f; speedStyleMultiplier = 1.0f;
@ -2578,7 +2572,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;
@ -2692,7 +2686,7 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
float distance = 30.0f; float distance = 30.0f;
CFire* pNearestFire = gFireManager.FindNearestFire(FindPlayerCoors(), &distance); CFire* pNearestFire = gFireManager.FindNearestFire(FindPlayerCoors(), &distance);
if (pNearestFire) { if (pNearestFire) {
if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 30000){ if (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 35000){
CStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY); CStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY);
CStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE);
if (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){ if (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){

View File

@ -13,6 +13,9 @@
#include "Font.h" #include "Font.h"
#include "Text.h" #include "Text.h"
#include "Vehicle.h" #include "Vehicle.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
@ -60,18 +63,30 @@ 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:
{ {
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(30.0f)); #ifdef FIX_BUGS
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 30));
#else
CFont::SetCentreSize(SCREEN_WIDTH - 30);
#endif
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetPropOn(); CFont::SetPropOn();
uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart;
if (CDarkel::bStandardSoundAndMessages) { if (CDarkel::bStandardSoundAndMessages) {
if (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) { if (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) {
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f)); CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));
#else
CFont::SetScale(1.3f, 1.3f);
#endif
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000))); CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000)));
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
@ -81,7 +96,11 @@ CDarkel::DrawMessages()
} }
} else { } else {
if (timePassedSinceStart < 8000) { if (timePassedSinceStart < 8000) {
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f)); CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));
#else
CFont::SetScale(1.3f, 1.3f);
#endif
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000))); CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000)));
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
@ -90,7 +109,11 @@ CDarkel::DrawMessages()
} }
} }
} }
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(1.5f)); CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(1.5f));
#else
CFont::SetScale(0.75f, 1.5f);
#endif
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetRightJustifyOn(); CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
@ -100,7 +123,15 @@ CDarkel::DrawMessages()
AsciiToUnicode(gString, gUString); AsciiToUnicode(gString, gUString);
if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) { if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) {
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString); #if defined(PS2_HUD) || defined(FIX_BUGS)
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f - 1.0f), SCREEN_SCALE_Y(108.0f + 1.0f), gUString);
#else -
CFont::PrintString(SCREEN_WIDTH-(34.0f - 1.0f), 108.0f + 1.0f, gUString);
#endif
#else
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f + 1.0f), SCREEN_SCALE_Y(108.0f + 1.0f), gUString);
#endif
CFont::SetColor(CRGBA(150, 100, 255, 255)); CFont::SetColor(CRGBA(150, 100, 255, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString);
} }
@ -113,7 +144,16 @@ CDarkel::DrawMessages()
#else #else
#define DARKEL_COUNTER_HEIGHT 128.0f #define DARKEL_COUNTER_HEIGHT 128.0f
#endif #endif
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT + 1.0f), gUString);
#if defined(PS2_HUD) || defined(FIX_BUGS)
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f - 1.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT + 1.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH-(34.0f - 1.0f), DARKEL_COUNTER_HEIGHT + 1.0f, gUString);
#endif
#else
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f + 1.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT + 1.0f), gUString);
#endif
CFont::SetColor(CRGBA(255, 128, 128, 255)); CFont::SetColor(CRGBA(255, 128, 128, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT), gUString); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(DARKEL_COUNTER_HEIGHT), gUString);
#undef DARKEL_COUNTER_HEIGHT #undef DARKEL_COUNTER_HEIGHT
@ -125,13 +165,25 @@ CDarkel::DrawMessages()
uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart;
if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) { if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) {
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); #ifdef FIX_BUGS
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
#else
CFont::SetCentreSize(SCREEN_WIDTH - 20);
#endif
CFont::SetCentreOn(); CFont::SetCentreOn();
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));
#else
CFont::SetScale(1.5f, 1.5f);
#endif
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000))); CFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000)));
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
#ifdef FIX_BUGS
int y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f); int y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f);
#else
int y = (SCREEN_HEIGHT / 2 + 25) - (timePassedSinceStart * 0.01f);
#endif
CFont::PrintString(SCREEN_WIDTH / 2, y, TheText.Get("KF_3")); CFont::PrintString(SCREEN_WIDTH / 2, y, TheText.Get("KF_3"));
} }
} }
@ -171,6 +223,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) {
@ -185,6 +241,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
@ -210,6 +270,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++;
} }
@ -301,6 +365,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

@ -19,6 +19,7 @@
#include "Fire.h" #include "Fire.h"
#include "Script.h" #include "Script.h"
#include "Garages.h" #include "Garages.h"
#include "screendroplets.h"
uint8 CGameLogic::ActivePlayers; uint8 CGameLogic::ActivePlayers;
@ -117,6 +118,9 @@ CGameLogic::Update()
} }
} }
CEventList::Initialise(); CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@ -196,6 +200,9 @@ CGameLogic::Update()
} }
} }
CEventList::Initialise(); CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
@ -245,6 +252,9 @@ CGameLogic::Update()
} }
} }
CEventList::Initialise(); CEventList::Initialise();
#ifdef SCREEN_DROPLETS
ScreenDroplets::Initialise();
#endif
CMessages::ClearMessages(); CMessages::ClearMessages();
CCarCtrl::ClearInterestingVehicleList(); CCarCtrl::ClearInterestingVehicleList();
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1); CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);

View File

@ -129,7 +129,7 @@ int32 CGarages::PoliceCarsCollected;
CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
int32 CGarages::AudioEntity = AEHANDLE_NONE; int32 hGarages = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES]; CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde; bool CGarages::bCamShouldBeOutisde;
@ -156,12 +156,12 @@ void CGarages::Init(void)
aCarsInSafeHouse2[i].Init(); aCarsInSafeHouse2[i].Init();
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
aCarsInSafeHouse3[i].Init(); aCarsInSafeHouse3[i].Init();
AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1); hGarages = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
if (AudioEntity >= 0) if (hGarages >= 0)
DMAudio.SetEntityStatus(AudioEntity, 1); DMAudio.SetEntityStatus(hGarages, true);
AddOne( AddOne(
CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1, CVector(CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1),
CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2, CVector(CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2),
GARAGE_CRUSHER, 0); GARAGE_CRUSHER, 0);
} }
@ -169,20 +169,18 @@ void CGarages::Init(void)
void CGarages::Shutdown(void) void CGarages::Shutdown(void)
{ {
NumGarages = 0; NumGarages = 0;
if (AudioEntity < 0) if (hGarages < 0)
return; return;
DMAudio.DestroyEntity(AudioEntity); DMAudio.DestroyEntity(hGarages);
AudioEntity = AEHANDLE_NONE; hGarages = AEHANDLE_NONE;
} }
#endif #endif
void CGarages::Update(void) void CGarages::Update(void)
{ {
static int GarageToBeTidied = 0; static int GarageToBeTidied = 0;
#ifndef PS2
if (CReplay::IsPlayingBack()) if (CReplay::IsPlayingBack())
return; return;
#endif
bCamShouldBeOutisde = false; bCamShouldBeOutisde = false;
TheCamera.pToGarageWeAreIn = nil; TheCamera.pToGarageWeAreIn = nil;
TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = nil; TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = nil;
@ -202,23 +200,23 @@ void CGarages::Update(void)
aGarages[GarageToBeTidied].TidyUpGarage(); aGarages[GarageToBeTidied].TidyUpGarage();
} }
int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId) int16 CGarages::AddOne(CVector p1, CVector p2, uint8 type, int32 targetId)
{ {
if (NumGarages >= NUM_GARAGES) { if (NumGarages >= NUM_GARAGES) {
assert(0); assert(0);
return NumGarages++; return NumGarages++;
} }
CGarage* pGarage = &aGarages[NumGarages]; CGarage* pGarage = &aGarages[NumGarages];
pGarage->m_fX1 = Min(X1, X2); pGarage->m_fX1 = Min(p1.x, p2.x);
pGarage->m_fX2 = Max(X1, X2); pGarage->m_fX2 = Max(p1.x, p2.x);
pGarage->m_fY1 = Min(Y1, Y2); pGarage->m_fY1 = Min(p1.y, p2.y);
pGarage->m_fY2 = Max(Y1, Y2); pGarage->m_fY2 = Max(p1.y, p2.y);
pGarage->m_fZ1 = Min(Z1, Z2); pGarage->m_fZ1 = Min(p1.z, p2.z);
pGarage->m_fZ2 = Max(Z1, Z2); pGarage->m_fZ2 = Max(p1.z, p2.z);
pGarage->m_pDoor1 = nil; pGarage->m_pDoor1 = nil;
pGarage->m_pDoor2 = nil; pGarage->m_pDoor2 = nil;
pGarage->m_fDoor1Z = Z1; pGarage->m_fDoor1Z = p1.z;
pGarage->m_fDoor2Z = Z1; pGarage->m_fDoor2Z = p1.z;
pGarage->m_eGarageType = type; pGarage->m_eGarageType = type;
pGarage->m_bRecreateDoorOnNextRefresh = false; pGarage->m_bRecreateDoorOnNextRefresh = false;
pGarage->m_bRotatedDoor = false; pGarage->m_bRotatedDoor = false;
@ -285,7 +283,7 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z
return NumGarages++; return NumGarages++;
} }
void CGarages::ChangeGarageType(int16 garage, eGarageType type, int32 mi) void CGarages::ChangeGarageType(int16 garage, uint8 type, int32 mi)
{ {
CGarage* pGarage = &aGarages[garage]; CGarage* pGarage = &aGarages[garage];
pGarage->m_eGarageType = type; pGarage->m_eGarageType = type;
@ -368,7 +366,7 @@ void CGarage::Update()
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
CStats::CheckPointReachedSuccessfully(); CStats::CheckPointReachedSuccessfully();
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
@ -464,7 +462,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENEDCONTAINSCAR; m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -510,7 +508,7 @@ void CGarage::Update()
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -575,7 +573,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENEDCONTAINSCAR; m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -599,7 +597,8 @@ void CGarage::Update()
} }
} }
else if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && else if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) &&
!IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) { !IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f) &&
!IsAnyOtherCarTouchingGarage(m_pTarget)) {
CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE); CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
m_eGarageState = GS_CLOSING; m_eGarageState = GS_CLOSING;
@ -609,7 +608,7 @@ void CGarage::Update()
case GS_CLOSING: case GS_CLOSING:
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_bClosingWithoutTargetCar) if (m_bClosingWithoutTargetCar)
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
else { else {
@ -639,7 +638,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -676,7 +675,7 @@ void CGarage::Update()
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_pTarget) { if (m_pTarget) {
DestroyVehicleAndDriverAndPassengers(m_pTarget); DestroyVehicleAndDriverAndPassengers(m_pTarget);
m_pTarget = nil; m_pTarget = nil;
@ -723,7 +722,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -772,7 +771,7 @@ void CGarage::Update()
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_pTarget) { if (m_pTarget) {
MarkThisCarAsCollectedForCraig(m_pTarget->GetModelIndex()); MarkThisCarAsCollectedForCraig(m_pTarget->GetModelIndex());
DestroyVehicleAndDriverAndPassengers(m_pTarget); DestroyVehicleAndDriverAndPassengers(m_pTarget);
@ -812,7 +811,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -833,7 +832,7 @@ void CGarage::Update()
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
} }
if (!IsGarageEmpty()) if (!IsGarageEmpty())
m_eGarageState = GS_OPENING; m_eGarageState = GS_OPENING;
@ -844,7 +843,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -893,7 +892,7 @@ void CGarage::Update()
m_pTarget = nil; m_pTarget = nil;
m_eGarageState = GS_AFTERDROPOFF; m_eGarageState = GS_AFTERDROPOFF;
m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
} }
} }
else else
@ -913,7 +912,7 @@ void CGarage::Update()
m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED); m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED);
if (m_fDoorPos == HALFPI) { if (m_fDoorPos == HALFPI) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateCrusherAngle(); UpdateCrusherAngle();
break; break;
@ -945,7 +944,7 @@ void CGarage::Update()
case GS_CLOSING: case GS_CLOSING:
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
if (m_bClosingWithoutTargetCar) if (m_bClosingWithoutTargetCar)
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
else { else {
@ -974,7 +973,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -994,7 +993,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1014,7 +1013,7 @@ void CGarage::Update()
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1022,7 +1021,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1045,8 +1044,8 @@ void CGarage::Update()
// Close car doors either if player is far, or if he is in vehicle and garage is full, // Close car doors either if player is far, or if he is in vehicle and garage is full,
// or if player is very very far so that we can remove whatever is blocking garage door without him noticing // or if player is very very far so that we can remove whatever is blocking garage door without him noticing
if ((distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR) || if ((distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR) ||
!FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT) && !FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT)) &&
!IsAnyCarBlockingDoor())) !IsAnyCarBlockingDoor())
m_eGarageState = GS_CLOSING; m_eGarageState = GS_CLOSING;
else if (FindPlayerVehicle() && else if (FindPlayerVehicle() &&
CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >= CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=
@ -1064,7 +1063,7 @@ void CGarage::Update()
if (!IsPlayerOutsideGarage()) if (!IsPlayerOutsideGarage())
m_eGarageState = GS_OPENING; m_eGarageState = GS_OPENING;
else if (m_fDoorPos == 0.0f) { else if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
switch (m_eGarageType) { switch (m_eGarageType) {
case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break; case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break;
@ -1111,7 +1110,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1136,7 +1135,7 @@ void CGarage::Update()
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) { if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED; m_eGarageState = GS_FULLYCLOSED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1152,7 +1151,7 @@ void CGarage::Update()
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == m_fDoorHeight) { if (m_fDoorPos == m_fDoorHeight) {
m_eGarageState = GS_OPENED; m_eGarageState = GS_OPENED;
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); DMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);
} }
UpdateDoorsHeight(); UpdateDoorsHeight();
break; break;
@ -1260,9 +1259,9 @@ bool CGarage::IsPlayerOutsideGarage()
bool CGarage::IsEntityTouching3D(CEntity * pEntity) bool CGarage::IsEntityTouching3D(CEntity * pEntity)
{ {
float radius = pEntity->GetBoundRadius(); float radius = pEntity->GetBoundRadius();
if (pEntity->GetPosition().x - radius < m_fX1 || pEntity->GetPosition().x + radius > m_fX2 || if (m_fX1 - radius > pEntity->GetPosition().x || m_fX2 + radius < pEntity->GetPosition().x ||
pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 || m_fY1 - radius > pEntity->GetPosition().y || m_fY2 + radius < pEntity->GetPosition().y ||
pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2) m_fZ1 - radius > pEntity->GetPosition().z || m_fZ2 + radius < pEntity->GetPosition().z)
return false; return false;
CColModel* pColModel = pEntity->GetColModel(); CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) { for (int i = 0; i < pColModel->numSpheres; i++) {
@ -1271,9 +1270,9 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 && if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
pos.y + radius > m_fY1 && pos.y - radius < m_fY2 && pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2) pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
return false;
}
return true; return true;
}
return false;
} }
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin) bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
@ -1387,7 +1386,9 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
if (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { if (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
CWorld::Remove(pVehicle); CWorld::Remove(pVehicle);
delete pVehicle; delete pVehicle;
return; // WHY? #ifndef FIX_BUGS
return; // makes no sense
#endif
} }
} }
} }
@ -1396,44 +1397,68 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
void CGarages::PrintMessages() void CGarages::PrintMessages()
{ {
if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) { if (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) {
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f)); // BUG: game doesn't use macro here. #ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f));
#else
CFont::SetScale(1.2f, 1.5f);
#endif
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); #ifdef FIX_BUGS
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 50));
#else
CFont::SetCentreSize(SCREEN_WIDTH - 50);
#endif
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(CRGBA(0, 0, 0, 255));
#if defined(PS2) || defined (FIX_BUGS) #if defined(PS2_HUD) || defined (FIX_BUGS)
float y_offset = SCREEN_HEIGHT / 3; // THIS is PS2 calculation float y_offset = SCREEN_HEIGHT / 3; // THIS is PS2 calculation
#else #else
float y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements float y_offset = SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(84.0f); // This is PC and results in text being written over some HUD elements
#endif #endif
if (MessageNumberInString2 < 0) { if (MessageNumberInString2 >= 0) {
if (MessageNumberInString < 0) { CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString)); #ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
#endif
CFont::SetColor(CRGBA(89, 115, 150, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
#endif
}
else if (MessageNumberInString >= 0) {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2 + 2.0f, y_offset - 40.0f + 2.0f, gUString);
#endif
CFont::SetColor(CRGBA(89, 115, 150, 255)); CFont::SetColor(CRGBA(89, 115, 150, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
#else
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - 40.0f, gUString);
#endif
}
else {
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
#else
CFont::PrintString(SCREEN_WIDTH / 2 - 2.0f, y_offset - 2.0f, TheText.Get(MessageIDString));
#endif
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString)); CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
} }
else {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
else {
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
CFont::SetColor(CRGBA(89, 115, 150, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
} }
} }
@ -1508,41 +1533,54 @@ void CGarage::UpdateCrusherShake(float X, float Y)
m_pDoor2->GetMatrix().GetPosition().y -= Y; m_pDoor2->GetMatrix().GetPosition().y -= Y;
} }
// 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)
{
bool bNeedToFindDoorEntities = false;
if (pDoor) {
if (bIsDummy) {
if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex((CDummy*)pDoor)))
return true;
if (nIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)pDoor) & 0x7F))
bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex()))
return true;
}
else {
if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex((CObject*)pDoor)))
return true;
if (nIndex != (CPools::GetObjectPool()->GetIndex((CObject*)pDoor) & 0x7F))
bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(pDoor->GetModelIndex()))
return true;
}
}
return bNeedToFindDoorEntities;
}
void CGarage::RefreshDoorPointers(bool bCreate) void CGarage::RefreshDoorPointers(bool bCreate)
{ {
bool bNeedToFindDoorEntities = true; bool bNeedToFindDoorEntities = bCreate || m_bRecreateDoorOnNextRefresh;
if (!bCreate && !m_bRecreateDoorOnNextRefresh)
bNeedToFindDoorEntities = false;
m_bRecreateDoorOnNextRefresh = false; m_bRecreateDoorOnNextRefresh = false;
if (DoINeedToRefreshPointer(m_pDoor1, m_bDoor1IsDummy, m_bDoor1PoolIndex)) if (m_pDoor1) {
if (m_bDoor1IsDummy) {
if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor1)))
bNeedToFindDoorEntities = true; bNeedToFindDoorEntities = true;
if (DoINeedToRefreshPointer(m_pDoor2, m_bDoor2IsDummy, m_bDoor2PoolIndex)) else {
if (m_bDoor1PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor1) & 0x7F))
bNeedToFindDoorEntities = true; bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))
bNeedToFindDoorEntities = true;
}
}
else {
if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor1)))
bNeedToFindDoorEntities = true;
else {
if (m_bDoor1PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor1) & 0x7F))
bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))
bNeedToFindDoorEntities = true;
}
}
}
if (m_pDoor2) {
if (m_bDoor2IsDummy) {
if (CPools::GetDummyPool()->IsFreeSlot(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor2)))
bNeedToFindDoorEntities = true;
else {
if (m_bDoor2PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor2) & 0x7F))
bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))
bNeedToFindDoorEntities = true;
}
}
else {
if (CPools::GetObjectPool()->IsFreeSlot(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor2)))
bNeedToFindDoorEntities = true;
else {
if (m_bDoor2PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor2) & 0x7F))
bNeedToFindDoorEntities = true;
if (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))
bNeedToFindDoorEntities = true;
}
}
}
if (bNeedToFindDoorEntities) if (bNeedToFindDoorEntities)
FindDoorsEntities(); FindDoorsEntities();
} }
@ -2158,7 +2196,7 @@ void CGarages::CloseHideOutGaragesBeforeSave()
} }
} }
int32 CGarages::CountCarsInHideoutGarage(eGarageType type) int32 CGarages::CountCarsInHideoutGarage(uint8 type)
{ {
int32 total = 0; int32 total = 0;
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) { for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
@ -2178,7 +2216,7 @@ int32 CGarages::CountCarsInHideoutGarage(eGarageType type)
return total; return total;
} }
int32 CGarages::FindMaxNumStoredCarsForGarage(eGarageType type) int32 CGarages::FindMaxNumStoredCarsForGarage(uint8 type)
{ {
switch (type) { switch (type) {
case GARAGE_HIDEOUT_ONE: case GARAGE_HIDEOUT_ONE:

View File

@ -7,7 +7,7 @@
class CVehicle; class CVehicle;
class CCamera; class CCamera;
enum eGarageState : int8 enum eGarageState
{ {
GS_FULLYCLOSED, GS_FULLYCLOSED,
GS_OPENED, GS_OPENED,
@ -18,7 +18,7 @@ enum eGarageState : int8
GS_AFTERDROPOFF, GS_AFTERDROPOFF,
}; };
enum eGarageType : int8 enum eGarageType
{ {
GARAGE_NONE, GARAGE_NONE,
GARAGE_MISSION, GARAGE_MISSION,
@ -81,8 +81,8 @@ VALIDATE_SIZE(CStoredCar, 0x28);
class CGarage class CGarage
{ {
eGarageType m_eGarageType; uint8 m_eGarageType;
eGarageState m_eGarageState; uint8 m_eGarageState;
bool field_2; // unused bool field_2; // unused
bool m_bClosingWithoutTargetCar; bool m_bClosingWithoutTargetCar;
bool m_bDeactivated; bool m_bDeactivated;
@ -198,7 +198,6 @@ class CGarages
static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
static int32 AudioEntity;
static bool bCamShouldBeOutisde; static bool bCamShouldBeOutisde;
public: public:
@ -208,8 +207,8 @@ public:
#endif #endif
static void Update(void); static void Update(void);
static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId); static int16 AddOne(CVector pos1, CVector pos2, uint8 type, int32 targetId);
static void ChangeGarageType(int16, eGarageType, int32); static void ChangeGarageType(int16, uint8, int32);
static void PrintMessages(void); static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16); static void TriggerMessage(const char* text, int16, uint16 time, int16);
static void SetTargetCarForMissonGarage(int16, CVehicle*); static void SetTargetCarForMissonGarage(int16, CVehicle*);
@ -245,11 +244,14 @@ private:
static bool IsCarSprayable(CVehicle*); static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32); static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void); static void CloseHideOutGaragesBeforeSave(void);
static int32 CountCarsInHideoutGarage(eGarageType); static int32 CountCarsInHideoutGarage(uint8);
static int32 FindMaxNumStoredCarsForGarage(eGarageType); static int32 FindMaxNumStoredCarsForGarage(uint8);
static int32 GetBombTypeForGarageType(eGarageType type) { return type - GARAGE_BOMBSHOP1 + 1; } static int32 GetBombTypeForGarageType(uint8 type) { return type - GARAGE_BOMBSHOP1 + 1; }
static int32 GetCarsCollectedIndexForGarageType(eGarageType type) { return type - GARAGE_COLLECTCARS_1; } static int32 GetCarsCollectedIndexForGarageType(uint8 type) { return type - GARAGE_COLLECTCARS_1; }
friend class cAudioManager; friend class cAudioManager;
friend class CGarage; friend class CGarage;
#ifdef FIX_BUGS
friend class CReplay;
#endif
}; };

87
src/control/NameGrid.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "common.h"
#include "NameGrid.h"
// TODO: reverse mobile code
CPlayerName::CPlayerName()
{
// TODO
}
void
CPlayerName::DisplayName(int)
{
// TODO
}
CRow::CRow()
{
// TODO
}
void
CRow::SetLetter(int, wchar *)
{
// TODO
}
CGrid::CGrid()
{
// TODO
}
void
CGrid::ProcessAnyLeftJustDown()
{
unk_int2--;
}
void
CGrid::ProcessAnyRightJustDown()
{
unk_int2++;
}
void
CGrid::ProcessAnyUpJustDown()
{
unk_int1--;
}
void
CGrid::ProcessAnyDownJustDown()
{
unk_int1++;
}
void
CGrid::AllDoneMakePlayerName()
{
// TODO
}
void
CGrid::ProcessDPadCrossJustDown()
{
// TODO
}
void
CGrid::DisplayGrid()
{
// TODO
}
void
CGrid::ProcessControllerInput()
{
// TODO
}
void
CGrid::Process()
{
ProcessControllerInput();
DisplayGrid();
playerName.DisplayName(2 * playerName.unk_4c);
}

53
src/control/NameGrid.h Normal file
View File

@ -0,0 +1,53 @@
#pragma once
// TODO: reverse mobile code
class CPlayerName
{
friend class CGrid;
float x;
float y;
wchar unk_8[34];
int unk_4c;
public:
CPlayerName();
void DisplayName(int);
};
class CRow
{
friend class CGrid;
int unk_0;
int unk_4;
wchar unk_8[20];
int unk_30;
public:
CRow();
void SetLetter(int, wchar *);
};
class CGrid
{
CRow rows[5];
int unk_int1;
int unk_int2;
int unk_int3;
float unk_float1;
float unk_float2;
CPlayerName playerName;
char unk2[4];
char unk3[4];
public:
CGrid();
void ProcessAnyLeftJustDown();
void ProcessAnyRightJustDown();
void ProcessAnyUpJustDown();
void ProcessAnyDownJustDown();
void AllDoneMakePlayerName();
void ProcessDPadCrossJustDown();
void DisplayGrid();
void ProcessControllerInput();
void Process();
};

View File

@ -542,6 +542,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
int done, cont; int done, cont;
int tileStart; int tileStart;
#ifndef MASTER
for (i = 0; i < m_numMapObjects-1; i++)
for (j = i+1; j < m_numMapObjects; j++) {
CTreadable *obj1 = m_mapObjects[i];
CTreadable *obj2 = m_mapObjects[j];
if (obj1->GetModelIndex() == obj2->GetModelIndex() &&
obj1->GetPosition().x == obj2->GetPosition().x && obj1->GetPosition().y == obj2->GetPosition().y && obj1->GetPosition().z == obj2->GetPosition().z &&
obj1->GetRight().x == obj2->GetRight().x && obj1->GetForward().x == obj2->GetForward().x && obj1->GetUp().x == obj2->GetUp().x &&
obj1->GetRight().y == obj2->GetRight().y && obj1->GetForward().y == obj2->GetForward().y && obj1->GetUp().y == obj2->GetUp().y &&
obj1->GetRight().z == obj2->GetRight().z && obj1->GetForward().z == obj2->GetForward().z && obj1->GetUp().z == obj2->GetUp().z) {
printf("THIS IS VERY BAD INDEED. FIX IMMEDIATELY!!!\n");
printf("Double road objects at the following coors: %f %f %f\n", obj1->GetPosition().x, obj1->GetPosition().y, obj1->GetPosition().z);
}
}
#endif // !MASTER
oldNumPathNodes = m_numPathNodes; oldNumPathNodes = m_numPathNodes;
oldNumLinks = m_numConnections; oldNumLinks = m_numConnections;
@ -1633,10 +1649,18 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1); DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1);
else else
DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1); DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1);
#ifdef FIX_BUGS
// dist has GenerationDistMultiplier as a factor, so our reference dist should have it too
if(type == PATH_CAR)
return dist < 160.0f*TheCamera.GenerationDistMultiplier;
else
return dist < 100.0f*TheCamera.GenerationDistMultiplier;
#else
if(type == PATH_CAR) if(type == PATH_CAR)
return dist < 160.0f; return dist < 160.0f;
else else
return dist < 100.0f; return dist < 100.0f;
#endif
} }
void void

View File

@ -67,7 +67,7 @@ CPhoneInfo::Update(void)
} else { } else {
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PHONE); CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PHONE);
if (player->m_nPedState == PED_MAKE_CALL) if (player->m_nPedState == PED_MAKE_CALL)
player->m_nPedState = PED_IDLE; player->SetPedState(PED_IDLE);
} }
} }
bool notInCar; bool notInCar;
@ -114,7 +114,7 @@ CPhoneInfo::Update(void)
player->m_fRotationCur = angleToFace; player->m_fRotationCur = angleToFace;
player->m_fRotationDest = angleToFace; player->m_fRotationDest = angleToFace;
player->SetHeading(angleToFace); player->SetHeading(angleToFace);
player->m_nPedState = PED_MAKE_CALL; player->SetPedState(PED_MAKE_CALL);
CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PHONE); CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PHONE);
TheCamera.SetWideScreenOn(); TheCamera.SetWideScreenOn();
playerInfo->MakePlayerSafe(true); playerInfo->MakePlayerSafe(true);
@ -387,7 +387,7 @@ INITSAVEBUF
// Convert entity pointer to building pool index while saving // Convert entity pointer to building pool index while saving
if (phone->m_pEntity) { if (phone->m_pEntity) {
phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex((CBuilding*)phone->m_pEntity) + 1); phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1);
} }
} }
VALIDATESAVEBUF(*size) VALIDATESAVEBUF(*size)
@ -412,7 +412,7 @@ PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg)
ped->bUpdateAnimHeading = true; ped->bUpdateAnimHeading = true;
if (ped->m_nPedState == PED_MAKE_CALL) if (ped->m_nPedState == PED_MAKE_CALL)
ped->m_nPedState = PED_IDLE; ped->SetPedState(PED_IDLE);
} }
void void

View File

@ -54,20 +54,15 @@ uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 25
uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 }; uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f }; float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
void
CPickup::RemoveKeepType() inline void
CPickup::Remove()
{ {
CWorld::Remove(m_pObject); CWorld::Remove(m_pObject);
delete m_pObject; delete m_pObject;
m_bRemoved = true; m_bRemoved = true;
m_pObject = nil; m_pObject = nil;
}
void
CPickup::Remove()
{
RemoveKeepType();
m_eType = PICKUP_NONE; m_eType = PICKUP_NONE;
} }
@ -76,11 +71,11 @@ CPickup::GiveUsAPickUpObject(int32 handle)
{ {
CObject *object; CObject *object;
if (handle <= 0) object = new CObject(m_eModelIndex, false); if (handle >= 0) {
else {
CPools::MakeSureSlotInObjectPoolIsEmpty(handle); CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
object = new(handle) CObject(m_eModelIndex, false); object = new (handle) CObject(m_eModelIndex, false);
} } else
object = new CObject(m_eModelIndex, false);
if (object == nil) return nil; if (object == nil) return nil;
object->ObjectCreatedBy = MISSION_OBJECT; object->ObjectCreatedBy = MISSION_OBJECT;
@ -131,7 +126,6 @@ CPickup::GiveUsAPickUpObject(int32 handle)
bool bool
CPickup::CanBePickedUp(CPlayerPed *player) CPickup::CanBePickedUp(CPlayerPed *player)
{ {
assert(m_pObject != nil);
bool cannotBePickedUp = bool cannotBePickedUp =
(m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f) (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
|| (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
@ -144,6 +138,7 @@ bool
CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
{ {
float waterLevel; float waterLevel;
bool result = false;
if (m_bRemoved) { if (m_bRemoved) {
if (CTimer::GetTimeInMilliseconds() > m_nTimer) { if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
@ -204,9 +199,12 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex())); player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE); DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
} }
RemoveKeepType(); result = true;
CWorld::Remove(m_pObject);
delete m_pObject;
m_pObject = nil;
m_nTimer = CTimer::GetTimeInMilliseconds() + 5000; m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
return true; m_bRemoved = true;
} }
break; break;
case PICKUP_ON_STREET: case PICKUP_ON_STREET:
@ -235,8 +233,12 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
} }
RemoveKeepType(); result = true;
return true; CWorld::Remove(m_pObject);
delete m_pObject;
m_pObject = nil;
m_bRemoved = true;
break;
case PICKUP_ONCE: case PICKUP_ONCE:
case PICKUP_ONCE_TIMEOUT: case PICKUP_ONCE_TIMEOUT:
if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
@ -247,8 +249,9 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
} }
DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
} }
result = true;
Remove(); Remove();
return true; break;
case PICKUP_COLLECTABLE1: case PICKUP_COLLECTABLE1:
CWorld::Players[playerId].m_nCollectedPackages++; CWorld::Players[playerId].m_nCollectedPackages++;
CWorld::Players[playerId].m_nMoney += 1000; CWorld::Players[playerId].m_nMoney += 1000;
@ -260,18 +263,20 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
} else } else
CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
result = true;
Remove(); Remove();
DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
return true; break;
case PICKUP_MONEY: case PICKUP_MONEY:
CWorld::Players[playerId].m_nMoney += m_nQuantity; CWorld::Players[playerId].m_nMoney += m_nQuantity;
sprintf(gString, "$%d", m_nQuantity); sprintf(gString, "$%d", m_nQuantity);
#ifdef MONEY_MESSAGES #ifdef MONEY_MESSAGES
CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f); CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
#endif #endif
result = true;
Remove(); Remove();
DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
return true; break;
default: default:
break; break;
} }
@ -298,7 +303,9 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
touched = true; touched = true;
break; // added break here #ifdef FIX_BUGS
break;
#endif
} }
} }
@ -320,12 +327,17 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
bool explode = false; bool explode = false;
if (CTimer::GetTimeInMilliseconds() > m_nTimer) if (CTimer::GetTimeInMilliseconds() > m_nTimer)
explode = true; explode = true;
else {// added else here since vehicle lookup is useless #ifdef FIX_BUGS
else// added else here since vehicle lookup is useless
#endif
{
for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
explode = true; explode = true;
break; // added break here #ifdef FIX_BUGS
break;
#endif
} }
} }
} }
@ -341,19 +353,19 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
m_pObject->GetMatrix().UpdateRW(); m_pObject->GetMatrix().UpdateRW();
m_pObject->UpdateRwFrame(); m_pObject->UpdateRwFrame();
if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z) if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false) && waterLevel >= m_pObject->GetPosition().z)
m_eType = PICKUP_FLOATINGPACKAGE_FLOATING; m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
break; break;
case PICKUP_FLOATINGPACKAGE_FLOATING: case PICKUP_FLOATINGPACKAGE_FLOATING:
if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
m_pObject->GetMatrix().GetPosition().z = waterLevel; m_pObject->GetMatrix().GetPosition().z = waterLevel;
m_pObject->GetMatrix().UpdateRW(); m_pObject->GetMatrix().UpdateRW();
m_pObject->UpdateRwFrame(); m_pObject->UpdateRwFrame();
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
Remove(); Remove();
result = true;
DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0); DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
return true;
} }
break; break;
default: break; default: break;
@ -361,7 +373,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
} }
if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer) if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
Remove(); Remove();
return false; return result;
} }
void void
@ -523,7 +535,7 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan
if (slot >= NUMPICKUPS) return -1; if (slot >= NUMPICKUPS) return -1;
aPickUps[slot].m_eType = (ePickupType)type; aPickUps[slot].m_eType = type;
aPickUps[slot].m_bRemoved = false; aPickUps[slot].m_bRemoved = false;
aPickUps[slot].m_nQuantity = quantity; aPickUps[slot].m_nQuantity = quantity;
if (type == PICKUP_ONCE_TIMEOUT) if (type == PICKUP_ONCE_TIMEOUT)
@ -628,7 +640,7 @@ CPickups::Update()
#ifdef CAMERA_PICKUP #ifdef CAMERA_PICKUP
if ( bPickUpcamActivated ) // taken from PS2 if ( bPickUpcamActivated ) // taken from PS2
{ {
float dist = (FindPlayerCoors() - StaticCamCoors).Magnitude2D(); float dist = Distance2D(StaticCamCoors, FindPlayerCoors());
float mult; float mult;
if ( dist < 10.0f ) if ( dist < 10.0f )
mult = 1.0f - (dist / 10.0f ); mult = 1.0f - (dist / 10.0f );
@ -644,8 +656,7 @@ CPickups::Update()
TheCamera.TakeControl(FindPlayerVehicle(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT); TheCamera.TakeControl(FindPlayerVehicle(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT);
} }
if ( FindPlayerVehicle() != pPlayerVehicle if ( FindPlayerVehicle() != pPlayerVehicle || Distance(StaticCamCoors, FindPlayerCoors()) > 40.0f
|| (FindPlayerCoors() - StaticCamCoors).Magnitude() > 40.0f
|| ((CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 60000) ) || ((CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 60000) )
{ {
TheCamera.RestoreWithJumpCut(); TheCamera.RestoreWithJumpCut();
@ -715,7 +726,7 @@ CPickups::DoPickUpEffects(CEntity *entity)
CObject *object = (CObject*)entity; CObject *object = (CObject*)entity;
if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue) { if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue) {
float dist = (TheCamera.GetPosition() - pos).Magnitude(); float dist = Distance2D(pos, TheCamera.GetPosition());
const float MAXDIST = 12.0f; const float MAXDIST = 12.0f;
if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) { if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
@ -746,7 +757,7 @@ void
CPickups::DoMineEffects(CEntity *entity) CPickups::DoMineEffects(CEntity *entity)
{ {
const CVector &pos = entity->GetPosition(); const CVector &pos = entity->GetPosition();
float dist = (TheCamera.GetPosition() - pos).Magnitude(); float dist = Distance(pos, TheCamera.GetPosition());
const float MAXDIST = 20.0f; const float MAXDIST = 20.0f;
if (dist < MAXDIST) { if (dist < MAXDIST) {
@ -765,7 +776,7 @@ void
CPickups::DoMoneyEffects(CEntity *entity) CPickups::DoMoneyEffects(CEntity *entity)
{ {
const CVector &pos = entity->GetPosition(); const CVector &pos = entity->GetPosition();
float dist = (TheCamera.GetPosition() - pos).Magnitude(); float dist = Distance(pos, TheCamera.GetPosition());
const float MAXDIST = 20.0f; const float MAXDIST = 20.0f;
if (dist < MAXDIST) { if (dist < MAXDIST) {
@ -784,7 +795,7 @@ void
CPickups::DoCollectableEffects(CEntity *entity) CPickups::DoCollectableEffects(CEntity *entity)
{ {
const CVector &pos = entity->GetPosition(); const CVector &pos = entity->GetPosition();
float dist = (TheCamera.GetPosition() - pos).Magnitude(); float dist = Distance(pos, TheCamera.GetPosition());
const float MAXDIST = 14.0f; const float MAXDIST = 14.0f;
if (dist < MAXDIST) { if (dist < MAXDIST) {
@ -953,7 +964,11 @@ CPickups::RenderPickUpText()
float fScaleX = aMessages[i].m_dist.x / 100.0f; float fScaleX = aMessages[i].m_dist.x / 100.0f;
if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE; if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(fScaleX), SCREEN_SCALE_Y(fScaleY));
#else
CFont::SetScale(fScaleX, fScaleY); CFont::SetScale(fScaleX, fScaleY);
#endif
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetCentreSize(SCREEN_WIDTH);
CFont::SetJustifyOff(); CFont::SetJustifyOff();
@ -998,7 +1013,7 @@ INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) { for (int32 i = 0; i < NUMPICKUPS; i++) {
CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil) if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1); buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);
} }
WriteSaveBuf(buf, CollectedPickUpIndex); WriteSaveBuf(buf, CollectedPickUpIndex);
@ -1421,3 +1436,85 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer()
FindPlayerVehicle()->m_fForceMultiplier = 1.0f; FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
} }
} }
void
CPed::CreateDeadPedMoney(void)
{
if (!CGame::nastyGame)
return;
int mi = GetModelIndex();
if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
return;
int money = CGeneral::GetRandomNumber() % 60;
if (money < 10)
return;
if (money == 43)
money = 700;
int pickupCount = money / 40 + 1;
int moneyPerPickup = money / pickupCount;
for(int i = 0; i < pickupCount; i++) {
// (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.
float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x;
float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().y;
bool found = false;
float groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;
if (found) {
CPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));
}
}
}
void
CPed::CreateDeadPedWeaponPickups(void)
{
bool found = false;
float angleToPed;
CVector pickupPos;
if (bInVehicle)
return;
for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
eWeaponType weapon = GetWeapon(i).m_eWeaponType;
int weaponAmmo = GetWeapon(i).m_nAmmoTotal;
if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0)
continue;
angleToPed = i * 1.75f;
pickupPos = GetPosition();
pickupPos.x += 1.5f * Sin(angleToPed);
pickupPos.y += 1.5f * Cos(angleToPed);
pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
CVector pedPos = GetPosition();
pedPos.z += 0.3f;
CVector pedToPickup = pickupPos - pedPos;
float distance = pedToPickup.Magnitude();
// outer edge of pickup
distance = (distance + 0.3f) / distance;
CVector pickupPos2 = pedPos;
pickupPos2 += distance * pedToPickup;
// pickup must be on ground and line to its edge must be clear
if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) {
// otherwise try another position (but disregard second check apparently)
angleToPed += 3.14f;
pickupPos = GetPosition();
pickupPos.x += 1.5f * Sin(angleToPed);
pickupPos.y += 1.5f * Cos(angleToPed);
pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
}
if (found)
CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
}
ClearWeapons();
}

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Weapon.h" #include "Weapon.h"
enum ePickupType : uint8 enum ePickupType
{ {
PICKUP_NONE = 0, PICKUP_NONE = 0,
PICKUP_IN_SHOP, PICKUP_IN_SHOP,
@ -29,7 +29,7 @@ class CPlayerPed;
class CPickup class CPickup
{ {
public: public:
ePickupType m_eType; uint8 m_eType;
bool m_bRemoved; bool m_bRemoved;
uint16 m_nQuantity; uint16 m_nQuantity;
CObject *m_pObject; CObject *m_pObject;
@ -41,10 +41,9 @@ public:
CObject *GiveUsAPickUpObject(int32 handle); CObject *GiveUsAPickUpObject(int32 handle);
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId); bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
private: private:
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; } inline bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
inline bool CanBePickedUp(CPlayerPed *player); inline bool CanBePickedUp(CPlayerPed *player);
void RemoveKeepType(); inline void Remove();
void Remove();
}; };
VALIDATE_SIZE(CPickup, 0x1C); VALIDATE_SIZE(CPickup, 0x1C);

View File

@ -402,15 +402,17 @@ void CRecordDataForChase::ProcessControlCars(void)
} }
} }
#if (defined(GTA_PS2) || defined(FIX_BUGS))
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad) bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
{ {
// may be wrong // may be wrong
if (Status == STATE_NONE || Status == STATE_PLAYBACK) if (Status == STATE_PLAYBACK_INIT) // this is useless but ps2 def checks if it's STATE_PLAYBACK_INIT
return false; return false;
if (Status == STATE_RECORD)
return pad != 0; return pad != 0;
return false;
} }
#endif
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2) void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
{ {

View File

@ -57,9 +57,7 @@ public:
static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*); static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*);
static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool); static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool);
static void ProcessControlCars(void); static void ProcessControlCars(void);
#if (defined(GTA_PS2) || defined(FIX_BUGS))
static bool ShouldThisPadBeLeftAlone(uint8 pad); static bool ShouldThisPadBeLeftAlone(uint8 pad);
#endif
static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8); static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8);
static void StartChaseScene(float); static void StartChaseScene(float);
static void CleanUpChaseScene(void); static void CleanUpChaseScene(void);

View File

@ -1,5 +1,5 @@
#include "common.h" #include "common.h"
#ifdef GTA_REPLAY
#include "AnimBlendAssociation.h" #include "AnimBlendAssociation.h"
#include "Boat.h" #include "Boat.h"
#include "SpecialFX.h" #include "SpecialFX.h"
@ -10,6 +10,10 @@
#include "DMAudio.h" #include "DMAudio.h"
#include "Draw.h" #include "Draw.h"
#include "FileMgr.h" #include "FileMgr.h"
#ifdef FIX_BUGS
#include "Fire.h"
#include "Garages.h"
#endif
#include "Heli.h" #include "Heli.h"
#include "main.h" #include "main.h"
#include "Matrix.h" #include "Matrix.h"
@ -22,6 +26,10 @@
#include "Plane.h" #include "Plane.h"
#include "Pools.h" #include "Pools.h"
#include "Population.h" #include "Population.h"
#ifdef FIX_BUGS
#include "Projectile.h"
#include "ProjectileInfo.h"
#endif
#include "Replay.h" #include "Replay.h"
#include "References.h" #include "References.h"
#include "Pools.h" #include "Pools.h"
@ -102,6 +110,11 @@ float CReplay::fDistanceLookAroundCam;
float CReplay::fBetaAngleLookAroundCam; float CReplay::fBetaAngleLookAroundCam;
float CReplay::fAlphaAngleLookAroundCam; float CReplay::fAlphaAngleLookAroundCam;
#ifdef FIX_BUGS #ifdef FIX_BUGS
uint8* CReplay::pGarages;
CFire* CReplay::FireArray;
uint32 CReplay::NumOfFires;
uint8* CReplay::paProjectileInfo;
uint8* CReplay::paProjectiles;
int CReplay::nHandleOfPlayerPed[NUMPLAYERS]; int CReplay::nHandleOfPlayerPed[NUMPLAYERS];
#endif #endif
@ -1052,10 +1065,10 @@ void CReplay::ProcessReplayCamera(void)
TheCamera.GetUp() = CVector(0.0f, 1.0f, 0.0f); TheCamera.GetUp() = CVector(0.0f, 1.0f, 0.0f);
TheCamera.GetRight() = CVector(1.0f, 0.0f, 0.0f); TheCamera.GetRight() = CVector(1.0f, 0.0f, 0.0f);
RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
pm->pos = *(RwV3d*)&TheCamera.GetPosition(); pm->pos = TheCamera.GetPosition();
pm->at = *(RwV3d*)&TheCamera.GetForward(); pm->at = TheCamera.GetForward();
pm->up = *(RwV3d*)&TheCamera.GetUp(); pm->up = TheCamera.GetUp();
pm->right = *(RwV3d*)&TheCamera.GetRight(); pm->right = TheCamera.GetRight();
break; break;
} }
case REPLAYCAMMODE_FIXED: case REPLAYCAMMODE_FIXED:
@ -1071,10 +1084,10 @@ void CReplay::ProcessReplayCamera(void)
TheCamera.GetMatrix().GetUp() = up; TheCamera.GetMatrix().GetUp() = up;
TheCamera.GetMatrix().GetRight() = right; TheCamera.GetMatrix().GetRight() = right;
RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
pm->pos = *(RwV3d*)&TheCamera.GetMatrix().GetPosition(); pm->pos = TheCamera.GetMatrix().GetPosition();
pm->at = *(RwV3d*)&TheCamera.GetMatrix().GetForward(); pm->at = TheCamera.GetMatrix().GetForward();
pm->up = *(RwV3d*)&TheCamera.GetMatrix().GetUp(); pm->up = TheCamera.GetMatrix().GetUp();
pm->right = *(RwV3d*)&TheCamera.GetMatrix().GetRight(); pm->right = TheCamera.GetMatrix().GetRight();
break; break;
} }
default: default:
@ -1183,6 +1196,17 @@ void CReplay::StoreStuffInMem(void)
if (ped) if (ped)
StoreDetailedPedAnimation(ped, &pPedAnims[i]); StoreDetailedPedAnimation(ped, &pPedAnims[i]);
} }
#ifdef FIX_BUGS
pGarages = new uint8[sizeof(CGarages::aGarages)];
memcpy(pGarages, CGarages::aGarages, sizeof(CGarages::aGarages));
FireArray = new CFire[NUM_FIRES];
memcpy(FireArray, gFireManager.m_aFires, sizeof(gFireManager.m_aFires));
NumOfFires = gFireManager.m_nTotalFires;
paProjectileInfo = new uint8[sizeof(gaProjectileInfo)];
memcpy(paProjectileInfo, gaProjectileInfo, sizeof(gaProjectileInfo));
paProjectiles = new uint8[sizeof(CProjectileInfo::ms_apProjectile)];
memcpy(paProjectiles, CProjectileInfo::ms_apProjectile, sizeof(CProjectileInfo::ms_apProjectile));
#endif
} }
void CReplay::RestoreStuffFromMem(void) void CReplay::RestoreStuffFromMem(void)
@ -1233,7 +1257,7 @@ void CReplay::RestoreStuffFromMem(void)
ped->m_rwObject = nil; ped->m_rwObject = nil;
ped->m_modelIndex = -1; ped->m_modelIndex = -1;
ped->SetModelIndex(mi); ped->SetModelIndex(mi);
ped->m_pVehicleAnim = 0; ped->m_pVehicleAnim = nil;
ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped); ped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped);
DMAudio.SetEntityStatus(ped->m_audioEntityId, true); DMAudio.SetEntityStatus(ped->m_audioEntityId, true);
CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false); CPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false);
@ -1349,6 +1373,22 @@ void CReplay::RestoreStuffFromMem(void)
} }
delete[] pPedAnims; delete[] pPedAnims;
pPedAnims = nil; pPedAnims = nil;
#ifdef FIX_BUGS
memcpy(CGarages::aGarages, pGarages, sizeof(CGarages::aGarages));
delete[] pGarages;
pGarages = nil;
memcpy(gFireManager.m_aFires, FireArray, sizeof(gFireManager.m_aFires));
delete[] FireArray;
FireArray = nil;
gFireManager.m_nTotalFires = NumOfFires;
memcpy(gaProjectileInfo, paProjectileInfo, sizeof(gaProjectileInfo));
delete[] paProjectileInfo;
paProjectileInfo = nil;
memcpy(CProjectileInfo::ms_apProjectile, paProjectiles, sizeof(CProjectileInfo::ms_apProjectile));
delete[] paProjectiles;
paProjectiles = nil;
//CExplosion::ClearAllExplosions(); not in III
#endif
DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND); DMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);
DMAudio.SetRadioInCar(OldRadioStation); DMAudio.SetRadioInCar(OldRadioStation);
DMAudio.ChangeMusicMode(MUSICMODE_GAME); DMAudio.ChangeMusicMode(MUSICMODE_GAME);
@ -1576,10 +1616,10 @@ void CReplay::ProcessLookAroundCam(void)
TheCamera.GetRight() = right; TheCamera.GetRight() = right;
TheCamera.SetPosition(camera_pt); TheCamera.SetPosition(camera_pt);
RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
pm->pos = *(RwV3d*)&TheCamera.GetPosition(); pm->pos = TheCamera.GetPosition();
pm->at = *(RwV3d*)&TheCamera.GetForward(); pm->at = TheCamera.GetForward();
pm->up = *(RwV3d*)&TheCamera.GetUp(); pm->up = TheCamera.GetUp();
pm->right = *(RwV3d*)&TheCamera.GetRight(); pm->right = TheCamera.GetRight();
TheCamera.CalculateDerivedValues(); TheCamera.CalculateDerivedValues();
RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));
RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera)); RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));
@ -1611,12 +1651,20 @@ void CReplay::Display()
TimeCount = (TimeCount + 1) % UINT16_MAX; TimeCount = (TimeCount + 1) % UINT16_MAX;
if ((TimeCount & 0x20) == 0) if ((TimeCount & 0x20) == 0)
return; return;
CFont::SetPropOn();
CFont::SetBackgroundOff();
CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));
CFont::SetAlignment(ALIGN_LEFT); CFont::SetJustifyOff();
CFont::SetBackgroundOff();
#ifdef FIX_BUGS
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-20));
#else
CFont::SetCentreSize(SCREEN_WIDTH-20);
#endif
CFont::SetCentreOff();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200)); CFont::SetColor(CRGBA(255, 255, 200, 200));
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
if (Mode == MODE_PLAYBACK) if (Mode == MODE_PLAYBACK)
CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY")); CFont::PrintString(SCREEN_WIDTH/15, SCREEN_HEIGHT/10, TheText.Get("REPLAY"));
} }
#endif

View File

@ -63,6 +63,12 @@ struct CStoredDetailedAnimationState
void PlayReplayFromHD(void); void PlayReplayFromHD(void);
#ifdef GTA_REPLAY
#define REPLAY_STUB
#else
#define REPLAY_STUB {}
#endif
class CReplay class CReplay
{ {
enum { enum {
@ -269,24 +275,33 @@ private:
static float fAlphaAngleLookAroundCam; static float fAlphaAngleLookAroundCam;
static float fBetaAngleLookAroundCam; static float fBetaAngleLookAroundCam;
#ifdef FIX_BUGS #ifdef FIX_BUGS
static uint8* pGarages;
static CFire* FireArray;
static uint32 NumOfFires;
static uint8* paProjectileInfo;
static uint8* paProjectiles;
static int nHandleOfPlayerPed[NUMPLAYERS]; static int nHandleOfPlayerPed[NUMPLAYERS];
#endif #endif
public: public:
static void Init(void); static void Init(void) REPLAY_STUB;
static void DisableReplays(void); static void DisableReplays(void) REPLAY_STUB;
static void EnableReplays(void); static void EnableReplays(void) REPLAY_STUB;
static void Update(void); static void Update(void) REPLAY_STUB;
static void FinishPlayback(void); static void FinishPlayback(void) REPLAY_STUB;
static void EmptyReplayBuffer(void); static void EmptyReplayBuffer(void) REPLAY_STUB;
static void Display(void); static void Display(void) REPLAY_STUB;
static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene); static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) REPLAY_STUB;
static void StreamAllNecessaryCarsAndPeds(void); static void StreamAllNecessaryCarsAndPeds(void) REPLAY_STUB;
static bool ShouldStandardCameraBeProcessed(void);
#ifndef GTA_REPLAY
static bool ShouldStandardCameraBeProcessed(void) { return true; }
static bool IsPlayingBack() { return false; }
static bool IsPlayingBackFromFile() { return false; }
#else
static bool ShouldStandardCameraBeProcessed(void);
static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; } static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; } static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
private: private:
static void RecordThisFrame(void); static void RecordThisFrame(void);
static void StorePedUpdate(CPed *ped, int id); static void StorePedUpdate(CPed *ped, int id);
@ -314,4 +329,5 @@ private:
/* Absolute nonsense, but how could this function end up being outside of class? */ /* Absolute nonsense, but how could this function end up being outside of class? */
friend void PlayReplayFromHD(void); friend void PlayReplayFromHD(void);
#endif
}; };

View File

@ -81,7 +81,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
} }
eLevelName curlevel = CTheZones::FindZoneForPoint(pos); eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f; float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS; int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level // find closest point on this level
@ -128,7 +128,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo
} }
eLevelName curlevel = CTheZones::FindZoneForPoint(pos); eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
float fMinDist = 16000000.0f; float fMinDist = SQR(4000.0f);
int closestPoint = NUM_RESTART_POINTS; int closestPoint = NUM_RESTART_POINTS;
// find closest point on this level // find closest point on this level

View File

@ -90,8 +90,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->m_nRoadblockNode = roadBlockNode;
pCopPed->bCrouchWhenShooting = roadBlockType != 2; pCopPed->bCrouchWhenShooting = roadBlockType != 2;
if (pEntityToAttack) { if (pEntityToAttack) {
pCopPed->m_pPointGunAt = pEntityToAttack; pCopPed->SetWeaponLockOnTarget(pEntityToAttack);
pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt);
pCopPed->SetAttack(pEntityToAttack); pCopPed->SetAttack(pEntityToAttack);
} }
pCopPed->m_pMyVehicle = pVehicle; pCopPed->m_pMyVehicle = pVehicle;
@ -165,7 +164,7 @@ CRoadBlocks::GenerateRoadBlocks(void)
vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
pVehicle->m_matrix = vehicleMatrix; pVehicle->m_matrix = vehicleMatrix;
pVehicle->PlaceOnRoadProperly(); pVehicle->PlaceOnRoadProperly();
pVehicle->bIsStatic = false; pVehicle->SetIsStatic(false);
pVehicle->m_matrix.UpdateRW(); pVehicle->m_matrix.UpdateRW();
pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
CCarCtrl::JoinCarWithRoadSystem(pVehicle); CCarCtrl::JoinCarWithRoadSystem(pVehicle);

View File

@ -1,7 +1,7 @@
#include "common.h" #include "common.h"
#include "SceneEdit.h" #include "SceneEdit.h"
#ifdef GTA_SCENE_EDIT
#include "Automobile.h" #include "Automobile.h"
#include "Camera.h" #include "Camera.h"
#include "CarCtrl.h" #include "CarCtrl.h"
@ -279,24 +279,44 @@ void CSceneEdit::Draw(void)
#endif #endif
sprintf(str, "Action"); sprintf(str, "Action");
AsciiToUnicode(str, wstr); AsciiToUnicode(str, wstr);
CFont::SetColor(CRGBA(0, 0, 0, 0)); CFont::SetColor(CRGBA(0, 0, 0, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-ACTION_MESSAGE_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-ACTION_MESSAGE_Y) + SHADOW_OFFSET, wstr);
#endif
CFont::SetColor(CRGBA(193, 164, 120, 255)); CFont::SetColor(CRGBA(193, 164, 120, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(ACTION_MESSAGE_Y), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(ACTION_MESSAGE_Y), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-ACTION_MESSAGE_Y), wstr);
#endif
sprintf(str, "Selected"); sprintf(str, "Selected");
AsciiToUnicode(str, wstr); AsciiToUnicode(str, wstr);
CFont::SetColor(CRGBA(0, 0, 0, 0)); CFont::SetColor(CRGBA(0, 0, 0, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-SELECTED_MESSAGE_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-SELECTED_MESSAGE_Y) + SHADOW_OFFSET, wstr);
#endif
CFont::SetColor(CRGBA(193, 164, 120, 255)); CFont::SetColor(CRGBA(193, 164, 120, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-SELECTED_MESSAGE_Y), wstr);
#endif
CFont::SetCentreOff(); CFont::SetCentreOff();
#ifdef FIX_BUGS
CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.7f)); CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.7f));
#else
CFont::SetScale(0.7f, 0.7f);
#endif
#ifdef FIX_BUGS #ifdef FIX_BUGS
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);
#else #else
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
#endif #endif
CFont::SetColor(CRGBA(0, 0, 0, 0)); CFont::SetColor(CRGBA(0, 0, 0, 255));
for (int i = 0; i < NUM_COMMANDS_TO_DRAW; i++) { for (int i = 0; i < NUM_COMMANDS_TO_DRAW; i++) {
int16 nCommandDrawn = m_nCurrentCommand + i - NUM_COMMANDS_TO_DRAW / 2; int16 nCommandDrawn = m_nCurrentCommand + i - NUM_COMMANDS_TO_DRAW / 2;
if (nCommandDrawn >= MOVIE_TOTAL_COMMANDS) if (nCommandDrawn >= MOVIE_TOTAL_COMMANDS)
@ -305,13 +325,21 @@ void CSceneEdit::Draw(void)
nCommandDrawn += (MOVIE_TOTAL_COMMANDS - 1); nCommandDrawn += (MOVIE_TOTAL_COMMANDS - 1);
sprintf(str, "%s", pCommandStrings[nCommandDrawn]); sprintf(str, "%s", pCommandStrings[nCommandDrawn]);
AsciiToUnicode(str, wstr); AsciiToUnicode(str, wstr);
CFont::SetColor(CRGBA(0, 0, 0, 0)); CFont::SetColor(CRGBA(0, 0, 0, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-COMMAND_NAME_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-COMMAND_NAME_Y) + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr);
#endif
if (nCommandDrawn == m_nCurrentCommand) if (nCommandDrawn == m_nCurrentCommand)
CFont::SetColor(CRGBA(156, 91, 40, 255)); CFont::SetColor(CRGBA(156, 91, 40, 255));
else else
CFont::SetColor(CRGBA(193, 164, 120, 255)); CFont::SetColor(CRGBA(193, 164, 120, 255));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT), SCREEN_SCALE_Y(COMMAND_NAME_Y + i * COMMAND_NAME_HEIGHT), wstr); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT), SCREEN_SCALE_Y(COMMAND_NAME_Y + i * COMMAND_NAME_HEIGHT), wstr);
#else
CFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-COMMAND_NAME_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-COMMAND_NAME_Y) + i * COMMAND_NAME_HEIGHT), wstr);
#endif
} }
} }
@ -1096,3 +1124,4 @@ bool CSceneEdit::SelectWeapon(void)
} }
return false; return false;
} }
#endif

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#ifdef GTA_SCENE_EDIT
class CPed; class CPed;
class CVehicle; class CVehicle;
@ -93,3 +93,4 @@ public:
static void SelectVehicle(void); static void SelectVehicle(void);
static bool SelectWeapon(void); static bool SelectWeapon(void);
}; };
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include "Ped.h"
#include "PedType.h" #include "PedType.h"
#include "Text.h" #include "Text.h"
#include "Sprite2d.h" #include "Sprite2d.h"
@ -13,8 +14,35 @@ class CPlayerInfo;
class CRunningScript; class CRunningScript;
extern int32 ScriptParams[32];
void FlushLog();
#define script_assert(_Expression) FlushLog(); assert(_Expression);
#define PICKUP_PLACEMENT_OFFSET 0.5f
#define PED_FIND_Z_OFFSET 5.0f
#define SPHERE_MARKER_R 0
#define SPHERE_MARKER_G 128
#define SPHERE_MARKER_B 255
#define SPHERE_MARKER_A 128
#define SPHERE_MARKER_PULSE_PERIOD 2048
#define SPHERE_MARKER_PULSE_FRACTION 0.1f
#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
#define METERS_IN_FOOT 0.3048f
#define FEET_IN_METER 3.28084f
#else
#define METERS_IN_FOOT 0.3f
#define FEET_IN_METER 3.33f
#endif
#define KEY_LENGTH_IN_SCRIPT 8 #define KEY_LENGTH_IN_SCRIPT 8
#if GTA_VERSION <= GTA_PS2_160
#define GTA_SCRIPT_COLLECTIVE
#endif
struct intro_script_rectangle struct intro_script_rectangle
{ {
bool m_bIsUsed; bool m_bIsUsed;
@ -190,8 +218,8 @@ enum {
struct tCollectiveData struct tCollectiveData
{ {
int32 index; int32 colIndex;
uint32 unk_data; int32 pedIndex;
}; };
enum { enum {
@ -263,7 +291,7 @@ class CTheScripts
static bool StoreVehicleWasRandom; static bool StoreVehicleWasRandom;
static CRunningScript *pIdleScripts; static CRunningScript *pIdleScripts;
static CRunningScript *pActiveScripts; static CRunningScript *pActiveScripts;
static uint32 NextFreeCollectiveIndex; static int32 NextFreeCollectiveIndex;
static int32 LastRandomPedId; static int32 LastRandomPedId;
static uint16 NumberOfUsedObjects; static uint16 NumberOfUsedObjects;
static bool bAlreadyRunningAMissionScript; static bool bAlreadyRunningAMissionScript;
@ -370,12 +398,36 @@ private:
static int32 GetNewUniqueScriptSphereIndex(int32 index); static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index); static void RemoveScriptSphere(int32 index);
#ifdef GTA_SCRIPT_COLLECTIVE
static void AdvanceCollectiveIndex()
{
if (NextFreeCollectiveIndex == INT32_MAX)
NextFreeCollectiveIndex = 0;
else
NextFreeCollectiveIndex++;
}
static int AddPedsInVehicleToCollective(int);
static int AddPedsInAreaToCollective(float, float, float, float);
static int FindFreeSlotInCollectiveArray();
static void SetObjectiveForAllPedsInCollective(int, eObjective, int16, int16);
static void SetObjectiveForAllPedsInCollective(int, eObjective, CVector, float);
static void SetObjectiveForAllPedsInCollective(int, eObjective, CVector);
static void SetObjectiveForAllPedsInCollective(int, eObjective, void*);
static void SetObjectiveForAllPedsInCollective(int, eObjective);
#endif
friend class CRunningScript; friend class CRunningScript;
friend class CHud; friend class CHud;
friend void CMissionCleanup::Process(); friend void CMissionCleanup::Process();
#ifdef FIX_BUGS #ifdef MISSION_REPLAY
friend void RetryMission(int, int); friend void RetryMission(int, int);
#endif #endif
#ifdef MISSION_SWITCHER
public:
static void SwitchToMission(int32 mission);
#endif
}; };
@ -483,6 +535,14 @@ private:
void CharInAreaCheckCommand(int32, uint32*); void CharInAreaCheckCommand(int32, uint32*);
void CarInAreaCheckCommand(int32, uint32*); void CarInAreaCheckCommand(int32, uint32*);
#ifdef GTA_SCRIPT_COLLECTIVE
void LocateCollectiveCommand(int32, uint32*);
void LocateCollectiveCharCommand(int32, uint32*);
void LocateCollectiveCarCommand(int32, uint32*);
void LocateCollectivePlayerCommand(int32, uint32*);
void CollectiveInAreaCheckCommand(int32, uint32*);
#endif
#ifdef MISSION_REPLAY #ifdef MISSION_REPLAY
bool CanAllowMissionReplay(); bool CanAllowMissionReplay();
#endif #endif
@ -514,6 +574,8 @@ private:
return false; return false;
} }
} }
friend class CTheScripts;
}; };
#ifdef MISSION_REPLAY #ifdef MISSION_REPLAY

1555
src/control/Script2.cpp Normal file

File diff suppressed because it is too large Load Diff

2360
src/control/Script3.cpp Normal file

File diff suppressed because it is too large Load Diff

2177
src/control/Script4.cpp Normal file

File diff suppressed because it is too large Load Diff

2517
src/control/Script5.cpp Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More