diff --git a/.gitattributes b/.gitattributes index 412eeda78d..e9b301bd85 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,3 +20,7 @@ *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain + +# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails. +# See https://help.github.com/articles/dealing-with-line-endings/ +*.sh text eol=lf diff --git a/CMakeLists.txt b/CMakeLists.txt index 51b748ba5e..dc5091adac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ if(APPLE) endif() # Custom CMake Modules needed -list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/CMakeModules") +list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake/Modules") Include(CheckTypeSize) check_type_size("void*" CMAKE_SIZEOF_VOID_P) @@ -208,6 +208,7 @@ if(MSVC) set(SharedDefines ${SharedDefines} "_CRT_SECURE_NO_WARNINGS") set(SharedDefines ${SharedDefines} "_SCL_SECURE_NO_WARNINGS") set(SharedDefines ${SharedDefines} "_CRT_NONSTDC_NO_DEPRECATE") + set(SharedDefines ${SharedDefines} "WINDOWS_IGNORE_PACKING_MISMATCH") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:SSE2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") diff --git a/CMakeModules/FindAngelscript.cmake b/CMakeModules/FindAngelscript.cmake deleted file mode 100644 index bc675afb60..0000000000 --- a/CMakeModules/FindAngelscript.cmake +++ /dev/null @@ -1,96 +0,0 @@ -# This find module searches for AngleScript using the environment variable ANGLESCRIPT_HOME -# Use the standard SDK download from the AngleScript website - -# Create variables -if(WIN32) - # Search include directory - find_path(AngelScript_INCLUDE_DIR angelscript.h ${ANGELSCRIPT_HOME}/include/) - - # Remember include directory - set(AngelScript_INCLUDE_DIRS "AngelScript_INCLUDE_DIRS-NOTFOUND") - - if (AngelScript_INCLUDE_DIR) - set(AngelScript_INCLUDE_DIRS ${AngelScript_INCLUDE_DIR}) - endif(AngelScript_INCLUDE_DIR) - - # Search LIB files - find_library(AngelScript_LIBRARY_RELEASE NAMES angelscript HINTS ${ANGELSCRIPT_HOME}/lib/) - find_library(AngelScript_LIBRARY_DEBUG NAMES angelscriptd HINTS ${ANGELSCRIPT_HOME}/lib/) - - # Publish LIB files - set(AngelScript_LIBRARY "AngelScript_LIBRARY-NOTFOUND") - - if(AngelScript_LIBRARY_RELEASE AND AngelScript_LIBRARY_DEBUG) - set(AngelScript_LIBRARY optimized ${AngelScript_LIBRARY_RELEASE} debug ${AngelScript_LIBRARY_DEBUG}) - elseif(AngelScript_LIBRARY_RELEASE) - set(AngelScript_LIBRARY ${AngelScript_LIBRARY_RELEASE}) - elseif(AngelScript_LIBRARY_DEBUG) - set(AngelScript_LIBRARY ${AngelScript_LIBRARY_DEBUG}) - endif() - - # Process components - foreach(COMPONENT ${AngelScript_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCMP) - - if (${COMPONENT} STREQUAL scriptbuilder OR - ${COMPONENT} STREQUAL scriptstring OR - ${COMPONENT} STREQUAL scriptstdstring OR - ${COMPONENT} STREQUAL scriptarray OR - ${COMPONENT} STREQUAL scriptmath OR - ${COMPONENT} STREQUAL scriptdictionary) - # Search source files - find_file(AngelScript_${UPPERCMP}_H NAMES ${COMPONENT}.h HINTS ${ANGELSCRIPT_HOME}/add_on/${COMPONENT}/) - find_file(AngelScript_${UPPERCMP}_CPP NAMES ${COMPONENT}.cpp HINTS ${ANGELSCRIPT_HOME}/add_on/${COMPONENT}/) - - # Publish source files - set(AngelScript_${UPPERCMP}_FILES "AngelScript_${UPPERCMP}_FILES-NOTFOUND") - - if(AngelScript_${UPPERCMP}_H AND AngelScript_${UPPERCMP}_CPP) - # Update component variables - set(AngelScript_${UPPERCMP}_FOUND TRUE) - set(AngelScript_${UPPERCMP}_FILES ${AngelScript_${UPPERCMP}_H} ${AngelScript_${UPPERCMP}_CPP}) - - # Update set variables - set(AngelScript_INCLUDE_DIRS ${AngelScript_INCLUDE_DIRS} ${ANGELSCRIPT_HOME}/add_on/${COMPONENT}/) - set(AngelScript_FILES ${AngelScript_FILES} ${AngelScript_${UPPERCMP}_FILES}) - endif() - endif() - endforeach() -else() - # Notify error - message(FATAL_ERROR "Platform not supported") -endif() - -# Check success -if(AngelScript_INCLUDE_DIR AND AngelScript_LIBRARY) - set(AngelScript_FOUND TRUE) -endif() - -# Print messages -if(AngelScript_FOUND) - if(NOT AngelScript_FOUND_QUIETLY) - # Notify success - message(STATUS "AngelScript found: ${AngelScript_LIBRARY}") - endif() -else(AngelScript_FOUND) - if(AngelScript_FIND_REQUIRED) - # Print error - message(FATAL_ERROR "AngelScript not found") - message(STATUS "Please set the environment variable ANGELSCRIPT_HOME") - endif() -endif() - -# Print component status -foreach(COMPONENT ${AngelScript_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCMP) - - if(AngelScript_${UPPERCMP}_FOUND) - if(NOT AngelScript_FOUND_QUIETLY) - message(STATUS "AngelScript ${COMPONENT} found: ${AngelScript_${UPPERCMP}_FILES}") - endif() - else(AngelScript_${UPPERCMP}_FOUND) - if(AngelScript_FIND_REQUIRED) - message(FATAL_ERROR "AngelScript ${COMPONENT} not found") - endif() - endif() -endforeach() \ No newline at end of file diff --git a/CMakeModules/FindSDL2.cmake b/CMakeModules/FindSDL2.cmake deleted file mode 100644 index 5be23d6e13..0000000000 --- a/CMakeModules/FindSDL2.cmake +++ /dev/null @@ -1,182 +0,0 @@ -# Locate SDL2 library -# This module defines -# SDL2_LIBRARY, the name of the library to link against -# SDL2_FOUND, if false, do not try to link to SDL2 -# SDL2_INCLUDE_DIR, where to find SDL.h -# -# This module responds to the the flag: -# SDL2_BUILDING_LIBRARY -# If this is defined, then no SDL2main will be linked in because -# only applications need main(). -# Otherwise, it is assumed you are building an application and this -# module will attempt to locate and set the the proper link flags -# as part of the returned SDL2_LIBRARY variable. -# -# Don't forget to include SDLmain.h and SDLmain.m your project for the -# OS X framework based version. (Other versions link to -lSDL2main which -# this module will try to find on your behalf.) Also for OS X, this -# module will automatically add the -framework Cocoa on your behalf. -# -# -# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration -# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library -# (SDL2.dll, libsdl2.so, SDL2.framework, etc). -# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. -# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value -# as appropriate. These values are used to generate the final SDL2_LIBRARY -# variable, but when these values are unset, SDL2_LIBRARY does not get created. -# -# -# $SDL2DIR is an environment variable that would -# correspond to the ./configure --prefix=$SDL2DIR -# used in building SDL2. -# l.e.galup 9-20-02 -# -# Modified by Eric Wing. -# Added code to assist with automated building by using environmental variables -# and providing a more controlled/consistent search behavior. -# Added new modifications to recognize OS X frameworks and -# additional Unix paths (FreeBSD, etc). -# Also corrected the header search path to follow "proper" SDL guidelines. -# Added a search for SDL2main which is needed by some platforms. -# Added a search for threads which is needed by some platforms. -# Added needed compile switches for MinGW. -# -# On OSX, this will prefer the Framework version (if found) over others. -# People will have to manually change the cache values of -# SDL2_LIBRARY to override this selection or set the CMake environment -# CMAKE_INCLUDE_PATH to modify the search paths. -# -# Note that the header path has changed from SDL2/SDL.h to just SDL.h -# This needed to change because "proper" SDL convention -# is #include "SDL.h", not . This is done for portability -# reasons because not all systems place things in SDL2/ (see FreeBSD). - -#============================================================================= -# Copyright 2003-2009 Kitware, Inc. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the names of Kitware, Inc., the Insight Software Consortium, -# nor the names of their contributors may be used to endorse or promote -# products derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -SET(SDL2_SEARCH_PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -FIND_PATH(SDL2_INCLUDE_DIR SDL.h - NAMES SDL2 - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES include/SDL2 include - PATHS ${SDL2_SEARCH_PATHS} -) - -FIND_LIBRARY(SDL2_LIBRARY_TEMP - NAMES SDL2 - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES lib64 lib - PATHS ${SDL2_SEARCH_PATHS} -) - -IF(NOT SDL2_BUILDING_LIBRARY) - IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") - # Non-OS X framework versions expect you to also dynamically link to - # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms - # seem to provide SDL2main for compatibility even though they don't - # necessarily need it. - FIND_LIBRARY(SDL2MAIN_LIBRARY - NAMES SDL2main - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES lib64 lib - PATHS ${SDL2_SEARCH_PATHS} - ) - ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") -ENDIF(NOT SDL2_BUILDING_LIBRARY) - -# SDL2 may require threads on your system. -# The Apple build may not need an explicit flag because one of the -# frameworks may already provide it. -# But for non-OSX systems, I will use the CMake Threads package. -IF(NOT APPLE) - FIND_PACKAGE(Threads) -ENDIF(NOT APPLE) - -# MinGW needs an additional library, mwindows -# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows -# (Actually on second look, I think it only needs one of the m* libraries.) -IF(MINGW) - SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") -ENDIF(MINGW) - -IF(SDL2_LIBRARY_TEMP) - # For SDL2main - IF(NOT SDL2_BUILDING_LIBRARY) - IF(SDL2MAIN_LIBRARY) - SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) - ENDIF(SDL2MAIN_LIBRARY) - ENDIF(NOT SDL2_BUILDING_LIBRARY) - - # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. - # CMake doesn't display the -framework Cocoa string in the UI even - # though it actually is there if I modify a pre-used variable. - # I think it has something to do with the CACHE STRING. - # So I use a temporary variable until the end so I can set the - # "real" variable in one-shot. - IF(APPLE) - SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") - ENDIF(APPLE) - - # For threads, as mentioned Apple doesn't need this. - # In fact, there seems to be a problem if I used the Threads package - # and try using this line, so I'm just skipping it entirely for OS X. - IF(NOT APPLE) - SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) - ENDIF(NOT APPLE) - - # For MinGW library - IF(MINGW) - SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) - ENDIF(MINGW) - - # Set the final string here so the GUI reflects the final state. - SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") - # Set the temp variable to INTERNAL so it is not seen in the CMake GUI - SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") -ENDIF(SDL2_LIBRARY_TEMP) - -INCLUDE(FindPackageHandleStandardArgs) - -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) diff --git a/CreateVisualStudio2013Projects.bat b/CreateVisualStudio2013Projects.bat index b236088317..e0a83becd1 100644 --- a/CreateVisualStudio2013Projects.bat +++ b/CreateVisualStudio2013Projects.bat @@ -13,6 +13,6 @@ if not defined FOUND ( ) if not exist build\nul (mkdir build) pushd build -cmake -G "Visual Studio 12" -D CMAKE_INSTALL_PREFIX=../install .. +cmake -G "Visual Studio 12 2013" -A Win32 -D CMAKE_INSTALL_PREFIX=../install .. popd pause \ No newline at end of file diff --git a/CreateVisualStudio2015Projects.bat b/CreateVisualStudio2015Projects.bat index c574594714..f5a302ab2c 100644 --- a/CreateVisualStudio2015Projects.bat +++ b/CreateVisualStudio2015Projects.bat @@ -13,6 +13,6 @@ if not defined FOUND ( ) if not exist build\nul (mkdir build) pushd build -cmake -G "Visual Studio 14" -D CMAKE_INSTALL_PREFIX=../install .. +cmake -G "Visual Studio 14 2015" -A Win32 -D CMAKE_INSTALL_PREFIX=../install .. popd pause \ No newline at end of file diff --git a/CreateVisualStudio2017Projects.bat b/CreateVisualStudio2017Projects.bat new file mode 100644 index 0000000000..a7a924379b --- /dev/null +++ b/CreateVisualStudio2017Projects.bat @@ -0,0 +1,18 @@ +@REM Create OpenJK projects for Visual Studio 2017 using CMake +@echo off +for %%X in (cmake.exe) do (set FOUND=%%~$PATH:X) +if not defined FOUND ( + echo CMake was not found on your system. Please make sure you have installed CMake + echo from http://www.cmake.org/ and cmake.exe is installed to your system's PATH + echo environment variable. + echo. + pause + exit /b 1 +) else ( + echo Found CMake! +) +if not exist build\nul (mkdir build) +pushd build +cmake -G "Visual Studio 15 2017" -A Win32 -D CMAKE_INSTALL_PREFIX=../install .. +popd +pause \ No newline at end of file diff --git a/CreateVisualStudio2019Projects.bat b/CreateVisualStudio2019Projects.bat new file mode 100644 index 0000000000..257d42d069 --- /dev/null +++ b/CreateVisualStudio2019Projects.bat @@ -0,0 +1,18 @@ +@REM Create OpenJK projects for Visual Studio 2017 using CMake +@echo off +for %%X in (cmake.exe) do (set FOUND=%%~$PATH:X) +if not defined FOUND ( + echo CMake was not found on your system. Please make sure you have installed CMake + echo from http://www.cmake.org/ and cmake.exe is installed to your system's PATH + echo environment variable. + echo. + pause + exit /b 1 +) else ( + echo Found CMake! +) +if not exist build\nul (mkdir build) +pushd build +cmake -G "Visual Studio 16 2019" -A Win32 -D CMAKE_INSTALL_PREFIX=../install .. +popd +pause \ No newline at end of file diff --git a/README.md b/README.md index e53af18805..70c8d3632a 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,13 @@ Rough support for Jedi Outcast single player is also available, however this sho Please use discretion when making issue requests on GitHub. The [JKHub sub-forum](http://jkhub.org/forum/51-discussion/) is a better place for support queries, discussions, and feature requests. -[![IRC](https://img.shields.io/badge/irc-%23JACoders-brightgreen.svg)](http://unic0rn.github.io/tiramisu/jacoders/) + [![Forum](https://img.shields.io/badge/forum-JKHub.org%20OpenJK-brightgreen.svg)](http://jkhub.org/forum/51-discussion/) [![Coverity Scan Build Status](https://scan.coverity.com/projects/1153/badge.svg)](https://scan.coverity.com/projects/1153) -| Windows | macOS | Linux x86 | Linux x64 | -|---------|-------|-----------|-----------| -| [![Windows Build Status](http://jk.xd.cm/badge.svg?builder=windows)](http://jk.xd.cm/builders/windows) | [ ![macOS Build Status](http://jk.xd.cm/badge.svg?builder=osx)](http://jk.xd.cm/builders/osx) | [ ![Linux x86 Build Status](http://jk.xd.cm/badge.svg?builder=linux)](http://jk.xd.cm/builders/linux) | [ ![Linux x64 Build Status](http://jk.xd.cm/badge.svg?builder=linux-64)](http://jk.xd.cm/builders/linux-64) | - - ## License -[![License](https://img.shields.io/github/license/JACoders/OpenJK.svg)](https://github.com/JACoders/OpenJK/blob/master/LICENSE.txt) - OpenJK is licensed under GPLv2 as free software. You are free to use, modify and redistribute OpenJK following the terms in LICENSE.txt. @@ -87,12 +80,6 @@ If you have the Mac App Store Version of Jedi Academy, follow these steps to get * If you make a nice change, please consider back-porting to upstream via pull request as described above. This is so everyone benefits without having to reinvent the wheel for every project. -### Deciphering buildbot's output - -* Pick the build from the operating system builder you're interested in at the [builders](https://jk.xd.cm/builders) page. -* Click on stdio for the Steps to see the command executed and the result. -* The command is at the very top, the output starts below. - ## Maintainers (in alphabetical order) diff --git a/CMakeModules/GetGitRevisionDescription.cmake b/cmake/Modules/GetGitRevisionDescription.cmake similarity index 100% rename from CMakeModules/GetGitRevisionDescription.cmake rename to cmake/Modules/GetGitRevisionDescription.cmake diff --git a/CMakeModules/GetGitRevisionDescription.cmake.in b/cmake/Modules/GetGitRevisionDescription.cmake.in similarity index 100% rename from CMakeModules/GetGitRevisionDescription.cmake.in rename to cmake/Modules/GetGitRevisionDescription.cmake.in diff --git a/CMakeModules/InstallConfig.cmake b/cmake/Modules/InstallConfig.cmake similarity index 99% rename from CMakeModules/InstallConfig.cmake rename to cmake/Modules/InstallConfig.cmake index 8e0094a6e9..a25f87f0f5 100644 --- a/CMakeModules/InstallConfig.cmake +++ b/cmake/Modules/InstallConfig.cmake @@ -67,7 +67,6 @@ cpack_add_component_group(JK2SP DESCRIPTION "Jedi Outcast single player game") if(WIN32) - include(CPackNSIS) set(CPACK_NSIS_DISPLAY_NAME "OpenJK") set(CPACK_NSIS_PACKAGE_NAME "OpenJK") set(CPACK_NSIS_MUI_ICON "${SharedDir}/icons/icon.ico") @@ -160,4 +159,4 @@ set(CPACK_PACKAGE_DIRECTORY ${PACKAGE_DIR}) set(CPACK_BINARY_ZIP ON) # always create at least a zip file set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) # prevent additional directory in zip -include(CPack) \ No newline at end of file +include(CPack) diff --git a/CMakeModules/InstallZIP.cmake b/cmake/Modules/InstallZIP.cmake similarity index 100% rename from CMakeModules/InstallZIP.cmake rename to cmake/Modules/InstallZIP.cmake diff --git a/CMakeModules/LICENSE_1_0.txt b/cmake/Modules/LICENSE_1_0.txt similarity index 100% rename from CMakeModules/LICENSE_1_0.txt rename to cmake/Modules/LICENSE_1_0.txt diff --git a/CMakeModules/Toolchains/i686-w64-mingw32.cmake b/cmake/Toolchains/i686-w64-mingw32.cmake similarity index 100% rename from CMakeModules/Toolchains/i686-w64-mingw32.cmake rename to cmake/Toolchains/i686-w64-mingw32.cmake diff --git a/CMakeModules/Toolchains/linux-i686.cmake b/cmake/Toolchains/linux-i686.cmake similarity index 100% rename from CMakeModules/Toolchains/linux-i686.cmake rename to cmake/Toolchains/linux-i686.cmake diff --git a/CMakeModules/Toolchains/x86_64-w64-mingw32.cmake b/cmake/Toolchains/x86_64-w64-mingw32.cmake similarity index 100% rename from CMakeModules/Toolchains/x86_64-w64-mingw32.cmake rename to cmake/Toolchains/x86_64-w64-mingw32.cmake diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 9d121df4d4..2c8ff49880 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -90,9 +90,9 @@ if(BuildSPEngine OR BuildJK2SPEngine) ${OpenJKLibDir}/SDL2/include ) else() - find_package(SDL2 REQUIRED) - set(SPEngineIncludeDirectories ${SPEngineIncludeDirectories} ${SDL2_INCLUDE_DIR}) - set(SPEngineLibraries ${SPEngineLibraries} ${SDL2_LIBRARY}) + find_package(SDL2 REQUIRED CONFIG) + set(SPEngineIncludeDirectories ${SPEngineIncludeDirectories} ${SDL2_INCLUDE_DIRS}) + set(SPEngineLibraries ${SPEngineLibraries} ${SDL2_LIBRARIES}) endif() # Source Files diff --git a/code/cgame/cg_draw.cpp b/code/cgame/cg_draw.cpp index 9f2da29794..8a6690c8fe 100644 --- a/code/cgame/cg_draw.cpp +++ b/code/cgame/cg_draw.cpp @@ -2532,7 +2532,7 @@ void CG_ClearHealthBarEnts( void ) if ( cg_numHealthBarEnts ) { cg_numHealthBarEnts = 0; - memset( &cg_healthBarEnts, 0, MAX_HEALTH_BAR_ENTS ); + memset( &cg_healthBarEnts, 0, sizeof(cg_healthBarEnts) ); } } /* diff --git a/code/cgame/cg_event.cpp b/code/cgame/cg_event.cpp index 142a39bb86..423cb9cded 100644 --- a/code/cgame/cg_event.cpp +++ b/code/cgame/cg_event.cpp @@ -263,7 +263,35 @@ static void CG_UseItem( centity_t *cent ) } +/* +============== +CG_UnsafeEventType +Returns qtrue for event types that access cent->gent directly (and don't require it +to be the player / entity 0). +============== +*/ +qboolean CG_UnsafeEventType(int eventType) +{ + switch (eventType) + { + case EV_CHANGE_WEAPON: + case EV_DISRUPTOR_SNIPER_SHOT: + case EV_DISRUPTOR_SNIPER_MISS: + case EV_CONC_ALT_MISS: + case EV_DISINTEGRATION: + case EV_GRENADE_BOUNCE: + case EV_MISSILE_HIT: + case EV_MISSILE_MISS: + case EV_PAIN: + case EV_PLAY_EFFECT: + case EV_TARGET_BEAM_DRAW: + return qtrue; + break; + default: + return qfalse; + } +} /* ============== CG_EntityEvent @@ -296,6 +324,14 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { { return; } + + //When skipping a cutscene the timescale is drastically increased, causing entities to be freed + //and possibly reused between the snapshot currentState and the actual state of the gent when accessed. + //We try to avoid this issue by ignoring events on entities that have been freed since the snapshot. + if (cent->gent->freetime > cg.snap->serverTime && CG_UnsafeEventType(event)) + { + return; + } //ci = ¢->gent->client->clientInfo; clientNum = cent->gent->s.number; diff --git a/code/cgame/cg_weapons.cpp b/code/cgame/cg_weapons.cpp index 5edde39ac4..4d76f23fd0 100644 --- a/code/cgame/cg_weapons.cpp +++ b/code/cgame/cg_weapons.cpp @@ -159,7 +159,7 @@ void CG_RegisterWeapon( int weaponNum ) { // Init the ghoul2 model weaponInfo->g2_skin = gi.RE_RegisterSkin(weaponData[weaponNum].skinPath); weaponInfo->g2_index = gi.G2API_InitGhoul2Model(weaponInfo->ghoul2, path, - G_ModelIndex(path), G_SkinIndex(weaponData[weaponNum].skinPath), NULL, 0, 0); + G_ModelIndex(path), G_SkinIndex(weaponData[weaponNum].skinPath), NULL_HANDLE, 0, 0); gi.G2API_SetSkin(&weaponInfo->ghoul2[weaponInfo->g2_index], 0, weaponInfo->g2_skin); // Add flash bolt weaponInfo->g2_flashbolt = gi.G2API_AddBolt(&weaponInfo->ghoul2[weaponInfo->g2_index], "*flash"); diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 6186128e49..981bd79afc 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -1084,6 +1084,7 @@ void CL_InitRef( void ) { static refimport_t rit; char dllName[MAX_OSPATH]; GetRefAPI_t GetRefAPI; + qboolean fallback = qfalse; Com_Printf( "----- Initializing Renderer ----\n" ); cl_renderer = Cvar_Get( "cl_renderer", DEFAULT_RENDER_LIBRARY, CVAR_ARCHIVE|CVAR_LATCH|CVAR_PROTECTED ); @@ -1092,6 +1093,7 @@ void CL_InitRef( void ) { if( !(rendererLib = Sys_LoadDll( dllName, qfalse )) && strcmp( cl_renderer->string, cl_renderer->resetString ) ) { + fallback = qtrue; Com_Printf( "failed: trying to load fallback renderer\n" ); Cvar_ForceReset( "cl_renderer" ); @@ -1106,7 +1108,20 @@ void CL_InitRef( void ) { memset( &rit, 0, sizeof( rit ) ); GetRefAPI = (GetRefAPI_t)Sys_LoadFunction( rendererLib, "GetRefAPI" ); - if ( !GetRefAPI ) + if (!GetRefAPI && !fallback) + { + Sys_UnloadLibrary(rendererLib); + fallback = qtrue; + Com_Printf("Can't load symbol GetRefAPI: trying to load fallback renderer\n"); + Cvar_ForceReset("cl_renderer"); + + Com_sprintf(dllName, sizeof(dllName), DEFAULT_RENDER_LIBRARY "_" ARCH_STRING DLL_EXT); + rendererLib = Sys_LoadDll(dllName, qfalse); + if (rendererLib) + GetRefAPI = (GetRefAPI_t)Sys_LoadFunction(rendererLib, "GetRefAPI"); + } + + if (!GetRefAPI ) Com_Error( ERR_FATAL, "Can't load symbol GetRefAPI: '%s'", Sys_LibraryError() ); #define RIT(y) rit.y = y @@ -1189,6 +1204,25 @@ void CL_InitRef( void ) { ret = GetRefAPI( REF_API_VERSION, &rit ); + if (!ret && !fallback) + { + Sys_UnloadLibrary(rendererLib); + fallback = qtrue; + Com_Printf("Version mismatch: trying to load fallback renderer\n"); + Cvar_ForceReset("cl_renderer"); + + Com_sprintf(dllName, sizeof(dllName), DEFAULT_RENDER_LIBRARY "_" ARCH_STRING DLL_EXT); + rendererLib = Sys_LoadDll(dllName, qfalse); + if (rendererLib) + { + GetRefAPI = (GetRefAPI_t)Sys_LoadFunction(rendererLib, "GetRefAPI"); + if (GetRefAPI) + { + ret = GetRefAPI(REF_API_VERSION, &rit); + } + } + } + if ( !ret ) { Com_Error (ERR_FATAL, "Couldn't initialize refresh" ); } diff --git a/code/game/AI_BobaFett.cpp b/code/game/AI_BobaFett.cpp index 3f16e01288..41435a5bef 100644 --- a/code/game/AI_BobaFett.cpp +++ b/code/game/AI_BobaFett.cpp @@ -429,10 +429,6 @@ void Boba_FlyStart( gentity_t *self ) G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); - if ( self->NPC ) - { - self->count = Q3_INFINITE; // SEEKER shot ammo count - } } } @@ -461,7 +457,6 @@ void Boba_FlyStop( gentity_t *self ) self->s.loopSound = 0; if ( self->NPC ) { - self->count = 0; // SEEKER shot ammo count TIMER_Set( self, "jetRecharge", Q_irand( 1000, 5000 ) ); TIMER_Set( self, "jumpChaseDebounce", Q_irand( 500, 2000 ) ); } diff --git a/code/game/AI_RocketTrooper.cpp b/code/game/AI_RocketTrooper.cpp index 69ac2f99bb..cab13a65b8 100644 --- a/code/game/AI_RocketTrooper.cpp +++ b/code/game/AI_RocketTrooper.cpp @@ -389,10 +389,6 @@ void RT_FlyStart( gentity_t *self ) G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); - if ( self->NPC ) - { - self->count = Q3_INFINITE; // SEEKER shot ammo count - } } } @@ -417,7 +413,6 @@ void RT_FlyStop( gentity_t *self ) if ( self->NPC ) { - self->count = 0; // SEEKER shot ammo count TIMER_Set( self, "jetRecharge", Q_irand( 1000, 5000 ) ); TIMER_Set( self, "jumpChaseDebounce", Q_irand( 500, 2000 ) ); } diff --git a/code/game/bg_panimate.cpp b/code/game/bg_panimate.cpp index 084cba851c..5d82da52cb 100644 --- a/code/game/bg_panimate.cpp +++ b/code/game/bg_panimate.cpp @@ -4730,7 +4730,7 @@ void PM_SetAnimFinal(int *torsoAnim,int *legsAnim, const bool animSync = (g_synchSplitAnims->integer!=0 && !animRestart); float animCurrent = (-1.0f); float animSpeed = (50.0f / curAnim.frameLerp * timeScaleMod); // animSpeed is 1.0 if the frameLerp (ms/frame) is 50 (20 fps). - const float animFPS = (fabsf(curAnim.frameLerp)); + const float animFPS = (::abs(curAnim.frameLerp)); const int animDurMSec = (int)(((curAnim.numFrames - 1) * animFPS) / timeScaleMod); const int animHoldMSec = ((animHoldless && timeScaleMod==1.0f)?((animDurMSec>1)?(animDurMSec-1):(animFPS)):(animDurMSec)); int animFlags = (curAnim.loopFrames!=-1)?(BONE_ANIM_OVERRIDE_LOOP):(BONE_ANIM_OVERRIDE_FREEZE); diff --git a/code/game/bg_public.h b/code/game/bg_public.h index 2469a95d10..d7eab3b1ba 100644 --- a/code/game/bg_public.h +++ b/code/game/bg_public.h @@ -459,7 +459,7 @@ typedef enum { EV_DEBUG_LINE, EV_KOTHOS_BEAM, - + EV_NUM_ENTITY_EVENTS } entity_event_t; class animation_t diff --git a/code/game/g_active.cpp b/code/game/g_active.cpp index c09a9613b1..f316c2c9c3 100644 --- a/code/game/g_active.cpp +++ b/code/game/g_active.cpp @@ -4297,11 +4297,7 @@ void G_CheckClientIdle( gentity_t *ent, usercmd_t *ucmd ) { return; } - if ( !ent->s.number && (cg_trueguns.integer || (!cg.renderingThirdPerson && (ent->client->ps.weapon == WP_SABER || ent->client->ps.weapon == WP_MELEE)) ) ) - { - return; - } - if ( !ent->s.number && ( /*!cg.renderingThirdPerson ||*/ cg.zoomMode ) ) + if ( !ent->s.number && ( !cg.renderingThirdPerson || cg.zoomMode ) ) { if ( ent->client->idleTime < level.time ) { diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index 68e39af161..2600bbbc8b 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -699,6 +699,10 @@ extern gitem_t *FindItemForInventory( int inv ); RegisterItem( FindItemForWeapon( (weapon_t)i++ ) ); } } + else + { + i++; + } /* Get next token: */ var = strtok( NULL, " " ); } diff --git a/code/game/g_combat.cpp b/code/game/g_combat.cpp index 1caf812ee7..275eec0497 100644 --- a/code/game/g_combat.cpp +++ b/code/game/g_combat.cpp @@ -50,6 +50,7 @@ extern cvar_t *d_slowmodeath; extern gentity_t *player; extern cvar_t *debug_subdivision; extern cvar_t *g_dismemberProbabilities; +extern cvar_t *g_broadsword; gentity_t *g_lastClientDamaged; @@ -4649,7 +4650,7 @@ extern void RunEmplacedWeapon( gentity_t *ent, usercmd_t **ucmd ); self->client->respawnTime = level.time + 2000;//self->client->ps.legsAnimTimer; //rww - RAGDOLL_BEGIN - if (gi.Cvar_VariableIntegerValue("broadsword")) + if (g_broadsword->integer) { if ( self->client && (!self->NPC || !G_StandardHumanoid( self ) ) ) { diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index e554e830e1..31d63650e0 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -682,9 +682,9 @@ void G_InitCvars( void ) { com_buildScript = gi.cvar ("com_buildscript", "0", 0); g_saberAutoBlocking = gi.cvar( "g_saberAutoBlocking", "1", CVAR_CHEAT );//must press +block button to do any blocking - g_saberRealisticCombat = gi.cvar( "g_saberMoreRealistic", "0", CVAR_CHEAT );//makes collision more precise, increases damage - debug_subdivision = gi.cvar( "debug_subdivision", "0", CVAR_CHEAT|CVAR_INIT );//debug for dismemberment - g_dismemberProbabilities = gi.cvar ( "g_dismemberProbabilities", "1", CVAR_CHEAT );//0 = ignore probabilities, 1 = use probabilities + g_saberRealisticCombat = gi.cvar( "g_saberMoreRealistic", "0", CVAR_ARCHIVE );//makes collision more precise, increases damage + debug_subdivision = gi.cvar( "debug_subdivision", "0", CVAR_ARCHIVE );//debug for dismemberment + g_dismemberProbabilities = gi.cvar ( "g_dismemberProbabilities", "1", CVAR_ARCHIVE );//0 = ignore probabilities, 1 = use probabilities g_saberDamageCapping = gi.cvar( "g_saberDamageCapping", "1", CVAR_CHEAT );//caps damage of sabers vs players and NPC who use sabers g_saberMoveSpeed = gi.cvar( "g_saberMoveSpeed", "1", CVAR_CHEAT );//how fast you run while attacking with a saber g_saberAnimSpeed = gi.cvar( "g_saberAnimSpeed", "1", CVAR_CHEAT );//how fast saber animations run diff --git a/code/game/g_roff.cpp b/code/game/g_roff.cpp index a337b28423..5dd6381f42 100644 --- a/code/game/g_roff.cpp +++ b/code/game/g_roff.cpp @@ -24,9 +24,11 @@ along with this program; if not, see . #include "g_roff.h" #include "Q3_Interface.h" #include "../cgame/cg_local.h" +#include "../cgame/cg_media.h" #include "g_functions.h" #include "qcommon/ojk_saved_game_helper.h" + // The list of precached ROFFs roff_list_t roffs[MAX_ROFFS]; int num_roffs = 0; @@ -35,7 +37,8 @@ qboolean g_bCollidableRoffs = qfalse; extern void Q3_TaskIDComplete( gentity_t *ent, taskID_t taskType ); -static void G_RoffNotetrackCallback( gentity_t *cent, const char *notetrack) + +static void G_RoffNotetrackCallback( gentity_t *ent, const char *notetrack) { int i = 0, r = 0, r2 = 0, objectID = 0, anglesGathered = 0, posoffsetGathered = 0; char type[256]; @@ -47,12 +50,50 @@ static void G_RoffNotetrackCallback( gentity_t *cent, const char *notetrack) int addlArgs = 0; vec3_t parsedAngles, parsedOffset, useAngles, useOrigin, forward, right, up; - if (!cent || !notetrack) + if (!ent || !notetrack) { return; } - //notetrack = "effect effects/explosion1.efx 0+0+64 0-0-1"; + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Supported notetrack types: effect, sound, USE, loop + // + //General notetrack format: [additionalArguments] + //Note: <> denote required argument, [] denote optional argument, | denotes argument choices + // + //Examples: + //effect notetrack format: effect [originOffset] [rotationOffset] + // notetrack = "effect effects/explosion1.efx 0+0+64 0-0-1"; + //'effect' notes: + // (1) the '+' and '-' are delimiters and not positive/negative signs; e.g., negative origin offset would be: -10+-20+-10 + // (2) angles are expected to be from 0 to 360, i.e., no negative angles. + // (3) optional additional argument for rotationOffset requires the originOffset preceding it. + // + // + //sound notetrack format: sound + // notetrack = "sound sound/vehicles/tie/flyby2.mp3"; + //'sound' notes: + // (1) supported sound file formats are: .mp3, .wav + // + // + //USE notetrack format: USE + // notetrack = "USE shuttlemap/shuttletakeoff"; + // + // + //loop notetrack format: loop < absolute | relative > + // loop < relative_soundfilepath.ext | kill > + // notetrack = "loop rof absolute"; + // notetrack = "loop rof relative"; + // notetrack = "loop sfx sound/vehicles/tie/loop.wav"; + // notetrack = "loop sfx kill"; + //'loop rof' notes: + // (1) absolute ==> reset rof to original delta position/rotation world location before looping. + // (2) relative ==> reset rof to original delta position/rotation at current location before looping. + //'loop sfx' notes: + // (1) adds a sound to be looped which gets assigned to the entitystate's loopSound parameter. + // (2) addlArg 'kill' -- kills the looping sound by setting entitystate's loopSound equal to zero. + // + ////////////////////////////////////////////////////////////////////////////////////////////////////////// while (notetrack[i] && notetrack[i] != ' ') { @@ -122,7 +163,7 @@ static void G_RoffNotetrackCallback( gentity_t *cent, const char *notetrack) t[r] = '\0'; i++; if (!r) - { //failure.. + { //failure... VectorClear(parsedOffset); i = 0; goto defaultoffsetposition; @@ -210,18 +251,18 @@ static void G_RoffNotetrackCallback( gentity_t *cent, const char *notetrack) VectorCopy(parsedAngles, useAngles); } else - { //failed to parse angles from the extra argument provided.. - VectorCopy(cent->s.apos.trBase, useAngles); + { //failed to parse angles from the extra argument provided... + VectorCopy(ent->s.apos.trBase, useAngles); } } else { //if no constant angles, play in direction entity is facing - VectorCopy(cent->s.apos.trBase, useAngles); + VectorCopy(ent->s.apos.trBase, useAngles); } AngleVectors(useAngles, forward, right, up); - VectorCopy(cent->s.pos.trBase, useOrigin); + VectorCopy(ent->s.pos.trBase, useOrigin); //forward useOrigin[0] += forward[0]*parsedOffset[0]; @@ -238,34 +279,188 @@ static void G_RoffNotetrackCallback( gentity_t *cent, const char *notetrack) useOrigin[1] += up[1]*parsedOffset[2]; useOrigin[2] += up[2]*parsedOffset[2]; + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + G_PlayEffect(objectID, useOrigin, useAngles); } } else if (strcmp(type, "sound") == 0) { - objectID = G_SoundIndex(argument); - cgi_S_StartSound(cent->s.pos.trBase, cent->s.number, CHAN_BODY, objectID); + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + + //check for eType and play the sound + if (ent->s.eType == ET_MOVER) + { + objectID = cgi_S_RegisterSound(argument); + cgi_S_StartSound(ent->s.pos.trBase, ent->s.number, CHAN_BODY, objectID); + } + else + { + G_SoundOnEnt(ent, CHAN_BODY, argument); + } + } + else if (strcmp(type, "USE") == 0) + { + //try to cache the script + Quake3Game()->PrecacheScript(argument); + + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + + //run the IBI script + Quake3Game()->RunScript(ent, argument); + } + else if (strcmp(type, "loop") == 0) + { + if (strcmp(argument, "rof") == 0) + { + if (strcmp(addlArg, "absolute") == 0) + { + VectorClear(ent->pos1); + VectorClear(ent->pos2); + + VectorClear(ent->currentOrigin); + VectorClear(ent->currentAngles); + + VectorClear(ent->s.pos.trBase); + VectorClear(ent->s.apos.trBase); + + VectorClear(ent->s.origin2); + VectorClear(ent->s.angles2); + } + else if (strcmp(addlArg, "relative") == 0) + { + VectorCopy(ent->s.origin2, ent->s.pos.trBase); + VectorCopy(ent->s.origin2, ent->currentOrigin); + VectorCopy(ent->s.angles2, ent->s.apos.trBase); + VectorCopy(ent->s.angles2, ent->currentAngles); + } + else + { + sprintf(errMsg, "Invalid additional argument <%s> for type 'loop rof'", addlArg); + goto functionend; + } + + // Start the ROFF from the beginning + ent->roff_ctr = 0; + + // Let the ROFF playing start + ent->next_roff_time = level.time; + + //Re-link entity + gi.linkentity(ent); + + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + + // Re-apply the ROFF + G_Roff(ent); + } + else if (strcmp(argument, "sfx") == 0) + { + //check additional argument for relative sound path + r = 0; + r2 = 0; + + if (addlArg[r] == '/') + { + r++; + } + while (addlArg[r] && addlArg[r] != '/') + { + teststr[r2] = addlArg[r]; + r2++; + r++; + } + teststr[r2] = '\0'; + + if (r2 && strstr(teststr, "kill")) + { // kill the looping sound + ent->s.loopSound = 0; + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + } + else if (r2 && strstr(teststr, "sound")) + { // OK... we should have a relative sound path + //try to register the sound and add it to the entitystate loopSound parameter + if (ent->s.eType == ET_MOVER) + { + objectID = cgi_S_RegisterSound(addlArg); + if (objectID) + { + ent->s.loopSound = objectID; + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + } + else + { + ent->s.loopSound = 0; + sprintf(errMsg, "cgi_S_RegisterSound(%s) failed to return a valid sfxHandle_t for additional argument. Setting 'loopSound' to 0.", addlArg); + goto functionend; + } + } + else + { + ent->s.loopSound = G_SoundIndex(addlArg); + if (g_developer->integer) + { + Com_Printf(S_COLOR_GREEN "NoteTrack: \"%s\"\n", notetrack); + } + } + } + else + { + sprintf(errMsg, "Invalid additional argument <%s> for type 'loop sfx'", addlArg); + goto functionend; + } + } + else + { + sprintf(errMsg, "Invalid argument <%s> for type 'loop' notetrack.", argument); + goto functionend; + } } //else if ... else { if (type[0]) { - Com_Printf("Warning: \"%s\" is an invalid ROFF notetrack function\n", type); + Com_Printf(S_COLOR_YELLOW"Warning: \"%s\" is an invalid ROFF NoteTrack function\n", type); } else { - Com_Printf("Warning: Notetrack is missing function and/or arguments\n"); + Com_Printf(S_COLOR_YELLOW"Warning: NoteTrack is missing function and/or arguments\n"); } } return; functionend: - Com_Printf("Type-specific notetrack error: %s\n", errMsg); + Com_Printf(S_COLOR_RED"Type-specific NoteTrack error: %s\n", errMsg); return; } + +//------------------------------------------------------- +// G_ValidRoff +// +// Checks header to verify we have a valid .ROF file +//------------------------------------------------------- + static qboolean G_ValidRoff( roff_hdr2_t *header ) { if ( !strncmp( header->mHeader, "ROFF", 4 )) @@ -283,6 +478,13 @@ static qboolean G_ValidRoff( roff_hdr2_t *header ) return qfalse; } + +//------------------------------------------------------- +// G_FreeRoff +// +// Deletes all .ROF files from memory +//------------------------------------------------------- + static void G_FreeRoff(int index) { if(roffs[index].mNumNoteTracks) { @@ -291,6 +493,13 @@ static void G_FreeRoff(int index) } } + +//------------------------------------------------------- +// G_InitRoff +// +// Initializes the .ROF file +//------------------------------------------------------- + static qboolean G_InitRoff( char *file, unsigned char *data ) { roff_hdr_t *header = (roff_hdr_t *)data; @@ -412,6 +621,7 @@ static qboolean G_InitRoff( char *file, unsigned char *data ) roffs[num_roffs].mNoteTrackIndexes[i] = ptr; } } + return qtrue; } } @@ -419,6 +629,7 @@ static qboolean G_InitRoff( char *file, unsigned char *data ) return qfalse; } + //------------------------------------------------------- // G_LoadRoff // @@ -472,7 +683,7 @@ int G_LoadRoff( const char *fileName ) // ..and make sure it's reasonably valid if ( !G_ValidRoff( header )) { - Com_Printf( S_COLOR_RED"Invalid roff format '%s'\n", fileName ); + Com_Printf( S_COLOR_RED"Invalid .ROF format '%s'\n", fileName ); } else { @@ -531,9 +742,13 @@ void G_Roff( gentity_t *ent ) move_rotate2_t *data = &((move_rotate2_t *)roff->data)[ ent->roff_ctr ]; VectorCopy( data->origin_delta, org ); VectorCopy( data->rotate_delta, ang ); - if (data->mStartNote != -1 || data->mNumNotes) + + if ( data->mStartNote != -1 ) { - G_RoffNotetrackCallback(ent, roffs[roff_id - 1].mNoteTrackIndexes[data->mStartNote]); + for ( int n = 0; n < data->mNumNotes; n++ ) + { + G_RoffNotetrackCallback(ent, roffs[roff_id - 1].mNoteTrackIndexes[data->mStartNote + n]); + } } } else diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index ea3df64fd9..db7ad00a9f 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -2507,9 +2507,9 @@ qboolean WP_SaberDamageEffects( trace_t *tr, const vec3_t start, float length, f } //Get the hit location based on surface name - if ( (hitLoc[hitEntNum[numHitEnts]] == HL_NONE && trHitLoc[numHitEnts] == HL_NONE) - || (hitDismemberLoc[hitEntNum[numHitEnts]] == HL_NONE && trDismemberLoc[numHitEnts] == HL_NONE) - || (!hitDismember[hitEntNum[numHitEnts]] && !trDismember[numHitEnts]) ) + if ( (hitLoc[numHitEnts] == HL_NONE && trHitLoc[numHitEnts] == HL_NONE) + || (hitDismemberLoc[numHitEnts] == HL_NONE && trDismemberLoc[numHitEnts] == HL_NONE) + || (!hitDismember[numHitEnts] && !trDismember[numHitEnts]) ) {//no hit loc set for this ent this damage cycle yet //FIXME: find closest impact surf *first* (per ent), then call G_GetHitLocFromSurfName? //FIXED: if hit multiple ents in this collision record, these trSurfName, trDismember and trDismemberLoc will get stomped/confused over the multiple ents I hit diff --git a/code/rd-common/mdx_format.h b/code/rd-common/mdx_format.h index c205c611db..989b20929e 100644 --- a/code/rd-common/mdx_format.h +++ b/code/rd-common/mdx_format.h @@ -432,10 +432,11 @@ typedef struct { // // (iFrameNum * mdxaHeader_t->numBones * 3) + (iBoneNum * 3) // - // then read the int at that location and AND it with 0x00FFFFFF. I use the struct below simply for easy searches + // Then convert the three byte int at that location. + // This struct is used for easy searches. typedef struct { - int iIndex; // this struct for pointing purposes, need to and with 0x00FFFFFF to be meaningful + byte iIndex[3]; } mdxaIndex_t; // // (note that there's then an alignement-pad here to get the next struct back onto 32-bit alignement) diff --git a/code/rd-common/tr_types.h b/code/rd-common/tr_types.h index f4b870120e..3a560f04b3 100644 --- a/code/rd-common/tr_types.h +++ b/code/rd-common/tr_types.h @@ -254,6 +254,8 @@ typedef struct glconfig_s { int displayFrequency; + qboolean doStencilShadowsInOneDrawcall; + // synonymous with "does rendering consume the entire screen?", therefore // a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that // used CDS. diff --git a/code/rd-vanilla/glext.h b/code/rd-vanilla/glext.h index 63ea7f2465..09d03652d8 100644 --- a/code/rd-vanilla/glext.h +++ b/code/rd-vanilla/glext.h @@ -1,5 +1,5 @@ -#ifndef __glext_h_ -#define __glext_h_ 1 +#ifndef __gl_glext_h_ +#define __gl_glext_h_ 1 #ifdef __cplusplus extern "C" { @@ -11767,4 +11767,4 @@ GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (co } #endif -#endif \ No newline at end of file +#endif diff --git a/code/rd-vanilla/qgl.h b/code/rd-vanilla/qgl.h index f9fc10f312..c9215dbd13 100644 --- a/code/rd-vanilla/qgl.h +++ b/code/rd-vanilla/qgl.h @@ -306,6 +306,9 @@ along with this program; if not, see . #define qglStencilFunc glStencilFunc #define qglStencilMask glStencilMask #define qglStencilOp glStencilOp +#if defined(__APPLE__) +#define qglStencilOpSeparate glStencilOpSeparate +#endif #define qglTexCoord1d glTexCoord1d #define qglTexCoord1dv glTexCoord1dv #define qglTexCoord1f glTexCoord1f @@ -386,6 +389,10 @@ along with this program; if not, see . #define qglVertexPointer glVertexPointer #define qglViewport glViewport +#if !defined(__APPLE__) +extern PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate; +#endif + extern PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB; extern PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB; extern PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB; diff --git a/code/rd-vanilla/tr_ghoul2.cpp b/code/rd-vanilla/tr_ghoul2.cpp index 1c9fa5c7f0..04f7f27c5b 100644 --- a/code/rd-vanilla/tr_ghoul2.cpp +++ b/code/rd-vanilla/tr_ghoul2.cpp @@ -927,21 +927,15 @@ void Multiply_3x4Matrix(mdxaBone_t *out,const mdxaBone_t *in2,const mdxaBone_t out->matrix[2][3] = (in2->matrix[2][0] * in->matrix[0][3]) + (in2->matrix[2][1] * in->matrix[1][3]) + (in2->matrix[2][2] * in->matrix[2][3]) + in2->matrix[2][3]; } -static int G2_GetBonePoolIndex( const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) +static int G2_GetBonePoolIndex(const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) { assert(iFrame>=0&&iFramenumFrames); assert(iBone>=0&&iBonenumBones); - const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); - mdxaIndex_t *pIndex = (mdxaIndex_t *) ((byte*) pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); + const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); + mdxaIndex_t *pIndex = (mdxaIndex_t *)((byte*)pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); -#ifdef Q3_BIG_ENDIAN - int tmp = pIndex->iIndex & 0xFFFFFF00; - LL(tmp); - return tmp; -#else - return pIndex->iIndex & 0x00FFFFFF; -#endif + return (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); } @@ -3585,18 +3579,31 @@ qboolean R_LoadMDXM( model_t *mod, void *buffer, const char *mod_name, qboolean // first up, go load in the animation file we need that has the skeletal animation info for this model mdxm->animIndex = RE_RegisterModel(va ("%s.gla",mdxm->animName)); - if (!strcmp(mdxm->animName,"models/players/_humanoid/_humanoid")) - { //if we're loading the humanoid, look for a cinematic gla for this map - const char*mapname = sv_mapname->string; - if (strcmp(mapname,"nomap") ) + + char animGLAName[MAX_QPATH]; + char *strippedName; + char *slash = NULL; + const char*mapname = sv_mapname->string; + + if (strcmp(mapname,"nomap") ) + { + if (strrchr(mapname,'/') ) //maps in subfolders use the root name, ( presuming only one level deep!) { - if (strrchr(mapname,'/') ) //maps in subfolders use the root name, ( presuming only one level deep!) - { - mapname = strrchr(mapname,'/')+1; - } - RE_RegisterModel(va ("models/players/_humanoid_%s/_humanoid_%s.gla",mapname,mapname)); + mapname = strrchr(mapname,'/')+1; } - } + //stripped name of GLA for this model + Q_strncpyz(animGLAName, mdxm->animName, sizeof(animGLAName)); + slash = strrchr(animGLAName, '/'); + if (slash) + { + *slash = 0; + } + strippedName = COM_SkipPath(animGLAName); + if (VALIDSTRING(strippedName)) + { + RE_RegisterModel(va("models/players/%s_%s/%s_%s.gla", strippedName, mapname, strippedName, mapname)); + } + } #ifndef JK2_MODE bool isAnOldModelFile = false; @@ -3831,6 +3838,7 @@ qboolean R_LoadMDXA( model_t *mod, void *buffer, const char *mod_name, qboolean mdxaCompQuatBone_t *pCompBonePool; unsigned short *pwIn; mdxaIndex_t *pIndex; + int tmp; #endif pinmodel = (mdxaHeader_t *)buffer; @@ -3920,24 +3928,24 @@ qboolean R_LoadMDXA( model_t *mod, void *buffer, const char *mod_name, qboolean } } - // find the largest index, since the actual number of compressed bone pools is not stored anywhere - for ( i = 0 ; i < mdxa->numFrames ; i++ ) - { - for ( j = 0 ; j < mdxa->numBones ; j++ ) - { - k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex - pIndex = (mdxaIndex_t *) ((byte*) mdxa + mdxa->ofsFrames + k); + // Determine the amount of compressed bones. - // 3 byte ints, yeah... - int tmp = pIndex->iIndex & 0xFFFFFF00; - LL(tmp); + // Find the largest index by iterating through all frames. + // It is not guaranteed that the compressed bone pool resides + // at the end of the file. + for(i = 0; i < mdxa->numFrames; i++){ + for(j = 0; j < mdxa->numBones; j++){ + k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex + pIndex = (mdxaIndex_t *) ((byte *)mdxa + mdxa->ofsFrames + k); + tmp = (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); - if (maxBoneIndex < tmp) + if(maxBoneIndex < tmp){ maxBoneIndex = tmp; + } } } - // swap the compressed bones + // Swap the compressed bones. pCompBonePool = (mdxaCompQuatBone_t *) ((byte *)mdxa + mdxa->ofsCompBonePool); for ( i = 0 ; i <= maxBoneIndex ; i++ ) { diff --git a/code/rd-vanilla/tr_init.cpp b/code/rd-vanilla/tr_init.cpp index 6ac4e8fb94..eb371304d6 100644 --- a/code/rd-vanilla/tr_init.cpp +++ b/code/rd-vanilla/tr_init.cpp @@ -185,8 +185,11 @@ cvar_t *com_buildScript; cvar_t *r_environmentMapping; cvar_t *r_screenshotJpegQuality; -cvar_t *r_swapInterval; +cvar_t* r_swapInterval; +#if !defined(__APPLE__) +PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate; +#endif PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB; PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB; @@ -671,6 +674,16 @@ static void GLimp_InitExtensions( void ) g_bDynamicGlowSupported = false; ri.Cvar_Set( "r_DynamicGlow","0" ); } + +#if !defined(__APPLE__) + qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri->GL_GetProcAddress("glStencilOpSeparate"); + if (qglStencilOpSeparate) + { + glConfig.doStencilShadowsInOneDrawcall = qtrue; + } +#else + glConfig.doStencilShadowsInOneDrawcall = qtrue; +#endif } /* diff --git a/code/rd-vanilla/tr_shadows.cpp b/code/rd-vanilla/tr_shadows.cpp index 905ab098af..c1cb97a25c 100644 --- a/code/rd-vanilla/tr_shadows.cpp +++ b/code/rd-vanilla/tr_shadows.cpp @@ -354,28 +354,24 @@ void RB_DoShadowTessEnd( vec3_t lightPos ) qglDepthFunc(GL_LESS); //now using the Carmack Reverse -rww - if ( backEnd.viewParms.isMirror ) { - //qglCullFace( GL_BACK ); - GL_Cull(CT_BACK_SIDED); - qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); - - R_RenderShadowEdges(); - - //qglCullFace( GL_FRONT ); - GL_Cull(CT_FRONT_SIDED); - qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); + if (glConfig.doStencilShadowsInOneDrawcall) + { + GL_Cull(CT_TWO_SIDED); + qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); + qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); R_RenderShadowEdges(); - } else { - //qglCullFace( GL_FRONT ); + qglDisable(GL_STENCIL_TEST); + } + else + { GL_Cull(CT_FRONT_SIDED); - qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); + qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); R_RenderShadowEdges(); - //qglCullFace( GL_BACK ); GL_Cull(CT_BACK_SIDED); - qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); + qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); R_RenderShadowEdges(); } diff --git a/code/server/sv_ccmds.cpp b/code/server/sv_ccmds.cpp index 4b3e570b86..0e3a7a11d9 100644 --- a/code/server/sv_ccmds.cpp +++ b/code/server/sv_ccmds.cpp @@ -131,7 +131,7 @@ void SV_Player_EndOfLevelSave(void) ); #else // |general info |-force powers |-saber 1 |-saber 2 |-general saber - s = va("%i %i %i %i %i %i %f %f %f %i %i %i %i %i %s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i &i %i %i %i %i", + s = va("%i %i %i %i %i %i %f %f %f %i %i %i %i %i %s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %s %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", pState->stats[STAT_HEALTH], pState->stats[STAT_ARMOR], pState->stats[STAT_ITEMS], diff --git a/code/ui/menudef.h b/code/ui/menudef.h index afe5f09a25..597e652ef4 100644 --- a/code/ui/menudef.h +++ b/code/ui/menudef.h @@ -36,6 +36,7 @@ along with this program; if not, see . #define ITEM_TYPE_BIND 13 // multiple list setting, enumerated #define ITEM_TYPE_TEXTSCROLL 14 // scrolling text #define ITEM_TYPE_SLIDER_INTEGER 15 +#define ITEM_TYPE_SLIDER_ROTATE 16 #define ITEM_ALIGN_LEFT 0 // left alignment @@ -112,6 +113,9 @@ along with this program; if not, see . #define FEEDER_SABER2_SKIN_4 0x21 #define FEEDER_SABER2_SKIN_5 0x22 +#define FEEDER_SABER_SINGLE_INFO 0x23 +#define FEEDER_SABER_STAFF_INFO 0x24 + #define UI_VERSION 200 #define UI_HANDICAP 200 diff --git a/code/ui/ui_local.h b/code/ui/ui_local.h index f274a314a6..3097a8ab0f 100644 --- a/code/ui/ui_local.h +++ b/code/ui/ui_local.h @@ -34,6 +34,7 @@ along with this program; if not, see . #include "ui_shared.h" #define MAX_DEFERRED_SCRIPT 1024 +#define MAX_SABER_HILTS 256 // // ui_qmenu.c diff --git a/code/ui/ui_main.cpp b/code/ui/ui_main.cpp index 9c0ea6b469..51bb404d44 100644 --- a/code/ui/ui_main.cpp +++ b/code/ui/ui_main.cpp @@ -55,11 +55,16 @@ extern qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name ); extern qboolean ItemParse_asset_model_go_head( itemDef_t *item, const char *name, qboolean cleanuponly ); extern qboolean ItemParse_model_g2skin_go( itemDef_t *item, const char *skinName ); extern qboolean UI_SaberModelForSaber( const char *saberName, char *saberModel ); +extern qboolean UI_SaberProperNameForSaber( const char* saberName, char* saberProperName ); extern qboolean UI_SaberSkinForSaber( const char *saberName, char *saberSkin, qboolean secondSaber ); +extern void UI_SaberGetHiltInfo(const char* singleHilts[MAX_SABER_HILTS], const char* staffHilts[MAX_SABER_HILTS]); extern void UI_SaberAttachToChar( itemDef_t *item ); extern qboolean PC_Script_Parse(const char **out); +const char* saberSingleHiltInfo[MAX_SABER_HILTS]; +const char* saberStaffHiltInfo[MAX_SABER_HILTS]; + #define LISTBUFSIZE 10240 static struct @@ -113,6 +118,7 @@ static void UI_GetCharacterCvars ( void ); static void UI_UpdateSaberCvars ( void ); static void UI_GetSaberCvars ( void ); static void UI_ResetSaberCvars ( void ); +static void UI_SetSaberFeeders(void); static void UI_InitAllocForcePowers ( const char *forceName ); static void UI_AffectForcePowerLevel ( const char *forceName ); static void UI_ShowForceLevelDesc ( const char *forceName ); @@ -451,6 +457,8 @@ vmCvar_t ui_hilt2_color_red; vmCvar_t ui_hilt2_color_green; vmCvar_t ui_hilt2_color_blue; +vmCvar_t ui_char_model_angle; + static void UI_UpdateScreenshot( void ) { qboolean changed = qfalse; @@ -557,7 +565,8 @@ static cvarTable_t cvarTable[] = { &ui_SFXSabers, "cg_SFXSabers", "1", NULL, CVAR_ARCHIVE }, { &ui_SFXSabersGlowSize, "cg_SFXSabersGlowSize", "1.0", NULL, CVAR_ARCHIVE }, { &ui_SFXSabersCoreSize, "cg_SFXSabersCoreSize", "1.0", NULL, CVAR_ARCHIVE }, - + + { &ui_char_model_angle, "ui_char_model_angle", "180", NULL, 0}, }; @@ -768,6 +777,7 @@ void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const cha const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t *handle) { + static char info[MAX_STRING_CHARS]; // don't change this size without changing the sizes inside the SaberProperName calls *handle = -1; if (feederID == FEEDER_SAVEGAMES) @@ -925,6 +935,16 @@ const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t * return uiInfo.customSabers[uiInfo.customSabers2Index].Skin5.skins[index].name; } } + else if (feederID == FEEDER_SABER_SINGLE_INFO) + { + UI_SaberProperNameForSaber(saberSingleHiltInfo[index], info); + return info; + } + else if (feederID == FEEDER_SABER_STAFF_INFO) + { + UI_SaberProperNameForSaber(saberStaffHiltInfo[index], info); + return info; + } else if (feederID == FEEDER_MODS) { if (index >= 0 && index < uiInfo.modCount) @@ -1969,10 +1989,90 @@ static qboolean UI_RunMenuScript ( const char **args ) { UI_ResetCharacterListBoxes(); } + else if (Q_stricmp(name, "getsaberhiltinfo") == 0) + { + UI_SaberGetHiltInfo(saberSingleHiltInfo, saberStaffHiltInfo); + } else if ( Q_stricmp( name, "LaunchMP" ) == 0 ) { // TODO for MAC_PORT, will only be valid for non-JK2 mode } + else if (Q_stricmp(name, "setscreensaberhilt") == 0) + { + menuDef_t* menu; + itemDef_t* item; + + menu = Menu_GetFocused(); // Get current menu + if (menu) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut"); + if (item) + { + if (saberSingleHiltInfo[item->cursorPos]) + { + Cvar_Set("ui_saber", saberSingleHiltInfo[item->cursorPos]); + } + } + } + } + else if (Q_stricmp(name, "setscreensaberhilt1") == 0) + { + menuDef_t* menu; + itemDef_t* item; + + menu = Menu_GetFocused(); // Get current menu + if (menu) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut1"); + if (item) + { + if (saberSingleHiltInfo[item->cursorPos]) + { + Cvar_Set("ui_saber", saberSingleHiltInfo[item->cursorPos]); + } + } + } + } + else if (Q_stricmp(name, "setscreensaberhilt2") == 0) + { + menuDef_t* menu; + itemDef_t* item; + + menu = Menu_GetFocused(); // Get current menu + if (menu) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut2"); + if (item) + { + if (saberSingleHiltInfo[item->cursorPos]) + { + Cvar_Set("ui_saber2", saberSingleHiltInfo[item->cursorPos]); + } + } + } + } + else if (Q_stricmp(name, "setscreensaberstaff") == 0) + { + menuDef_t* menu; + itemDef_t* item; + + menu = Menu_GetFocused(); // Get current menu + if (menu) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut_staves"); + if (item) + { + if (saberSingleHiltInfo[item->cursorPos]) + { + Cvar_Set("ui_saber", saberStaffHiltInfo[item->cursorPos]); + } + } + } + } + else if (Q_stricmp(name, "setsaberfeeders") == 0) + { + UI_SetSaberFeeders(); + } else { Com_Printf("unknown UI script %s\n", name); @@ -2317,6 +2417,38 @@ static int UI_FeederCount(float feederID) { return uiInfo.customSabers[uiInfo.customSabers2Index].Skin5.count; } + else if (feederID == FEEDER_SABER_SINGLE_INFO) + { + int count = 0, i; + for (i = 0; i < MAX_SABER_HILTS; i++) + { + if (saberSingleHiltInfo[i]) + { + count++; + } + else + {//done + break; + } + } + return count; + } + else if (feederID == FEEDER_SABER_STAFF_INFO) + { + int count = 0, i; + for (i = 0; i < MAX_SABER_HILTS; i++) + { + if (saberStaffHiltInfo[i]) + { + count++; + } + else + {//done + break; + } + } + return count; + } return 0; } @@ -7789,7 +7921,59 @@ static void UI_GetSaberCvars ( void ) Cvar_Set ( "ui_hilt2_color_red", Cvar_VariableString ( "g_hilt2_color_red" ) ); Cvar_Set ( "ui_hilt2_color_blue", Cvar_VariableString ( "g_hilt2_color_blue" ) ); Cvar_Set ( "ui_hilt2_color_green", Cvar_VariableString ( "g_hilt2_color_green" ) ); +} + +static void UI_SetSaberFeeders(void) +{ + const char* saber1 = Cvar_VariableString("ui_saber"); + const char* saber2 = Cvar_VariableString("ui_saber2"); + menuDef_t* menu; + itemDef_t* item; + menu = Menu_GetFocused(); // Get current menu + + if (!menu) + return; + + for (int i = 0; i < MAX_SABER_HILTS; i++) // Set first saber + { + if (saberSingleHiltInfo[i] && !Q_stricmp(saberSingleHiltInfo[i], saber1)) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut"); + if (item) + { + item->cursorPos = i; + } + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut1"); + if (item) + { + item->cursorPos = i; + } + break; + } + + if (saberStaffHiltInfo[i] && !Q_stricmp(saberStaffHiltInfo[i], saber1)) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut_staves"); + if (item) + { + item->cursorPos = i; + } + break; + } + } + for (int j = 0; j < MAX_SABER_HILTS; j++) //Set second saber + { + if (saberSingleHiltInfo[j] && !Q_stricmp(saberSingleHiltInfo[j], saber2)) + { + item = (itemDef_t*)Menu_FindItemByName((menuDef_t*)menu, "hiltbut2"); + if (item) + { + item->cursorPos = j; + } + break; + } + } } static void UI_ResetSaberCvars ( void ) diff --git a/code/ui/ui_saber.cpp b/code/ui/ui_saber.cpp index 4bd856e8a4..c4c47183c3 100644 --- a/code/ui/ui_saber.cpp +++ b/code/ui/ui_saber.cpp @@ -104,20 +104,22 @@ void UI_CacheSaberGlowGraphics( void ) blackSaberBladeShader = re.RegisterShader( "SFX_Sabers/black_blade" ); } -qboolean UI_ParseLiteral( const char **data, const char *string ) +qboolean UI_ParseLiteral( const char **data, const char *string, qboolean silent ) { const char *token; token = COM_ParseExt( data, qtrue ); if ( token[0] == 0 ) { - ui.Printf( "unexpected EOF\n" ); + if (!silent) + ui.Printf( "unexpected EOF\n" ); return qtrue; } if ( Q_stricmp( token, string ) ) { - ui.Printf( "required string '%s' missing\n", string ); + if (!silent) + ui.Printf( "required string '%s' missing\n", string ); return qtrue; } @@ -162,7 +164,7 @@ qboolean UI_SaberParseParm( const char *saberName, const char *parmname, char *s return qfalse; } - if ( UI_ParseLiteral( &p, "{" ) ) + if ( UI_ParseLiteral( &p, "{", qfalse ) ) { COM_EndParseSession( ); return qfalse; @@ -466,6 +468,109 @@ void UI_SaberLoadParms( void ) } } + +qboolean UI_SaberValidForPlayerInSP(const char* saberName) +{ + char allowed[8] = { 0 }; + if (!UI_SaberParseParm(saberName, "notInMP", allowed)) + {//not defined, default is yes + return qtrue; + } + if (!allowed[0]) + {//not defined, default is yes + return qtrue; + } + else + {//return value + return ((qboolean)(atoi(allowed) == 0)); + } +} + +qboolean UI_IsSaberTwoHanded(const char* saberName) +{ + int twoHanded; + char twoHandedString[8] = { 0 }; + UI_SaberParseParm(saberName, "twoHanded", twoHandedString); + if (!twoHandedString[0]) + {//not defined defaults to "no" + return qfalse; + } + twoHanded = atoi(twoHandedString); + return ((qboolean)(twoHanded != 0)); +} + +void UI_SaberGetHiltInfo(const char* singleHilts[MAX_SABER_HILTS], const char* staffHilts[MAX_SABER_HILTS]) +{ + int numSingleHilts = 0, numStaffHilts = 0; + const char* saberName; + const char* token; + const char* p; + + //check the sabers have been loaded + if (!ui_saber_parms_parsed) + { + UI_SaberLoadParms(); + } + + //go through all the loaded sabers and put the valid ones in the proper list + p = SaberParms; + COM_BeginParseSession(); + + // look for a saber + while (p) + { + token = COM_ParseExt(&p, qtrue); + if (token[0] == 0) + {//invalid name + continue; + } + saberName = String_Alloc(token); + //see if there's a "{" on the next line + SkipRestOfLine(&p); + + if (UI_ParseLiteral(&p, "{", qtrue)) + {//nope, not a name, keep looking + continue; + } + + //this is a saber name + if (!UI_SaberValidForPlayerInSP(saberName)) + { + SkipBracedSection(&p); + continue; + } + + if (UI_IsSaberTwoHanded(saberName)) + { + if (numStaffHilts < MAX_SABER_HILTS - 1)//-1 because we have to NULL terminate the list + { + staffHilts[numStaffHilts++] = saberName; + } + else + { + Com_Printf("WARNING: too many two-handed sabers, ignoring saber '%s'\n", saberName); + } + } + else + { + if (numSingleHilts < MAX_SABER_HILTS - 1)//-1 because we have to NULL terminate the list + { + singleHilts[numSingleHilts++] = saberName; + } + else + { + Com_Printf("WARNING: too many one-handed sabers, ignoring saber '%s'\n", saberName); + } + } + //skip the whole braced section and move on to the next entry + SkipBracedSection(&p); + } + //null terminate the list so the UI code knows where to stop listing them + singleHilts[numSingleHilts] = NULL; + staffHilts[numStaffHilts] = NULL; + COM_EndParseSession(); +} + void UI_DoSFXSaber( vec3_t blade_muz, vec3_t blade_dir, float lengthMax, float radius, saber_colors_t color, saber_crystals_t crystals, int whichSaber ) { vec3_t mid; diff --git a/code/ui/ui_shared.cpp b/code/ui/ui_shared.cpp index 3c3a88ef4b..986abdce91 100644 --- a/code/ui/ui_shared.cpp +++ b/code/ui/ui_shared.cpp @@ -67,6 +67,8 @@ extern vmCvar_t ui_rgb_saber2_red; extern vmCvar_t ui_rgb_saber2_green; extern vmCvar_t ui_rgb_saber2_blue; +extern vmCvar_t ui_char_model_angle; + void *UI_Alloc( int size ); void Controls_GetConfig( void ); @@ -197,6 +199,7 @@ const char *types [] = { "ITEM_TYPE_BIND", "ITEM_TYPE_TEXTSCROLL", "ITEM_TYPE_SLIDER_INTEGER", +"ITEM_TYPE_SLIDER_ROTATE", NULL }; @@ -4539,6 +4542,13 @@ qboolean ItemParse_cvar( itemDef_t *item) editPtr->maxVal = -1; editPtr->defVal = -1; break; + case ITEM_TYPE_SLIDER_ROTATE: + editPtr = (editFieldDef_t*)item->typeData; + editPtr->range = 720; + editPtr->minVal = -1; + editPtr->maxVal = -1; + editPtr->defVal = -1; + break; } } return qtrue; @@ -4647,6 +4657,30 @@ qboolean ItemParse_cvarFloat( itemDef_t *item) return qfalse; } +/* + =============== + ItemParse_cvarRotateScale + =============== + */ +qboolean ItemParse_cvarRotateScale( itemDef_t *item) +{ + editFieldDef_t *editPtr; + + Item_ValidateTypeData(item); + if (!item->typeData) + { + return qfalse; + } + editPtr = (editFieldDef_t*)item->typeData; + if (PC_ParseStringMem((const char **) &item->cvar) && + !PC_ParseFloat(&editPtr->range)) + { + return qtrue; + } + + return qfalse; +} + /* =============== ItemParse_cvarStrList @@ -4932,7 +4966,7 @@ void Item_ValidateTypeData(itemDef_t *item) item->typeData = UI_Alloc(sizeof(listBoxDef_t)); memset(item->typeData, 0, sizeof(listBoxDef_t)); } - else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_BIND || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_SLIDER_INTEGER || item->type == ITEM_TYPE_TEXT) + else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_BIND || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_SLIDER_INTEGER || item->type == ITEM_TYPE_TEXT || item->type == ITEM_TYPE_SLIDER_ROTATE ) { item->typeData = UI_Alloc(sizeof(editFieldDef_t)); memset(item->typeData, 0, sizeof(editFieldDef_t)); @@ -5052,6 +5086,7 @@ keywordHash_t itemParseKeywords[] = { {"columns", ItemParse_columns, }, {"cvar", ItemParse_cvar, }, {"cvarFloat", ItemParse_cvarFloat, }, + {"cvarRotateScale", ItemParse_cvarRotateScale, }, {"cvarFloatList", ItemParse_cvarFloatList, }, {"cvarSubString", ItemParse_cvarsubstring }, {"cvarStrList", ItemParse_cvarStrList, }, @@ -6969,6 +7004,12 @@ void Item_ListBox_Paint(itemDef_t *item) { text = DC->feederItemText(item->special, i, 0, &optionalImage); + if (text && text[0]=='@') + { + const char* stringText = SE_GetString(&text[1]); + if (stringText && stringText[0]) + text = stringText; + } if (optionalImage >= 0) { //DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage); @@ -7548,7 +7589,11 @@ void Item_Model_Paint(itemDef_t *item) memset( &ent, 0, sizeof(ent) ); // use item storage to track - float curYaw = modelPtr->angle; + float curYaw = modelPtr->angle; + if ( item->cvar ) + { + curYaw = DC->getCVarValue(item->cvar); + } if (modelPtr->rotationSpeed) { curYaw += (float)refdef.time/modelPtr->rotationSpeed; @@ -8629,6 +8674,9 @@ static qboolean Item_Paint(itemDef_t *item, qboolean bDraw) case ITEM_TYPE_SLIDER_INTEGER: Item_Slider_Paint(item); break; + case ITEM_TYPE_SLIDER_ROTATE: + //Don't bother drawing anything at all for now! + break; default: break; } @@ -10941,6 +10989,55 @@ static void Scroll_Slider_ThumbFunc(void *p) value += editDef->minVal; DC->setCVar(si->item->cvar, va("%f", value)); } + +/* + ================= + Scroll_Rotate + ================= + */ +static void Scroll_Rotate(void *p) +{ + //This maps a scroll to a rotation. That rotation is then added to the current cvar value. + //It reads off editDef->range to give the correct angle range for the item area. + float start, size, cursorpos, cursorpos_old; + int intValue; + float angleDiff; + scrollInfo_t *si = (scrollInfo_t*)p; + editFieldDef_t *editDef = (struct editFieldDef_s *) si->item->typeData; + + qboolean useYAxis = (qboolean)( si->item->flags&ITF_ISANYSABER && !(si->item->flags&ITF_ISCHARACTER) ); + + if ( useYAxis ) + { + start = si->item->window.rect.y; + size = si->item->window.rect.h; + + cursorpos = DC->cursory; + cursorpos_old = si->yStart; + } + else + { + start = si->item->window.rect.x; + size = si->item->window.rect.w; + + cursorpos = DC->cursorx; + cursorpos_old = si->xStart; + } + + if (cursorpos < start) + { + cursorpos = start; + } + else if (cursorpos > start + size) + { + cursorpos = start + size; + } + //moving across the whole model area should allow for 720 degree rotation + angleDiff = (editDef->range)*(cursorpos - cursorpos_old)/size; + intValue = (int)(si->adjustValue + angleDiff) % 360; + DC->setCVar(si->item->cvar, va("%d", intValue)); +} + /* ================= Item_StartCapture @@ -11038,6 +11135,22 @@ void Item_StartCapture(itemDef_t *item, int key) } break; } + + case ITEM_TYPE_SLIDER_ROTATE: + { + if ( Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) ) + { + scrollInfo.scrollKey = key; + scrollInfo.item = item; + scrollInfo.xStart = DC->cursorx; + scrollInfo.yStart = DC->cursory; + scrollInfo.adjustValue = (int)DC->getCVarValue(item->cvar); + captureData = &scrollInfo; + captureFunc = &Scroll_Rotate; + itemCapture = item; + } + break; + } } } @@ -11449,6 +11562,10 @@ qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) case ITEM_TYPE_SLIDER_INTEGER: return Item_Slider_Integer_HandleKey(item, key, down); break; + case ITEM_TYPE_SLIDER_ROTATE: + //don't bother with this! + return qfalse; + break; //JLF MPMOVED case ITEM_TYPE_TEXT: return Item_Text_HandleKey(item, key); @@ -11742,7 +11859,7 @@ void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) should just process the action and not support the accept functionality. */ //JLFACCEPT - else if ( item->type == ITEM_TYPE_MULTI || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_SLIDER_INTEGER ) + else if ( item->type == ITEM_TYPE_MULTI || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_SLIDER_INTEGER || item->type == ITEM_TYPE_SLIDER_ROTATE ) { if (Item_HandleAccept(item)) diff --git a/codeJK2/game/bg_public.h b/codeJK2/game/bg_public.h index 55b29c48ba..d31ac4b41a 100644 --- a/codeJK2/game/bg_public.h +++ b/codeJK2/game/bg_public.h @@ -438,7 +438,7 @@ typedef enum { EV_DEBUG_LINE, - + EV_NUM_ENTITY_EVENTS } entity_event_t; class animation_t diff --git a/codeJK2/game/g_main.cpp b/codeJK2/game/g_main.cpp index d3288949ac..bc723828a9 100644 --- a/codeJK2/game/g_main.cpp +++ b/codeJK2/game/g_main.cpp @@ -638,7 +638,7 @@ void G_InitCvars( void ) { com_buildScript = gi.cvar ("com_buildscript", "0", 0); g_saberAutoBlocking = gi.cvar( "g_saberAutoBlocking", "1", CVAR_ARCHIVE|CVAR_CHEAT );//must press +block button to do any blocking - g_saberRealisticCombat = gi.cvar( "g_saberRealisticCombat", "0", CVAR_ARCHIVE|CVAR_CHEAT );//makes collision more precise, increases damage + g_saberRealisticCombat = gi.cvar( "g_saberRealisticCombat", "0", CVAR_ARCHIVE );//makes collision more precise, increases damage g_saberMoveSpeed = gi.cvar( "g_saberMoveSpeed", "1", CVAR_ARCHIVE|CVAR_CHEAT );//how fast you run while attacking with a saber g_saberAnimSpeed = gi.cvar( "g_saberAnimSpeed", "1", CVAR_ARCHIVE|CVAR_CHEAT );//how fast saber animations run g_saberAutoAim = gi.cvar( "g_saberAutoAim", "1", CVAR_ARCHIVE|CVAR_CHEAT );//auto-aims at enemies when not moving or when just running forward diff --git a/codeJK2/game/wp_saber.cpp b/codeJK2/game/wp_saber.cpp index 40b76cd42a..22d1c83fbc 100644 --- a/codeJK2/game/wp_saber.cpp +++ b/codeJK2/game/wp_saber.cpp @@ -1385,9 +1385,9 @@ qboolean WP_SaberDamageEffects( trace_t *tr, const vec3_t start, float length, f G_PlayEffect( hitEffect, coll.mCollisionPosition, coll.mCollisionNormal ); //Get the hit location based on surface name - if ( (hitLoc[hitEntNum[numHitEnts]] == HL_NONE && trHitLoc == HL_NONE) - || (hitDismemberLoc[hitEntNum[numHitEnts]] == HL_NONE && trDismemberLoc == HL_NONE) - || (!hitDismember[hitEntNum[numHitEnts]] && !trDismember) ) + if ( (hitLoc[numHitEnts] == HL_NONE && trHitLoc == HL_NONE) + || (hitDismemberLoc[numHitEnts] == HL_NONE && trDismemberLoc == HL_NONE) + || (!hitDismember[numHitEnts] && !trDismember) ) {//no hit loc set for this ent this damage cycle yet //FIXME: find closest impact surf *first* (per ent), then call G_GetHitLocFromSurfName? trDismember = G_GetHitLocFromSurfName( &g_entities[coll.mEntityNum], gi.G2API_GetSurfaceName( &g_entities[coll.mEntityNum].ghoul2[coll.mModelIndex], coll.mSurfaceIndex ), &trHitLoc, coll.mCollisionPosition, dmgDir, bladeDir, MOD_SABER ); diff --git a/codemp/CMakeLists.txt b/codemp/CMakeLists.txt index c0e7a48740..a55ddf7893 100644 --- a/codemp/CMakeLists.txt +++ b/codemp/CMakeLists.txt @@ -396,9 +396,9 @@ if(BuildMPEngine) ${OpenJKLibDir}/SDL2/include ) else() - find_package(SDL2 REQUIRED) - set(MPEngineIncludeDirectories ${MPEngineIncludeDirectories} ${SDL2_INCLUDE_DIR}) - set(MPEngineLibraries ${MPEngineLibraries} ${SDL2_LIBRARY}) + find_package(SDL2 REQUIRED CONFIG) + set(MPEngineIncludeDirectories ${MPEngineIncludeDirectories} ${SDL2_INCLUDE_DIRS}) + set(MPEngineLibraries ${MPEngineLibraries} ${SDL2_LIBRARIES}) endif() # EAX is Windows-Only (right?) diff --git a/codemp/cgame/cg_draw.c b/codemp/cgame/cg_draw.c index 62078d2d97..8b793c1593 100644 --- a/codemp/cgame/cg_draw.c +++ b/codemp/cgame/cg_draw.c @@ -5225,7 +5225,7 @@ static void CG_DrawCrosshair( vec3_t worldPoint, int chEntValid ) { if ( !hShader ) { - hShader = cgs.media.crosshairShader[ cg_drawCrosshair.integer % NUM_CROSSHAIRS ]; + hShader = cgs.media.crosshairShader[Com_Clampi( 1, NUM_CROSSHAIRS, cg_drawCrosshair.integer ) - 1]; } chX = x + cg.refdef.x + 0.5 * (640 - w); diff --git a/codemp/cgame/cg_ents.c b/codemp/cgame/cg_ents.c index 5c790f5f56..531dd40038 100644 --- a/codemp/cgame/cg_ents.c +++ b/codemp/cgame/cg_ents.c @@ -658,7 +658,7 @@ void ScaleModelAxis(refEntity_t *ent) Ghoul2 Insert End */ -char *forceHolocronModels[] = { +char *forceHolocronModels[NUM_FORCE_POWERS] = { "models/map_objects/mp/lt_heal.md3", //FP_HEAL, "models/map_objects/mp/force_jump.md3", //FP_LEVITATION, "models/map_objects/mp/force_speed.md3", //FP_SPEED, @@ -2472,7 +2472,7 @@ static void CG_Missile( centity_t *cent ) { } else { - trap->G2API_InitGhoul2Model(¢->ghoul2, "models/weapons2/saber/saber_w.glm", 0, 0, 0, 0, 0); + trap->G2API_InitGhoul2Model(¢->ghoul2, DEFAULT_SABER_MODEL, 0, 0, 0, 0, 0); } return; } diff --git a/codemp/cgame/cg_main.c b/codemp/cgame/cg_main.c index d92b35b21a..91d0204ae5 100644 --- a/codemp/cgame/cg_main.c +++ b/codemp/cgame/cg_main.c @@ -26,6 +26,10 @@ along with this program; if not, see . #include "cg_local.h" #include "ui/ui_shared.h" + +NORETURN_PTR void (*Com_Error)( int level, const char *error, ... ); +void (*Com_Printf)( const char *msg, ... ); + // display context for new ui stuff displayContextDef_t cgDC; diff --git a/codemp/cgame/cg_players.c b/codemp/cgame/cg_players.c index 6eac153513..d9262deb87 100644 --- a/codemp/cgame/cg_players.c +++ b/codemp/cgame/cg_players.c @@ -10118,7 +10118,7 @@ void CG_Player( centity_t *cent ) { } else { - trap->G2API_InitGhoul2Model(&saberEnt->ghoul2, "models/weapons2/saber/saber_w.glm", 0, 0, 0, 0, 0); + trap->G2API_InitGhoul2Model(&saberEnt->ghoul2, DEFAULT_SABER_MODEL, 0, 0, 0, 0, 0); } //trap->G2API_DuplicateGhoul2Instance(cent->ghoul2, &saberEnt->ghoul2); diff --git a/codemp/cgame/cg_spawn.c b/codemp/cgame/cg_spawn.c index a3c8ae7fd9..c10886394a 100644 --- a/codemp/cgame/cg_spawn.c +++ b/codemp/cgame/cg_spawn.c @@ -298,7 +298,7 @@ void CG_ParseEntityFromSpawnVars( void ) { int i; char *classname; char *p, *value, *gametypeName; - static char *gametypeNames [] = { "ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty" }; + static char *gametypeNames[GT_MAX_GAME_TYPE] = { "ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty" }; // check for "notsingle" flag if( cgs.gametype == GT_SINGLE_PLAYER ) { diff --git a/codemp/cgame/cg_weaponinit.c b/codemp/cgame/cg_weaponinit.c index 9e1d69d94c..88259344f3 100644 --- a/codemp/cgame/cg_weaponinit.c +++ b/codemp/cgame/cg_weaponinit.c @@ -40,12 +40,12 @@ void CG_RegisterWeapon( int weaponNum) { vec3_t mins, maxs; int i; - weaponInfo = &cg_weapons[weaponNum]; - - if ( weaponNum == 0 ) { + if ( weaponNum <= WP_NONE || weaponNum >= WP_NUM_WEAPONS ) { return; } + weaponInfo = &cg_weapons[weaponNum]; + if ( weaponInfo->registered ) { return; } @@ -167,7 +167,7 @@ void CG_RegisterWeapon( int weaponNum) { case WP_SABER: MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f ); weaponInfo->firingSound = trap->S_RegisterSound( "sound/weapons/saber/saberhum1.wav" ); - weaponInfo->missileModel = trap->R_RegisterModel( "models/weapons2/saber/saber_w.glm" ); + weaponInfo->missileModel = trap->R_RegisterModel( DEFAULT_SABER_MODEL ); break; case WP_CONCUSSION: diff --git a/codemp/client/snd_mix.cpp b/codemp/client/snd_mix.cpp index 52dab4422f..e418b4802b 100644 --- a/codemp/client/snd_mix.cpp +++ b/codemp/client/snd_mix.cpp @@ -443,8 +443,20 @@ void S_PaintChannels( int endtime ) { } count = end - ltime; - if ( sampleOffset + count > sc->iSoundLengthInSamples ) { - count = sc->iSoundLengthInSamples - sampleOffset; + if ( ch->doppler && ch->dopplerScale > 1 ) { + if ( sampleOffset + (count * ch->dopplerScale) > sc->iSoundLengthInSamples ) { + count = (sc->iSoundLengthInSamples - sampleOffset) / ch->dopplerScale; + + // avoid infinite loop once length of remaining pSoundData (numerator) + // is smaller than dopplerScale (denominator), resulting in 0. + if ( count == 0 ) { + break; + } + } + } else { + if ( sampleOffset + count > sc->iSoundLengthInSamples ) { + count = sc->iSoundLengthInSamples - sampleOffset; + } } if ( count > 0 ) { diff --git a/codemp/game/ai_main.c b/codemp/game/ai_main.c index f068349586..8e6a96e586 100644 --- a/codemp/game/ai_main.c +++ b/codemp/game/ai_main.c @@ -625,7 +625,7 @@ void BotInputToUserCommand(bot_input_t *bi, usercmd_t *ucmd, int delta_angles[3] //set the view independent movement f = DotProduct(forward, bi->dir); r = DotProduct(right, bi->dir); - u = abs(forward[2]) * bi->dir[2]; + u = fabs(forward[2]) * bi->dir[2]; m = fabs(f); if (fabs(r) > m) { diff --git a/codemp/game/bg_misc.c b/codemp/game/bg_misc.c index 10668df088..b7fc7ba955 100644 --- a/codemp/game/bg_misc.c +++ b/codemp/game/bg_misc.c @@ -1101,7 +1101,7 @@ Don't place this { "weapon_saber", "sound/weapons/w_pkup.wav", - { "models/weapons2/saber/saber_w.glm", + { DEFAULT_SABER_MODEL, 0, 0, 0}, /* view */ "models/weapons2/saber/saber_w.md3", /* icon */ "gfx/hud/w_icon_lightsaber", @@ -2316,7 +2316,7 @@ void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t resu } } -const char *eventnames[] = { +const char *eventnames[EV_NUM_ENTITY_EVENTS] = { "EV_NONE", "EV_CLIENTJOIN", diff --git a/codemp/game/bg_public.h b/codemp/game/bg_public.h index 2786ed6b16..731c56f6e8 100644 --- a/codemp/game/bg_public.h +++ b/codemp/game/bg_public.h @@ -1029,6 +1029,7 @@ typedef enum { EV_SIEGESPEC, + EV_NUM_ENTITY_EVENTS } entity_event_t; // There is a maximum of 256 events (8 bits transmission, 2 high bits for uniqueness) diff --git a/codemp/game/g_client.c b/codemp/game/g_client.c index 46fcdc9b51..0558003fa0 100644 --- a/codemp/game/g_client.c +++ b/codemp/game/g_client.c @@ -376,7 +376,7 @@ void JMSaberThink(gentity_t *ent) VectorCopy(ent->enemy->s.pos.trBase, ent->s.pos.trBase); VectorCopy(ent->enemy->s.pos.trBase, ent->s.origin); VectorCopy(ent->enemy->s.pos.trBase, ent->r.currentOrigin); - ent->s.modelindex = G_ModelIndex("models/weapons2/saber/saber_w.glm"); + ent->s.modelindex = G_ModelIndex( DEFAULT_SABER_MODEL ); ent->s.eFlags &= ~(EF_NODRAW); ent->s.modelGhoul2 = 1; ent->s.eType = ET_MISSILE; @@ -509,7 +509,7 @@ void SP_info_jedimaster_start(gentity_t *ent) ent->flags = FL_BOUNCE_HALF; - ent->s.modelindex = G_ModelIndex("models/weapons2/saber/saber_w.glm"); + ent->s.modelindex = G_ModelIndex( DEFAULT_SABER_MODEL ); ent->s.modelGhoul2 = 1; ent->s.g2radius = 20; //ent->s.eType = ET_GENERAL; @@ -1589,7 +1589,7 @@ void SetupGameGhoul2Model(gentity_t *ent, char *modelname, char *skinName) { int defSkin; - Com_sprintf( afilename, sizeof( afilename ), "models/players/kyle/model.glm" ); + Com_sprintf( afilename, sizeof( afilename ), "models/players/" DEFAULT_MODEL "/model.glm" ); handle = trap->G2API_InitGhoul2Model(&precachedKyle, afilename, 0, 0, -20, 0, 0); if (handle<0) @@ -1597,7 +1597,7 @@ void SetupGameGhoul2Model(gentity_t *ent, char *modelname, char *skinName) return; } - defSkin = trap->R_RegisterSkin("models/players/kyle/model_default.skin"); + defSkin = trap->R_RegisterSkin("models/players/" DEFAULT_MODEL "/model_default.skin"); trap->G2API_SetSkin(precachedKyle, 0, defSkin, defSkin); } @@ -1908,7 +1908,7 @@ void SetupGameGhoul2Model(gentity_t *ent, char *modelname, char *skinName) if (!g2SaberInstance) { - trap->G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0); + trap->G2API_InitGhoul2Model(&g2SaberInstance, DEFAULT_SABER_MODEL, 0, 0, -20, 0, 0); if (g2SaberInstance) { diff --git a/codemp/game/g_cmds.c b/codemp/game/g_cmds.c index c2a9feb6c5..a8125ab990 100644 --- a/codemp/game/g_cmds.c +++ b/codemp/game/g_cmds.c @@ -1853,7 +1853,7 @@ void Cmd_Where_f( gentity_t *ent ) { //trap->SendServerCommand( ent-g_entities, va("print \"%s\n\"", vtos( ent->s.origin ) ) ); } -static const char *gameNames[] = { +static const char *gameNames[GT_MAX_GAME_TYPE] = { "Free For All", "Holocron FFA", "Jedi Master", diff --git a/codemp/game/g_main.c b/codemp/game/g_main.c index 545cb62b1f..6b92258526 100644 --- a/codemp/game/g_main.c +++ b/codemp/game/g_main.c @@ -29,6 +29,9 @@ along with this program; if not, see . #include "bg_saga.h" #include "b_local.h" +NORETURN_PTR void (*Com_Error)( int level, const char *error, ... ); +void (*Com_Printf)( const char *msg, ... ); + level_locals_t level; int eventClearTime = 0; @@ -167,7 +170,7 @@ G_InitGame */ extern void RemoveAllWP(void); extern void BG_ClearVehicleParseParms(void); -gentity_t *SelectRandomDeathmatchSpawnPoint( void ); +gentity_t *SelectRandomDeathmatchSpawnPoint( qboolean isbot ); void SP_info_jedimaster_start( gentity_t *ent ); void G_InitGame( int levelTime, int randomSeed, int restart ) { int i; @@ -411,7 +414,7 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) { if ( i == level.num_entities ) { // no JM saber found. drop one at one of the player spawnpoints - gentity_t *spawnpoint = SelectRandomDeathmatchSpawnPoint(); + gentity_t *spawnpoint = SelectRandomDeathmatchSpawnPoint( qfalse ); if( !spawnpoint ) { trap->Error( ERR_DROP, "Couldn't find an FFA spawnpoint to drop the jedimaster saber at!\n" ); diff --git a/codemp/game/g_spawn.c b/codemp/game/g_spawn.c index 52218e2cf8..44f991b073 100644 --- a/codemp/game/g_spawn.c +++ b/codemp/game/g_spawn.c @@ -890,7 +890,7 @@ void G_SpawnGEntityFromSpawnVars( qboolean inSubBSP ) { int i; gentity_t *ent; char *s, *value, *gametypeName; - static char *gametypeNames[] = {"ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty"}; + static char *gametypeNames[GT_MAX_GAME_TYPE] = {"ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty"}; // get the next free entity ent = G_Spawn(); @@ -1418,18 +1418,18 @@ void SP_worldspawn( void ) { int defSkin; - trap->G2API_InitGhoul2Model(&precachedKyle, "models/players/kyle/model.glm", 0, 0, -20, 0, 0); + trap->G2API_InitGhoul2Model(&precachedKyle, "models/players/" DEFAULT_MODEL "/model.glm", 0, 0, -20, 0, 0); if (precachedKyle) { - defSkin = trap->R_RegisterSkin("models/players/kyle/model_default.skin"); + defSkin = trap->R_RegisterSkin("models/players/" DEFAULT_MODEL "/model_default.skin"); trap->G2API_SetSkin(precachedKyle, 0, defSkin, defSkin); } } if (!g2SaberInstance) { - trap->G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0); + trap->G2API_InitGhoul2Model(&g2SaberInstance, DEFAULT_SABER_MODEL, 0, 0, -20, 0, 0); if (g2SaberInstance) { diff --git a/codemp/game/w_saber.c b/codemp/game/w_saber.c index bb0b86e296..5561b3ed8d 100644 --- a/codemp/game/w_saber.c +++ b/codemp/game/w_saber.c @@ -6605,7 +6605,7 @@ void WP_SaberAddG2Model( gentity_t *saberent, const char *saberModel, qhandle_t } else { - saberent->s.modelindex = G_ModelIndex( "models/weapons2/saber/saber_w.glm" ); + saberent->s.modelindex = G_ModelIndex( DEFAULT_SABER_MODEL ); } //FIXME: use customSkin? trap->G2API_InitGhoul2Model( &saberent->ghoul2, saberModel, saberent->s.modelindex, saberSkin, 0, 0, 0 ); diff --git a/codemp/qcommon/q_shared.h b/codemp/qcommon/q_shared.h index ff86f3a27c..cea7b5c833 100644 --- a/codemp/qcommon/q_shared.h +++ b/codemp/qcommon/q_shared.h @@ -687,8 +687,8 @@ qboolean Info_NextPair( const char **s, char *key, char *value ); // this is only here so the functions in q_shared.c and bg_*.c can link #if defined( _GAME ) || defined( _CGAME ) || defined( UI_BUILD ) - NORETURN_PTR void (*Com_Error)( int level, const char *error, ... ); - void (*Com_Printf)( const char *msg, ... ); + extern NORETURN_PTR void (*Com_Error)( int level, const char *error, ... ); + extern void (*Com_Printf)( const char *msg, ... ); #else void NORETURN QDECL Com_Error( int level, const char *error, ... ); void QDECL Com_Printf( const char *msg, ... ); diff --git a/codemp/rd-common/mdx_format.h b/codemp/rd-common/mdx_format.h index c097a226f8..a51a526d4b 100644 --- a/codemp/rd-common/mdx_format.h +++ b/codemp/rd-common/mdx_format.h @@ -417,10 +417,11 @@ typedef struct mdxaHeader_s { // // (iFrameNum * mdxaHeader_t->numBones * 3) + (iBoneNum * 3) // - // then read the int at that location and AND it with 0x00FFFFFF. I use the struct below simply for easy searches + // Then convert the three byte int at that location. + // This struct is used for easy searches. typedef struct { - int iIndex; // this struct for pointing purposes, need to and with 0x00FFFFFF to be meaningful + byte iIndex[3]; } mdxaIndex_t; // // (note that there's then an alignement-pad here to get the next struct back onto 32-bit alignement) diff --git a/codemp/rd-dedicated/tr_ghoul2.cpp b/codemp/rd-dedicated/tr_ghoul2.cpp index 4190b9dc01..0797f76eed 100644 --- a/codemp/rd-dedicated/tr_ghoul2.cpp +++ b/codemp/rd-dedicated/tr_ghoul2.cpp @@ -915,13 +915,12 @@ void Multiply_3x4Matrix(mdxaBone_t *out, mdxaBone_t *in2, mdxaBone_t *in) } -static int G2_GetBonePoolIndex( const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) +static int G2_GetBonePoolIndex(const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) { - const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); + const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); + mdxaIndex_t *pIndex = (mdxaIndex_t *)((byte*)pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); - mdxaIndex_t *pIndex = (mdxaIndex_t *) ((byte*) pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); - - return pIndex->iIndex & 0x00FFFFFF; // this will cause problems for big-endian machines... ;-) + return (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); } diff --git a/codemp/rd-vanilla/glext.h b/codemp/rd-vanilla/glext.h index bedd07067e..09d03652d8 100644 --- a/codemp/rd-vanilla/glext.h +++ b/codemp/rd-vanilla/glext.h @@ -1,5 +1,5 @@ -#ifndef __glext_h_ -#define __glext_h_ 1 +#ifndef __gl_glext_h_ +#define __gl_glext_h_ 1 #ifdef __cplusplus extern "C" { diff --git a/codemp/rd-vanilla/qgl.h b/codemp/rd-vanilla/qgl.h index 8d96e635f5..2127128feb 100644 --- a/codemp/rd-vanilla/qgl.h +++ b/codemp/rd-vanilla/qgl.h @@ -306,6 +306,9 @@ along with this program; if not, see . #define qglStencilFunc glStencilFunc #define qglStencilMask glStencilMask #define qglStencilOp glStencilOp +#if defined(__APPLE__) +#define qglStencilOpSeparate glStencilOpSeparate +#endif #define qglTexCoord1d glTexCoord1d #define qglTexCoord1dv glTexCoord1dv #define qglTexCoord1f glTexCoord1f @@ -392,6 +395,10 @@ along with this program; if not, see . #define qglVertexPointer glVertexPointer #define qglViewport glViewport +#if !defined(__APPLE__) +extern PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate; +#endif + extern PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB; extern PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB; extern PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB; diff --git a/codemp/rd-vanilla/tr_ghoul2.cpp b/codemp/rd-vanilla/tr_ghoul2.cpp index 78adfcc44d..f4ca58b8d6 100644 --- a/codemp/rd-vanilla/tr_ghoul2.cpp +++ b/codemp/rd-vanilla/tr_ghoul2.cpp @@ -1067,19 +1067,12 @@ void Multiply_3x4Matrix(mdxaBone_t *out, mdxaBone_t *in2, mdxaBone_t *in) } -static int G2_GetBonePoolIndex( const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) +static int G2_GetBonePoolIndex(const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone) { - const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); + const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3); + mdxaIndex_t *pIndex = (mdxaIndex_t *)((byte*)pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); - mdxaIndex_t *pIndex = (mdxaIndex_t *) ((byte*) pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex); - -#ifdef Q3_BIG_ENDIAN - int tmp = pIndex->iIndex & 0xFFFFFF00; - LL(tmp); - return tmp; -#else - return pIndex->iIndex & 0x00FFFFFF; -#endif + return (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); } @@ -4657,6 +4650,7 @@ qboolean R_LoadMDXA( model_t *mod, void *buffer, const char *mod_name, qboolean mdxaCompQuatBone_t *pCompBonePool; unsigned short *pwIn; mdxaIndex_t *pIndex; + int tmp; #endif pinmodel = (mdxaHeader_t *)buffer; @@ -4875,24 +4869,24 @@ qboolean R_LoadMDXA( model_t *mod, void *buffer, const char *mod_name, qboolean } } - // find the largest index, since the actual number of compressed bone pools is not stored anywhere - for ( i = 0 ; i < mdxa->numFrames ; i++ ) - { - for ( j = 0 ; j < mdxa->numBones ; j++ ) - { - k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex - pIndex = (mdxaIndex_t *) ((byte*) mdxa + mdxa->ofsFrames + k); + // Determine the amount of compressed bones. - // 3 byte ints, yeah... - int tmp = pIndex->iIndex & 0xFFFFFF00; - LL(tmp); + // Find the largest index by iterating through all frames. + // It is not guaranteed that the compressed bone pool resides + // at the end of the file. + for(i = 0; i < mdxa->numFrames; i++){ + for(j = 0; j < mdxa->numBones; j++){ + k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex + pIndex = (mdxaIndex_t *) ((byte *)mdxa + mdxa->ofsFrames + k); + tmp = (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); - if (maxBoneIndex < tmp) + if(maxBoneIndex < tmp){ maxBoneIndex = tmp; + } } } - // swap the compressed bones + // Swap the compressed bones. pCompBonePool = (mdxaCompQuatBone_t *) ((byte *)mdxa + mdxa->ofsCompBonePool); for ( i = 0 ; i <= maxBoneIndex ; i++ ) { diff --git a/codemp/rd-vanilla/tr_init.cpp b/codemp/rd-vanilla/tr_init.cpp index 8dde47c327..2fb27a4401 100644 --- a/codemp/rd-vanilla/tr_init.cpp +++ b/codemp/rd-vanilla/tr_init.cpp @@ -216,6 +216,10 @@ cvar_t *se_language; cvar_t *r_aviMotionJpegQuality; cvar_t *r_screenshotJpegQuality; +#if !defined(__APPLE__) +PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate; +#endif + PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB; PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB; PFNGLMULTITEXCOORD2FARBPROC qglMultiTexCoord2fARB; @@ -725,6 +729,16 @@ static void GLimp_InitExtensions( void ) g_bDynamicGlowSupported = false; ri.Cvar_Set( "r_DynamicGlow","0" ); } + +#if !defined(__APPLE__) + qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri.GL_GetProcAddress("glStencilOpSeparate"); + if ( qglStencilOpSeparate ) + { + glConfigExt.doStencilShadowsInOneDrawcall = qtrue; + } +#else + glConfigExt.doStencilShadowsInOneDrawcall = qtrue; +#endif } // Truncates the GL extensions string by only allowing up to 'maxExtensions' extensions in the string. diff --git a/codemp/rd-vanilla/tr_local.h b/codemp/rd-vanilla/tr_local.h index 6893e7cc8a..97de6df75f 100644 --- a/codemp/rd-vanilla/tr_local.h +++ b/codemp/rd-vanilla/tr_local.h @@ -1099,6 +1099,7 @@ struct glconfigExt_t glconfig_t *glConfig; qboolean doGammaCorrectionWithShaders; + qboolean doStencilShadowsInOneDrawcall; const char *originalExtensionString; }; diff --git a/codemp/rd-vanilla/tr_model.cpp b/codemp/rd-vanilla/tr_model.cpp index 171be4213e..92c30ce4bd 100644 --- a/codemp/rd-vanilla/tr_model.cpp +++ b/codemp/rd-vanilla/tr_model.cpp @@ -682,6 +682,7 @@ qboolean ServerLoadMDXA( model_t *mod, void *buffer, const char *mod_name, qbool mdxaCompQuatBone_t *pCompBonePool; unsigned short *pwIn; mdxaIndex_t *pIndex; + int tmp; #endif pinmodel = (mdxaHeader_t *)buffer; @@ -767,24 +768,24 @@ qboolean ServerLoadMDXA( model_t *mod, void *buffer, const char *mod_name, qbool } } - // find the largest index, since the actual number of compressed bone pools is not stored anywhere - for ( i = 0 ; i < mdxa->numFrames ; i++ ) - { - for ( j = 0 ; j < mdxa->numBones ; j++ ) - { - k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex - pIndex = (mdxaIndex_t *) ((byte*) mdxa + mdxa->ofsFrames + k); + // Determine the amount of compressed bones. - // 3 byte ints, yeah... - int tmp = pIndex->iIndex & 0xFFFFFF00; - LL(tmp); + // Find the largest index by iterating through all frames. + // It is not guaranteed that the compressed bone pool resides + // at the end of the file. + for(i = 0; i < mdxa->numFrames; i++){ + for(j = 0; j < mdxa->numBones; j++){ + k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex + pIndex = (mdxaIndex_t *) ((byte *)mdxa + mdxa->ofsFrames + k); + tmp = (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]); - if (maxBoneIndex < tmp) + if(maxBoneIndex < tmp){ maxBoneIndex = tmp; + } } } - // swap the compressed bones + // Swap the compressed bones. pCompBonePool = (mdxaCompQuatBone_t *) ((byte *)mdxa + mdxa->ofsCompBonePool); for ( i = 0 ; i <= maxBoneIndex ; i++ ) { diff --git a/codemp/rd-vanilla/tr_shadows.cpp b/codemp/rd-vanilla/tr_shadows.cpp index 473e2538fc..d5480fc62c 100644 --- a/codemp/rd-vanilla/tr_shadows.cpp +++ b/codemp/rd-vanilla/tr_shadows.cpp @@ -350,28 +350,24 @@ void RB_DoShadowTessEnd( vec3_t lightPos ) qglDepthFunc(GL_LESS); //now using the Carmack Reverse -rww - if ( backEnd.viewParms.isMirror ) { - //qglCullFace( GL_BACK ); - GL_Cull(CT_BACK_SIDED); - qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); - - R_RenderShadowEdges(); - - //qglCullFace( GL_FRONT ); - GL_Cull(CT_FRONT_SIDED); - qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); + if ( glConfigExt.doStencilShadowsInOneDrawcall ) + { + GL_Cull(CT_TWO_SIDED); + qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); + qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); R_RenderShadowEdges(); - } else { - //qglCullFace( GL_FRONT ); + qglDisable(GL_STENCIL_TEST); + } + else + { GL_Cull(CT_FRONT_SIDED); - qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); + qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP); R_RenderShadowEdges(); - //qglCullFace( GL_BACK ); GL_Cull(CT_BACK_SIDED); - qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); + qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP); R_RenderShadowEdges(); } @@ -404,7 +400,7 @@ void RB_DoShadowTessEnd( vec3_t lightPos ) // reenable writing to the color buffer qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); - + #ifdef _DEBUG_STENCIL_SHADOWS qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif diff --git a/codemp/server/sv_client.cpp b/codemp/server/sv_client.cpp index bb8bf8d8fb..4f4016f671 100644 --- a/codemp/server/sv_client.cpp +++ b/codemp/server/sv_client.cpp @@ -1562,7 +1562,8 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { } // if we can tell that the client has dropped the last // gamestate we sent them, resend it - if ( cl->messageAcknowledge > cl->gamestateMessageNum ) { + // Fix for https://bugzilla.icculus.org/show_bug.cgi?id=6324 + if ( cl->state != CS_ACTIVE && cl->messageAcknowledge > cl->gamestateMessageNum ) { Com_DPrintf( "%s : dropped gamestate, resending\n", cl->name ); SV_SendClientGameState( cl ); } diff --git a/codemp/ui/ui_main.c b/codemp/ui/ui_main.c index 94f67a79f8..8ca16b705e 100644 --- a/codemp/ui/ui_main.c +++ b/codemp/ui/ui_main.c @@ -44,6 +44,9 @@ USER INTERFACE MAIN #include "game/bg_saga.h" #include "ui_shared.h" +NORETURN_PTR void (*Com_Error)( int level, const char *error, ... ); +void (*Com_Printf)( const char *msg, ... ); + extern void UI_SaberAttachToChar( itemDef_t *item ); const char *forcepowerDesc[NUM_FORCE_POWERS] = @@ -500,7 +503,7 @@ static const char *skillLevels[] = { }; static const size_t numSkillLevels = ARRAY_LEN( skillLevels ); -static const char *gameTypes[] = { +static const char *gameTypes[GT_MAX_GAME_TYPE] = { "FFA", "Holocron", "JediMaster", diff --git a/codemp/ui/ui_shared.c b/codemp/ui/ui_shared.c index 34a8b7d1f1..f2ed6d56f9 100644 --- a/codemp/ui/ui_shared.c +++ b/codemp/ui/ui_shared.c @@ -1550,10 +1550,10 @@ void Menu_TransitionItemByName(menuDef_t *menu, const char *p, const rectDef_t * item->window.offsetTime = time; memcpy(&item->window.rectClient, rectFrom, sizeof(rectDef_t)); memcpy(&item->window.rectEffects, rectTo, sizeof(rectDef_t)); - item->window.rectEffects2.x = abs(rectTo->x - rectFrom->x) / amt; - item->window.rectEffects2.y = abs(rectTo->y - rectFrom->y) / amt; - item->window.rectEffects2.w = abs(rectTo->w - rectFrom->w) / amt; - item->window.rectEffects2.h = abs(rectTo->h - rectFrom->h) / amt; + item->window.rectEffects2.x = fabs(rectTo->x - rectFrom->x) / amt; + item->window.rectEffects2.y = fabs(rectTo->y - rectFrom->y) / amt; + item->window.rectEffects2.w = fabs(rectTo->w - rectFrom->w) / amt; + item->window.rectEffects2.h = fabs(rectTo->h - rectFrom->h) / amt; Item_UpdatePosition(item); } @@ -1601,17 +1601,17 @@ void Menu_Transition3ItemByName(menuDef_t *menu, const char *p, const float minx // VectorSet(modelptr->g2maxs2, maxx, maxy, maxz); - modelptr->g2maxsEffect[0] = abs(modelptr->g2maxs2[0] - modelptr->g2maxs[0]) / amt; - modelptr->g2maxsEffect[1] = abs(modelptr->g2maxs2[1] - modelptr->g2maxs[1]) / amt; - modelptr->g2maxsEffect[2] = abs(modelptr->g2maxs2[2] - modelptr->g2maxs[2]) / amt; + modelptr->g2maxsEffect[0] = fabs(modelptr->g2maxs2[0] - modelptr->g2maxs[0]) / amt; + modelptr->g2maxsEffect[1] = fabs(modelptr->g2maxs2[1] - modelptr->g2maxs[1]) / amt; + modelptr->g2maxsEffect[2] = fabs(modelptr->g2maxs2[2] - modelptr->g2maxs[2]) / amt; - modelptr->g2minsEffect[0] = abs(modelptr->g2mins2[0] - modelptr->g2mins[0]) / amt; - modelptr->g2minsEffect[1] = abs(modelptr->g2mins2[1] - modelptr->g2mins[1]) / amt; - modelptr->g2minsEffect[2] = abs(modelptr->g2mins2[2] - modelptr->g2mins[2]) / amt; + modelptr->g2minsEffect[0] = fabs(modelptr->g2mins2[0] - modelptr->g2mins[0]) / amt; + modelptr->g2minsEffect[1] = fabs(modelptr->g2mins2[1] - modelptr->g2mins[1]) / amt; + modelptr->g2minsEffect[2] = fabs(modelptr->g2mins2[2] - modelptr->g2mins[2]) / amt; - modelptr->fov_Effectx = abs(modelptr->fov_x2 - modelptr->fov_x) / amt; - modelptr->fov_Effecty = abs(modelptr->fov_y2 - modelptr->fov_y) / amt; + modelptr->fov_Effectx = fabs(modelptr->fov_x2 - modelptr->fov_x) / amt; + modelptr->fov_Effecty = fabs(modelptr->fov_y2 - modelptr->fov_y) / amt; } } } diff --git a/scripts/travis/build.sh b/scripts/travis/build.sh index 179887178c..f9c17f815f 100644 --- a/scripts/travis/build.sh +++ b/scripts/travis/build.sh @@ -15,13 +15,13 @@ case "${host}" in export CC=${host}-gcc export CXX=${host}-g++ set -- \ - -D CMAKE_TOOLCHAIN_FILE=$(pwd)/CMakeModules/Toolchains/${host}.cmake \ + -D CMAKE_TOOLCHAIN_FILE=$(pwd)/cmake/Toolchains/${host}.cmake \ "$@" ;; (i?86-linux-gnu) set -- \ - -D CMAKE_TOOLCHAIN_FILE=$(pwd)/CMakeModules/Toolchains/linux-i686.cmake \ + -D CMAKE_TOOLCHAIN_FILE=$(pwd)/cmake/Toolchains/linux-i686.cmake \ "$@" ;; diff --git a/scripts/travis/install.sh b/scripts/travis/install.sh index 9e2226e871..75a47b2f4d 100644 --- a/scripts/travis/install.sh +++ b/scripts/travis/install.sh @@ -4,7 +4,8 @@ set -e set -x host="$1" -shift 1 +flavour="$2" +shift 2 # macOS is special if [ "${TRAVIS_OS_NAME}" = "osx" ]; then diff --git a/shared/sdl/sdl_input.cpp b/shared/sdl/sdl_input.cpp index c310ee8958..2bf67c7a32 100644 --- a/shared/sdl/sdl_input.cpp +++ b/shared/sdl/sdl_input.cpp @@ -435,7 +435,7 @@ static void IN_ActivateMouse( void ) } // in_nograb makes no sense in fullscreen mode - if( !Cvar_VariableIntegerValue("r_fullscreen") ) + if( !cls.glconfig.isFullscreen ) { if( in_nograb->modified || !mouseActive ) { @@ -463,7 +463,7 @@ static void IN_DeactivateMouse( void ) // Always show the cursor when the mouse is disabled, // but not when fullscreen - if( !Cvar_VariableIntegerValue("r_fullscreen") ) + if( !cls.glconfig.isFullscreen ) SDL_ShowCursor( 1 ); if( !mouseAvailable ) @@ -615,6 +615,14 @@ void IN_Init( void *windowData ) SDL_StartTextInput( ); mouseAvailable = (qboolean)( in_mouse->value != 0 ); + if ( in_mouse->integer == 2 ) { + Com_DPrintf( "Not using raw mouse input\n" ); + SDL_SetHint( "SDL_MOUSE_RELATIVE_MODE_WARP", "1" ); + } + else { + Com_DPrintf( "Using raw mouse input\n" ); + SDL_SetHint( "SDL_MOUSE_RELATIVE_MODE_WARP", "0" ); + } IN_DeactivateMouse( ); int appState = SDL_GetWindowFlags( SDL_window );