Merge remote-tracking branch 'origin/master' into network-items,

fixed conflicts.
This commit is contained in:
hiker 2018-06-08 10:55:14 +10:00
commit b0da0f640a
259 changed files with 7953 additions and 3205 deletions

View File

@ -26,11 +26,26 @@ option(USE_SYSTEM_ENET "Use system ENET instead of the built-in version, when av
option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON) option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON)
CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON
"NOT SERVER_ONLY;NOT USE_GLES2;NOT APPLE" OFF) "NOT SERVER_ONLY;NOT APPLE" OFF)
if(APPLE)
list(APPEND CMAKE_PREFIX_PATH /usr/local/opt)
include_directories(/usr/local/opt/fribidi/include/)
include_directories(/usr/local/opt/openssl@1.1/include/)
include_directories(/usr/local/opt/openssl@1.1/include/openssl/)
include_directories(/usr/local/opt/freetype/include/freetype2/)
endif()
if((UNIX AND NOT APPLE) AND NOT SERVER_ONLY) if((UNIX AND NOT APPLE) AND NOT SERVER_ONLY)
option(ENABLE_WAYLAND_DEVICE "Enable Wayland device for linux build" ON) option(ENABLE_WAYLAND_DEVICE "Enable Wayland device for linux build" ON)
option(USE_GLES2 "Use OpenGL ES2 renderer" OFF)
if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") OR
(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64"))
option(USE_GLES2 "Use OpenGL ES2 renderer" ON)
else()
option(USE_GLES2 "Use OpenGL ES2 renderer" OFF)
endif()
endif() endif()
if(UNIX OR MINGW) if(UNIX OR MINGW)
@ -143,7 +158,13 @@ else()
endif() endif()
# Find system GLEW library or build it if missing # Find system GLEW library or build it if missing
if(NOT USE_GLES2 AND NOT SERVER_ONLY) if (APPLE)
find_package(glew)
if(GLEW_FOUND)
include_directories(${GLEW_INCLUDE_DIRS})
endif()
elseif(NOT USE_GLES2 AND NOT SERVER_ONLY)
add_definitions(-DGLEW_NO_GLU) add_definitions(-DGLEW_NO_GLU)
if((UNIX AND NOT APPLE) AND USE_SYSTEM_GLEW) if((UNIX AND NOT APPLE) AND USE_SYSTEM_GLEW)
find_package(PkgConfig) find_package(PkgConfig)
@ -216,12 +237,12 @@ if (BUILD_RECORDER)
endif() endif()
endif() endif()
if(NOT SERVER_ONLY AND NOT USE_GLES2) if(NOT SERVER_ONLY)
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/graphics_utils") add_subdirectory("${PROJECT_SOURCE_DIR}/lib/graphics_utils")
include_directories("${PROJECT_SOURCE_DIR}/lib/graphics_utils") include_directories("${PROJECT_SOURCE_DIR}/lib/graphics_utils")
endif() endif()
if(NOT SERVER_ONLY AND NOT USE_GLES2) if(NOT SERVER_ONLY)
find_library(SQUISH_LIBRARY NAMES squish libsquish) find_library(SQUISH_LIBRARY NAMES squish libsquish)
find_path(SQUISH_INCLUDEDIR NAMES squish.h PATHS) find_path(SQUISH_INCLUDEDIR NAMES squish.h PATHS)
if (NOT SQUISH_LIBRARY OR NOT SQUISH_INCLUDEDIR) if (NOT SQUISH_LIBRARY OR NOT SQUISH_INCLUDEDIR)
@ -277,29 +298,12 @@ else()
endif() endif()
# OpenAL # OpenAL
if(APPLE) find_package(OpenAL REQUIRED)
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has include_directories(${OPENAL_INCLUDE_DIR})
# unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases :
# the mac I use to make STK releases does have other installs of vorbis/ogg/etc. which aren't compatible with STK, so letting
# CMake pick the library it wants essentially means I can't build.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework OpenAL")
set(OPENAL_LIBRARY)
else()
find_package(OpenAL REQUIRED)
include_directories(${OPENAL_INCLUDE_DIR})
endif()
# OggVorbis # OggVorbis
if(APPLE) find_package(OggVorbis REQUIRED)
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has include_directories(${OGGVORBIS_INCLUDE_DIRS})
# unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases :
# the mac I use to make STK releases does have other installs of vorbis/ogg/etc. which aren't compatible with STK, so letting
# CMake pick the library it wants essentially means I can't build.
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -I/Library/Frameworks/Ogg.framework/Versions/A/Headers -I/Library/Frameworks/Vorbis.framework/Versions/A/Headers")
else()
find_package(OggVorbis REQUIRED)
include_directories(${OGGVORBIS_INCLUDE_DIRS})
endif()
# Freetype # Freetype
find_package(Freetype) find_package(Freetype)
@ -450,14 +454,26 @@ else()
target_link_libraries(supertuxkart ${PTHREAD_LIBRARY}) target_link_libraries(supertuxkart ${PTHREAD_LIBRARY})
endif() endif()
# CURL # CURL and OpenSSL
# 1.0.1d for compatible AES GCM handling
SET(OPENSSL_MINIMUM_VERSION "1.0.1d")
if(MSVC) if(MSVC)
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurl.lib) target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurl.lib)
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libeay32.lib)
elseif(MINGW) elseif(MINGW)
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurldll.a) target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurldll.a)
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libeay32.dll)
else() else()
find_package(CURL REQUIRED) find_package(CURL REQUIRED)
find_package(OpenSSL REQUIRED)
if(${OPENSSL_VERSION} VERSION_LESS ${OPENSSL_MINIMUM_VERSION} OR
(${OPENSSL_VERSION} VERSION_EQUAL ${OPENSSL_MINIMUM_VERSION} AND ${OPENSSL_VERSION} STRLESS ${OPENSSL_MINIMUM_VERSION}))
message(FATAL_ERROR "OpenSSL version found (${OPENSSL_VERSION}) is less then the minimum required (${OPENSSL_MINIMUM_VERSION}), aborting.")
endif()
include_directories(${CURL_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS})
include_directories(${OpenSSL_INCLUDE_DIRS})
endif() endif()
# Common library dependencies # Common library dependencies
@ -474,19 +490,17 @@ target_link_libraries(supertuxkart
${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARIES}
${JPEG_LIBRARIES} ${JPEG_LIBRARIES}
${TURBOJPEG_LIBRARY} ${TURBOJPEG_LIBRARY}
#${VPX_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY}
) )
if(NOT SERVER_ONLY) if(NOT SERVER_ONLY)
if(NOT USE_GLES2) if(NOT USE_GLES2)
target_link_libraries(supertuxkart ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARIES} graphics_utils) target_link_libraries(supertuxkart ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARIES})
else() else()
target_link_libraries(supertuxkart GLESv2) target_link_libraries(supertuxkart GLESv2)
endif() endif()
endif()
if(NOT SERVER_ONLY AND NOT USE_GLES2) target_link_libraries(supertuxkart ${SQUISH_LIBRARY} graphics_utils)
target_link_libraries(supertuxkart ${SQUISH_LIBRARY})
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
@ -508,15 +522,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
endif() endif()
if(APPLE)
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has
# unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases :
# the mac I use to make STK releases does have other installs of vorbis/ogg/etc. which aren't compatible with STK, so letting
# CMake pick the library it wants essentially means I can't build.
set_target_properties(supertuxkart PROPERTIES LINK_FLAGS "-arch x86_64 -F/Library/Frameworks -framework OpenAL -framework Ogg -framework Vorbis")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/Library/Frameworks/OpenAL.framework/Versions/A/Headers")
endif()
if(USE_FRIBIDI) if(USE_FRIBIDI)
target_link_libraries(supertuxkart ${FRIBIDI_LIBRARIES}) target_link_libraries(supertuxkart ${FRIBIDI_LIBRARIES})
add_definitions(-DENABLE_BIDI) add_definitions(-DENABLE_BIDI)

View File

@ -188,20 +188,55 @@ On OS X 10.9.5, you might need the following workaround:
sudo ln -s `xcrun --show-sdk-path`/usr/include/ /usr/include sudo ln -s `xcrun --show-sdk-path`/usr/include/ /usr/include
sudo ln -s `xcrun --show-sdk-path`/System/Library/Frameworks/OpenGL.framework/Headers/ /usr/local/include/OpenGL sudo ln -s `xcrun --show-sdk-path`/System/Library/Frameworks/OpenGL.framework/Headers/ /usr/local/include/OpenGL
``` ```
The first link is required in order to find libcurl, the second to find opengl. The first link is required in order to find libcurl, the second to find opengl.
Download pre-built dependencies from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/OSX/) and put the frameworks in [hard disk root]/Library/Frameworks
### CMake ### CMake
CMake is used to build STK. At this time CMake will not make a binary that is ready for distribution. CMake is used to build STK. At this time CMake will not make a binary that is ready for distribution.
You'll have to run these commands inside your stk-code directory. You'll have to run these commands inside your stk-code directory.
### Building
With clang: ### STK 0.9.4 or later (or latest git)
Install homebrew ( https://brew.sh/)
Install all of the dependencies using homebrew :
```bash
brew install libogg
brew install libvorbis
brew install openal-soft
brew install freetype
brew install curl
brew install openssl@1.1
brew install fribidi
brew install glew
```
Build STK
```bash
mkdir cmake_build
cd cmake_build
CMAKE_PREFIX_PATH=/usr/local/opt/freetype/:/usr/local/opt/curl/:/usr/local/opt/libogg/:/usr/local/opt/libogg/:/usr/local/opt/libvorbis/:/usr/local/opt/openssl\@1.1/:/usr/local/opt/glew/:/usr/local/opt/fribidi/ /usr/local/opt/cmake/bin/cmake .. -DFREETYPE_INCLUDE_DIRS=/usr/local/opt/freetype/include/freetype2/ -DUSE_SYSTEM_GLEW=1 -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include/ -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib
make
```
#### (Optional) packaging for distribution
By default, the executable that is produced is not ready for distribution. Install https://github.com/auriamg/macdylibbundler
```bash
dylibbundler -od -b -x ./bin/SuperTuxKart.app/Contents/MacOS/supertuxkart -d ./bin/SuperTuxKart.app/Contents/libs/ -p @executable_path/../libs/
```
then copy the datafiles into /SuperTuxKart.app/Contents/Resources/data
### STK 0.9.3 or earlier
Download pre-built dependencies from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/OSX/) and put the frameworks in [hard disk root]/Library/Frameworks
Building with clang:
```bash ```bash
mkdir cmake_build mkdir cmake_build
@ -210,7 +245,7 @@ cmake ..
make make
``` ```
With GCC: Building with GCC:
```bash ```bash
mkdir cmake_build mkdir cmake_build
cd cmake_build cd cmake_build
@ -223,7 +258,7 @@ Building on 10.10 with 10.9 compatibility:
cmake .. -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 cmake .. -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
``` ```
### Xcode #### Xcode
Place an additional copy of the dependencies into `Users/<YOUR_USERNAME>/Library/Frameworks`. Place an additional copy of the dependencies into `Users/<YOUR_USERNAME>/Library/Frameworks`.
Then cd to your cloned stk-code directory and execute the following commands: Then cd to your cloned stk-code directory and execute the following commands:

View File

@ -158,6 +158,7 @@ LOCAL_CFLAGS := -I../lib/angelscript/include \
-Iobj/libogg/include \ -Iobj/libogg/include \
-Iobj/libvorbis/include \ -Iobj/libvorbis/include \
-Iobj/openal/include \ -Iobj/openal/include \
-Iobj/openssl/include \
-I$(call my-dir)/../../sources/android/native_app_glue \ -I$(call my-dir)/../../sources/android/native_app_glue \
-DUSE_GLES2 \ -DUSE_GLES2 \
-DHAVE_OGGVORBIS \ -DHAVE_OGGVORBIS \

View File

@ -39,8 +39,6 @@
<uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.gamepad" android:required="false"/> <uses-feature android:name="android.hardware.gamepad" android:required="false"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
</manifest> </manifest>

View File

@ -237,7 +237,7 @@ if [ -f "$DIRNAME/obj/project_version" ]; then
PROJECT_VERSION_PREV=$(cat "$DIRNAME/obj/project_version") PROJECT_VERSION_PREV=$(cat "$DIRNAME/obj/project_version")
if [ -z "$PROJECT_VERSION" ]; then if [ -z "$PROJECT_VERSION" ]; then
PROJECT_VERSION="$PROJECT_VERSION_PREV" export PROJECT_VERSION="$PROJECT_VERSION_PREV"
elif [ "$PROJECT_VERSION" != "$PROJECT_VERSION_PREV" ]; then elif [ "$PROJECT_VERSION" != "$PROJECT_VERSION_PREV" ]; then
echo "Different project version has been set. Forcing recompilation..." echo "Different project version has been set. Forcing recompilation..."
touch -c "$DIRNAME/Android.mk" touch -c "$DIRNAME/Android.mk"
@ -246,7 +246,7 @@ fi
if [ -z "$PROJECT_VERSION" ]; then if [ -z "$PROJECT_VERSION" ]; then
if [ $IS_DEBUG_BUILD -ne 0 ]; then if [ $IS_DEBUG_BUILD -ne 0 ]; then
PROJECT_VERSION="git" export PROJECT_VERSION="git"
else else
echo "Error: Variable PROJECT_VERSION is not set. It must have unique" \ echo "Error: Variable PROJECT_VERSION is not set. It must have unique" \
"value for release build." "value for release build."
@ -479,6 +479,10 @@ convert -scale 48x48 "$APP_ICON" "$DIRNAME/res/drawable-mdpi/icon.png"
convert -scale 96x96 "$APP_ICON" "$DIRNAME/res/drawable-xhdpi/icon.png" convert -scale 96x96 "$APP_ICON" "$DIRNAME/res/drawable-xhdpi/icon.png"
convert -scale 144x144 "$APP_ICON" "$DIRNAME/res/drawable-xxhdpi/icon.png" convert -scale 144x144 "$APP_ICON" "$DIRNAME/res/drawable-xxhdpi/icon.png"
if [ -f "/usr/lib/jvm/java-8-openjdk-amd64/bin/java" ]; then
export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
export PATH=$JAVA_HOME/bin:$PATH
fi
if [ "$BUILD_TOOL" = "gradle" ]; then if [ "$BUILD_TOOL" = "gradle" ]; then
export ANDROID_HOME="$SDK_PATH" export ANDROID_HOME="$SDK_PATH"

View File

@ -9,14 +9,7 @@
# FRIBIDI_LIBRARIES # FRIBIDI_LIBRARIES
# Fribidi library list # Fribidi library list
if(APPLE) if(UNIX)
set(FRIBIDI_INCLUDE_DIR NAMES fribidi/fribidi.h PATHS /Library/Frameworks/fribidi.framework/Headers)
find_library(FRIBIDI_LIBRARY NAMES fribidi PATHS /Library/Frameworks/fribidi.framework)
set(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY})
include_directories(/Library/Frameworks/fribidi.framework/Headers)
#add_definitions(-framework fribidi)
set(FRIBIDI_FOUND 1)
elseif(UNIX)
include(FindPkgConfig) include(FindPkgConfig)
pkg_check_modules(FRIBIDI fribidi) pkg_check_modules(FRIBIDI fribidi)
else() else()

View File

@ -17,20 +17,6 @@ find_library(OGGVORBIS_VORBIS_LIBRARY NAMES vorbis Vorbis libvorbis PATHS "${PRO
find_library(OGGVORBIS_VORBISFILE_LIBRARY NAMES vorbisfile libvorbisfile PATHS "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib") find_library(OGGVORBIS_VORBISFILE_LIBRARY NAMES vorbisfile libvorbisfile PATHS "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib")
find_library(OGGVORBIS_VORBISENC_LIBRARY NAMES vorbisenc libvorbisenc PATHS "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib") find_library(OGGVORBIS_VORBISENC_LIBRARY NAMES vorbisenc libvorbisenc PATHS "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib")
if (APPLE)
set(OGGVORBIS_OGG_INCLUDE_DIR "/Library/Frameworks/Ogg.framework/Headers/")
set(OGGVORBIS_VORBIS_INCLUDE_DIR "/Library/Frameworks/Vorbis.framework/Headers/")
endif()
if(APPLE AND NOT OGGVORBIS_VORBISFILE_LIBRARY)
# Seems to be the same on Apple systems
set(OGGVORBIS_VORBISFILE_LIBRARY ${OGGVORBIS_VORBIS_LIBRARY})
endif()
if(APPLE AND NOT OGGVORBIS_VORBISENC_LIBRARY)
# Seems to be the same on Apple systems
set(OGGVORBIS_VORBISENC_LIBRARY ${OGGVORBIS_VORBIS_LIBRARY})
endif()
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OggVorbis DEFAULT_MSG find_package_handle_standard_args(OggVorbis DEFAULT_MSG

View File

@ -1,15 +1,20 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="abyss" laps="3"/> <track id="abyss" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<best>
<karts number="7"/>
<requirements position="1" time="150"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="6"/>
<requirements position="1" time="160"/> <requirements position="1" time="165"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="5"/>
<requirements time="197"/> <requirements time="197"/>
</medium> </medium>
<easy> <easy>

View File

@ -1,21 +1,26 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="candela_city" laps="3"/> <track id="candela_city" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="70"/> <requirements trophies="75"/>
<best>
<karts number="9"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
<unlock kart="sara_the_wizard"/> <unlock kart="sara_the_racer"/>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="cocoa_temple" laps="3"/> <track id="cocoa_temple" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="5"/> <requirements trophies="5"/>
<best>
<karts number="8"/>
<requirements position="1" time="140"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="7"/>
<requirements position="1" time="170"/> <requirements position="1" time="170"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="6"/>
<requirements time="210"/> <requirements time="210"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="5"/>
<requirements time="300"/> <requirements time="300"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,15 +1,20 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="cornfield_crossing" laps="3"/> <track id="cornfield_crossing" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<best>
<karts number="7"/>
<requirements position="1" time="140"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="6"/>
<requirements position="1" time="165"/> <requirements position="1" time="165"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="5"/>
<requirements time="195"/> <requirements time="195"/>
</medium> </medium>
<easy> <easy>

View File

@ -1,9 +1,14 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="fortmagma" laps="3"/> <track id="fortmagma" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="180"/> <requirements trophies="190"/>
<best>
<karts number="2" aiIdent="nolok" superPower="nolokBoss"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="2" aiIdent="nolok" superPower="nolokBoss"/> <karts number="2" aiIdent="nolok" superPower="nolokBoss"/>
<requirements position="1"/> <requirements position="1"/>
@ -19,6 +24,5 @@
<unlock kart="gnu"/> <unlock kart="gnu"/>
<unlock kart="nolok"/> <unlock kart="nolok"/>
<unlock difficulty="difficulty_best"/>
<unlock track="fortmagma"/> <unlock track="fortmagma"/>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<grandprix id="1_penguinplayground"/> <grandprix id="1_penguinplayground"/>
<mode major="grandprix" minor="quickrace"/> <mode major="grandprix" minor="quickrace"/>
<requirements trophies="40"/> <requirements trophies="30"/>
<best>
<karts number="7"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="5"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="4"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<grandprix id="2_offthebeatentrack"/> <grandprix id="2_offthebeatentrack"/>
<mode major="grandprix" minor="quickrace"/> <mode major="grandprix" minor="quickrace"/>
<requirements trophies="85"/> <requirements trophies="70"/>
<best>
<karts number="8"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="5"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<grandprix id="3_tothemoonandback"/> <grandprix id="3_tothemoonandback"/>
<mode major="grandprix" minor="quickrace"/> <mode major="grandprix" minor="quickrace"/>
<requirements trophies="125"/> <requirements trophies="120"/>
<best>
<karts number="9"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<grandprix id="4_atworldsend"/> <grandprix id="4_atworldsend"/>
<mode major="grandprix" minor="quickrace"/> <mode major="grandprix" minor="quickrace"/>
<requirements trophies="165"/> <requirements trophies="165"/>
<best>
<karts number="10"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="9"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,20 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="gran_paradiso_island" laps="3"/> <track id="gran_paradiso_island" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="95"/> <requirements trophies="80"/>
<best>
<karts number="9"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="greenvalley" laps="3"/> <track id="greenvalley" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="95"/> <requirements trophies="90"/>
<best>
<karts number="9"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="hacienda" laps="3"/> <track id="hacienda" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="45"/> <requirements trophies="25"/>
<best>
<karts number="8"/>
<requirements position="1" time="130"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="7"/>
<requirements position="2" time="170"/> <requirements position="1" time="160"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="6"/>
<requirements time="187"/> <requirements position="2" time="187"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="5"/>
<requirements time="260"/> <requirements time="260"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,20 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<track id="lighthouse" laps="3"/> <unlock_list list="false"/>
<track id="lighthouse" laps="4"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="135"/> <requirements trophies="125"/>
<best>
<karts number="10"/>
<requirements position="1" time="120"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="9"/>
<requirements time="110" position="1"/> <requirements position="1" time="140"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="8"/>
<requirements time="145" position="1"/> <requirements position="1" time="190"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="7"/>
<requirements time="185"/> <requirements time="250"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,18 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="mansion" laps="3"/> <track id="mansion" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="110"/> <requirements trophies="100"/>
<best>
<karts number="9"/>
<requirements position="1" time="100"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="8"/>
<requirements time="110"/> <requirements position="1" time="115"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="7"/>
<requirements time="130"/> <requirements time="140"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="6"/>
<requirements time="160"/> <requirements time="180"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="mines" laps="3"/> <track id="mines" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="150"/> <requirements trophies="140"/>
<best>
<karts number="10"/>
<requirements position="1" time="140"/>
</best>
<hard> <hard>
<karts number="4"/> <karts number="9"/>
<requirements time="160"/> <requirements position="1" time="160"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="8"/>
<requirements time="190"/> <requirements position="2" time="190"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="7"/>
<requirements time="255"/> <requirements time="255"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<track id="minigolf" laps="3"/> <unlock_list list="false"/>
<track id="minigolf" laps="4"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="150"/> <requirements trophies="130"/>
<best>
<karts number="10"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="9"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="8"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="3"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,20 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<track id="olivermath" laps="3"/> <unlock_list list="false"/>
<track id="olivermath" laps="5"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<best>
<karts number="7"/>
<requirements position="1" time="95"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="6"/>
<requirements position="1" time="65"/> <requirements position="1" time="110"/>
</hard> </hard>
<medium> <medium>
<karts number="5"/> <karts number="5"/>
<requirements position="1" time="85"/> <requirements position="1" time="140"/>
</medium> </medium>
<easy> <easy>
<karts number="5"/> <karts number="4"/>
<requirements position="1" time="130"/> <requirements position="1" time="210"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,12 +1,17 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="sandtrack" laps="3"/> <track id="sandtrack" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<best>
<karts number="1"/>
<requirements energy="20" time="135"/>
</best>
<hard> <hard>
<karts number="1"/> <karts number="1"/>
<requirements energy="18" time="167"/> <requirements energy="18" time="165"/>
</hard> </hard>
<medium> <medium>
<karts number="1"/> <karts number="1"/>

View File

@ -1,15 +1,20 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="scotland" laps="3"/> <track id="scotland" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<best>
<karts number="7"/>
<requirements position="1" time="140"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="6"/>
<requirements position="1" time="165"/> <requirements position="1" time="165"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="5"/>
<requirements time="185"/> <requirements time="185"/>
</medium> </medium>
<easy> <easy>

View File

@ -1,18 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="snowmountain" laps="3"/> <track id="snowmountain" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="60"/> <requirements trophies="115"/>
<best>
<karts number="10"/>
<requirements position="1" time="120"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="9"/>
<requirements time="145"/> <requirements position="2" time="145"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="8"/>
<requirements time="187"/> <requirements time="187"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="7"/>
<requirements time="250"/> <requirements time="250"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="snowtuxpeak" laps="3"/> <track id="snowtuxpeak" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="60"/> <requirements trophies="45"/>
<best>
<karts number="8"/>
<requirements position="1" time="120"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="7"/>
<requirements position="1" time="145"/> <requirements position="1" time="140"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="6"/>
<requirements time="170"/> <requirements time="170"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="5"/>
<requirements time="195"/> <requirements time="210"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<challenge version="2">
<track id="stk_enterprise" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="110"/>
<hard>
<karts number="6"/>
<requirements position="2"/>
</hard>
<medium>
<karts number="6"/>
<requirements position="2"/>
</medium>
<easy>
<karts number="5"/>
<requirements position="2"/>
</easy>
</challenge>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<challenge version="3">
<unlock_list list="false"/>
<track id="stk_enterprise" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="105"/>
<best>
<karts number="9"/>
<requirements position="1"/>
</best>
<hard>
<karts number="8"/>
<requirements position="1"/>
</hard>
<medium>
<karts number="7"/>
<requirements position="1"/>
</medium>
<easy>
<karts number="6"/>
<requirements position="1"/>
</easy>
</challenge>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<challenge version="3">
<unlock_list list="true"/>
<!-- This is the (rounded) point equivalent of finishing all challenges
in easy, except the final challenge -->
<requirements trophies="190"/>
<unlock kart="amanda"/>
</challenge>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<challenge version="3">
<unlock_list list="true"/>
<!-- This is the point equivalent of finishing the
story mode with 8 supertux challenges and the rest in gold -->
<requirements trophies="280"/>
<unlock kart="sara_the_wizard"/>
</challenge>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<challenge version="3">
<unlock_list list="true"/>
<!-- This is the point equivalent of finishing the
story mode with all gold except 14 silver challenges -->
<requirements trophies="250"/>
<unlock difficulty="difficulty_best"/>
</challenge>

View File

@ -1,19 +1,24 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="volcano_island" laps="2"/> <track id="volcano_island" laps="2"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="15"/> <requirements trophies="15"/>
<best>
<karts number="8"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="5"/> <karts number="7"/>
<requirements position="1"/> <requirements position="1"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="6"/>
<requirements position="1"/> <requirements position="1"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="5"/>
<requirements position="1"/> <requirements position="1"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,12 +1,17 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<unlock_list list="false"/>
<track id="xr591" laps="2"/> <track id="xr591" laps="2"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="135"/> <requirements trophies="135"/>
<best>
<karts number="1"/>
<requirements energy="20" time="100"/>
</best>
<hard> <hard>
<karts number="1"/> <karts number="1"/>
<requirements energy="18" time="120"/> <requirements energy="18" time="115"/>
</hard> </hard>
<medium> <medium>
<karts number="1"/> <karts number="1"/>
@ -17,5 +22,3 @@
<requirements energy="12" time="180"/> <requirements energy="12" time="180"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -1,9 +1,14 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="3">
<track id="zengarden" laps="3"/> <unlock_list list="false"/>
<track id="zengarden" laps="4"/>
<mode major="single" minor="timetrial"/> <mode major="single" minor="timetrial"/>
<requirements trophies="45"/> <requirements trophies="35"/>
<best>
<karts number="3"/>
<requirements position="1"/>
</best>
<hard> <hard>
<karts number="2"/> <karts number="2"/>
<requirements position="1"/> <requirements position="1"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<particles emitter="box" box_x="0.05" box_y="0.05" box_z="0.60"> <particles emitter="box" box_x="0.05" box_y="0.05" box_z="0.05">
<spreading angle="2" /> <spreading angle="2" />

29
data/gfx/skid0.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<particles emitter="sphere" radius="0.03">
<spreading angle="25" />
<velocity x="0.0"
y="0.008"
z="-0.015" />
<material file="skid-particle1.png" />
<!-- Amount of particles emitted per second. The minimum rate
is used to show that the skidding bonus is now available,
the maximum is used when the skid bonus is applied to the kart -->
<rate min="200"
max="200" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="60"
max="70" />
<!-- Size of the particles -->
<size min="0.20"
max="0.20" />
<color min="253 253 253"
max="254 254 254" />
</particles>

View File

@ -1,29 +1,29 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<particles emitter="box" box_x="0.023" box_y="0.023" box_z="-0.5"> <particles emitter="sphere" radius="0.03">
<spreading angle="5" /> <spreading angle="15" />
<velocity x="0.0" <velocity x="0.0"
y="0.0" y="0.008"
z="-0.003" /> z="-0.015" />
<material file="skid-particle1.png" /> <material file="skid-particle1.png" />
<!-- Amount of particles emitted per second. The minimum rate <!-- Amount of particles emitted per second. The minimum rate
is used to show that the skidding bonus is now available, is used to show that the skidding bonus is now available,
the maximum is used when the skid bonus is applied to the kart --> the maximum is used when the skid bonus is applied to the kart -->
<rate min="1400" <rate min="2000"
max="1500" /> max="2000" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. --> <!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="15" <lifetime min="60"
max="25" /> max="70" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.35" <size min="0.18"
max="0.45" /> max="0.18" />
<color min="255 255 255" <color min="254 254 254"
max="255 255 255" /> max="255 255 255" />
</particles> </particles>

View File

@ -1,29 +1,29 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<particles emitter="box" box_x="0.023" box_y="0.023" box_z="-0.5"> <particles emitter="sphere" radius="0.03">
<spreading angle="5" /> <spreading angle="15" />
<velocity x="0.0" <velocity x="0.0"
y="0.0" y="0.008"
z="-0.003" /> z="-0.015" />
<material file="skid-particle2.png" /> <material file="skid-particle2.png" />
<!-- Amount of particles emitted per second. The minimum rate <!-- Amount of particles emitted per second. The minimum rate
is used to show that the skidding bonus is now available, is used to show that the skidding bonus is now available,
the maximum is used when the skid bonus is applied to the kart --> the maximum is used when the skid bonus is applied to the kart -->
<rate min="1400" <rate min="2500"
max="1500" /> max="2500" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. --> <!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="15" <lifetime min="65"
max="25" /> max="75" />
<!-- Size of the particles --> <!-- Size of the particles -->
<size min="0.35" <size min="0.20"
max="0.45" /> max="0.20" />
<color min="255 255 255" <color min="255 0 255"
max="255 255 255" /> max="255 100 255" />
</particles> </particles>

View File

@ -3,7 +3,7 @@
<track id="sandtrack" laps="3" reverse="false" /> <track id="sandtrack" laps="3" reverse="false" />
<track id="cornfield_crossing" laps="3" reverse="false" /> <track id="cornfield_crossing" laps="3" reverse="false" />
<track id="olivermath" laps="4" reverse="false" /> <track id="olivermath" laps="5" reverse="false" />
<track id="abyss" laps="3" reverse="false" /> <track id="abyss" laps="3" reverse="false" />
<track id="scotland" laps="3" reverse="false" /> <track id="scotland" laps="3" reverse="false" />

View File

@ -1,10 +1,10 @@
<supertuxkart_grand_prix name="Off the beaten track"> <supertuxkart_grand_prix name="Off the Beaten Track">
<track id="cocoa_temple" laps="3" reverse="false" /> <track id="cocoa_temple" laps="3" reverse="false" />
<track id="snowmountain" laps="3" reverse="false" /> <track id="hacienda" laps="3" reverse="false" />
<track id="hacienda" laps="3" reverse="false" /> <track id="zengarden" laps="4" reverse="false" />
<track id="zengarden" laps="4" reverse="false" /> <track id="volcano_island" laps="2" reverse="false" />
<track id="snowtuxpeak" laps="3" reverse="false" /> <track id="snowtuxpeak" laps="3" reverse="false" />
</supertuxkart_grand_prix> </supertuxkart_grand_prix>

View File

@ -1,11 +1,10 @@
<supertuxkart_grand_prix name="To the moon and back"> <supertuxkart_grand_prix name="To the Moon and Back">
<track id="gran_paradiso_island" laps="3" reverse="false" /> <track id="gran_paradiso_island" laps="3" reverse="false" />
<track id="greenvalley" laps="2" reverse="false" /> <track id="greenvalley" laps="3" reverse="false" />
<track id="mansion" laps="3" reverse="false" /> <track id="mansion" laps="3" reverse="false" />
<track id="stk_enterprise" laps="3" reverse="false" /> <track id="stk_enterprise" laps="3" reverse="false" />
<track id="volcano_island" laps="2" reverse="false" /> <track id="candela_city" laps="3" reverse="false" />
</supertuxkart_grand_prix> </supertuxkart_grand_prix>

View File

@ -1,11 +1,10 @@
<supertuxkart_grand_prix name="At World's End"> <supertuxkart_grand_prix name="At World's End">
<track id="fortmagma" laps="3" reverse="false" /> <track id="lighthouse" laps="4" reverse="false" />
<track id="minigolf" laps="3" reverse="false" /> <track id="snowmountain" laps="3" reverse="false" />
<track id="minigolf" laps="4" reverse="false" />
<track id="xr591" laps="3" reverse="false" /> <track id="xr591" laps="3" reverse="false" />
<track id="mines" laps="3" reverse="false" /> <track id="mines" laps="3" reverse="false" />
<track id="lighthouse" laps="4" reverse="false" />
</supertuxkart_grand_prix> </supertuxkart_grand_prix>

View File

@ -33,6 +33,7 @@
<card contains="ATI" os="windows" version="<=3.1.8787" disable="ForceLegacyDevice"/> <card contains="ATI" os="windows" version="<=3.1.8787" disable="ForceLegacyDevice"/>
<card os="android" disable="TextureFormatBGRA8888"/> <card os="android" disable="TextureFormatBGRA8888"/>
<card os="android" disable="ColorBufferFloat"/> <card os="android" disable="ColorBufferFloat"/>
<card os="android" disable="TextureCompressionS3TC"/>
<card contains="Adreno" os="android" version="<=19" disable="VertexIdWorking"/> <card contains="Adreno" os="android" version="<=19" disable="VertexIdWorking"/>
<card contains="Android Emulator" os="android" disable="ForceLegacyDevice"/> <card contains="Android Emulator" os="android" disable="ForceLegacyDevice"/>
<card contains="Android Emulator" os="android" disable="NpotTextures"/> <card contains="Android Emulator" os="android" disable="NpotTextures"/>

View File

@ -38,6 +38,8 @@ power.png by Auria, based on https://openclipart.org/detail/193925/check-engine
crown.png by glitch, from https://openclipart.org/detail/210257/misc-game-crown, released under public domain crown.png by glitch, from https://openclipart.org/detail/210257/misc-game-crown, released under public domain
ghost_plus.png by Alayan, based on https://openclipart.org/detail/17847/cartoon-ghost by lemmling, released under CC-O
==== ====
Glass Skin by Auria, under CC-BY-SA 3+ Glass Skin by Auria, under CC-BY-SA 3+

BIN
data/gui/cup_platinum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -9,7 +9,7 @@
<div layout="horizontal-row" width="100%" height="fit"> <div layout="horizontal-row" width="100%" height="fit">
<checkbox id="pixelshaders"/> <checkbox id="pixelshaders"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
<label text="Pixel Shaders" I18N="Video settings"/> <label text="Pixel shaders" I18N="Video settings"/>
</div> </div>
<spacer height="4" width="10" /> <spacer height="4" width="10" />
@ -61,7 +61,7 @@
<div layout="horizontal-row" proportion="1" height="fit"> <div layout="horizontal-row" proportion="1" height="fit">
<checkbox id="ssao"/> <checkbox id="ssao"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
<label text="Ambient Occlusion" I18N="Video settings"/> <label text="Ambient occlusion" I18N="Video settings"/>
</div> </div>
<spacer height="4" width="10" /> <spacer height="4" width="10" />
@ -81,7 +81,7 @@
<div layout="horizontal-row" proportion="1" height="fit"> <div layout="horizontal-row" proportion="1" height="fit">
<checkbox id="glow"/> <checkbox id="glow"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
<label text="Glow (outlines)" I18N="Video settings"/> <label text="Glow (Outlines)" I18N="Video settings"/>
</div> </div>
<spacer height="4" width="10" /> <spacer height="4" width="10" />
@ -119,7 +119,7 @@
<div layout="horizontal-row" proportion="1" height="fit"> <div layout="horizontal-row" proportion="1" height="fit">
<checkbox id="animated_characters"/> <checkbox id="animated_characters"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
<label text="Animated Characters" I18N="Video settings"/> <label text="Animated characters" I18N="Video settings"/>
</div> </div>
<spacer height="4" width="10" /> <spacer height="4" width="10" />
@ -134,9 +134,9 @@
<spacer height="20" width="10" /> <spacer height="20" width="10" />
<div layout="horizontal-row" width="100%" proportion="1"> <div layout="horizontal-row" width="100%" proportion="1">
<label text="Particles Effects" I18N="Video settings" width="40%"/> <label text="Particle effects" I18N="Video settings" width="40%"/>
<spacer width="10" height="10"/> <spacer width="10" height="10"/>
<gauge id="particles_effects" min_value="0" max_value="2" width="50%" /> <gauge id="particles_effects" min_value="1" max_value="2" width="50%" />
</div> </div>
<spacer height="4" width="10" /> <spacer height="4" width="10" />

BIN
data/gui/ghost_plus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,15 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<stkgui> <stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row"> <div y="2%" width="100%" height="96%" layout="vertical-row">
<div x="5%" y="0%" width="90%" proportion="6" layout="horizontal-row"> <div width="100%" height="50%" proportion="6" layout="horizontal-row">
<div width="40%" height="100%" layout="vertical-row"> <div width="25%" height="100%" layout="vertical-row">
<icon id="icon" align="center" width="100%" icon="gui/loading.png" /> <icon-button proportion="1" width="100%" height="100%" id="track_screenshot" custom_ratio="1.33333"/>
</div> </div>
<div width="60%" height="50%" layout="vertical-row"> <div width="75%" height="100%" layout="vertical-row">
<label id="name" width="100%" text_align="left"/> <div width="100%" height="25%" layout="vertical-row" >
<label id="name" width="100%" text_align="center"/>
</div>
<!-- This is filled in programmatically -->
<box width="98%" height="75%" align="center" layout="vertical-row" padding="1">
<list id="current_replay_info" x="0" y="0" width="100%" height="100%"/>
</box>
</div> </div>
</div> </div>
<div width="90%" align="center" layout="vertical-row" height="fit"> <div width="90%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" > <div width="100%" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="record-race" I18N="Ghost replay info action" text_align="left"/> <checkbox width="fit" id="record-race" I18N="Ghost replay info action" text_align="left"/>
@ -21,13 +29,21 @@
<spacer width="10"/> <spacer width="10"/>
<label proportion="1" id="watch-only-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Watch replay only"/> <label proportion="1" id="watch-only-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Watch replay only"/>
</div> </div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="compare-ghost" I18N="Ghost replay info action" text_align="left"/>
<spacer width="10"/>
<label proportion="1" id="compare-ghost-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Compare to another ghost"/>
</div>
</div> </div>
<div width="80%" proportion="5" align="center"> <div width="90%" proportion="5" align="center">
<buttonbar id="actions" x="0" y="0" height="100%" width="100%" align="center"> <buttonbar id="actions" x="0" y="0" height="100%" width="100%" align="center">
<icon-button id="start" width="128" height="128" <icon-button id="start" width="128" height="128"
icon="gui/green_check.png" icon="gui/green_check.png"
I18N="Ghost replay info screen action" text="Start Race" /> I18N="Ghost replay info screen action" text="Start Race" />
<icon-button id="add-ghost-to-compare" width="128" height="128"
icon="gui/ghost_plus.png"
I18N="Ghost replay info screen action" text="Compare ghost" />
<icon-button id="remove" width="128" height="128" <icon-button id="remove" width="128" height="128"
icon="gui/remove.png" icon="gui/remove.png"
I18N="Ghost replay info action" text="Remove" /> I18N="Ghost replay info action" text="Remove" />

View File

@ -8,19 +8,50 @@
<icon-button id="reload" height="90%" icon="gui/restart.png"/> <icon-button id="reload" height="90%" icon="gui/restart.png"/>
</div> </div>
<!-- This is filled in programmatically -->
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6"> <box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
<list id="replay_list" x="0" y="0" width="100%" height="100%"/> <list id="replay_list" x="0" y="0" width="100%" height="100%"/>
</box> </box>
<div width="99%" align="center" layout="vertical-row" height="fit"> <tabs id="race_mode" height="6%" max_height="110" x="2%" width="98%" align="center">
<div width="100%" height="fit" layout="horizontal-row" > <icon-button id="tab_time_trial" width="128" height="128" icon="gui/mode_tt.png"
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/> I18N="In the ghost replay selection screen" text="Time trial"/>
<spacer width="10"/> <icon-button id="tab_egg_hunt" width="128" height="128" icon="gui/mode_easter.png"
<label proportion="1" height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/> I18N="In the ghost replay selection screen" text="Egg hunt"/>
</tabs>
<spacer width="100%" height="1.5%" />
<div width="99%" align="center" layout="horizontal-row" height="fit">
<div proportion="1" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="best_times_toggle" text_align="left"/>
<spacer width="2%" height="fit"/>
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show the best times"/>
</div>
<div proportion="1" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="compare_toggle" text_align="left"/>
<spacer width="2%" height="fit"/>
<label height="100%" id="compare-toggle-text" text_align="left" I18N="In the ghost replay selection screen" text="Compare replay"/>
</div> </div>
</div> </div>
<spacer width="100%" height="1%" />
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record ghost replay"/> <div width="99%" align="center" layout="horizontal-row" height="fit">
<div proportion="2" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/>
<spacer width="1%" height="fit"/>
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/>
</div>
</div>
<div width="99%" align="center" layout="horizontal-row" height="fit">
<div proportion="1" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="replay_version_toggle" text_align="left"/>
<spacer width="1%" height="fit" />
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current version"/>
</div>
</div>
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record a ghost replay"/>
</div> </div>
</stkgui> </stkgui>

BIN
data/gui/mystery_unlock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -14,13 +14,17 @@
</box> </box>
</div> </div>
</div> </div>
<spacer height="10"/> <spacer height="20"/>
<div width="100%" proportion="1" layout="horizontal-row"> <div width="100%" proportion="1" layout="horizontal-row">
<spacer width="20" height="20"/> <spacer width="20" height="20"/>
<box proportion="2" height="100%" layout="vertical-row"> <box proportion="2" height="100%" layout="vertical-row">
<textbox id="chat" width="100%" height="30%"/> <textbox id="chat" width="100%" height="30%"/>
<spacer height="20"/> <spacer height="10"/>
<button id="send" height="30%" width="fit" I18N="In the network lobby" text="Send" /> <div width="100%" height="30%" proportion="1" layout="horizontal-row">
<button id="send" width="10%" height="fit" I18N="In the network lobby" text="Send" />
<spacer width="10"/>
<label id="timeout-message" width="80%" height="fit"/>
</div>
</box> </box>
<spacer width="40"/> <spacer width="40"/>
<buttonbar id="actions" proportion="1" width="75%" height="75%"> <buttonbar id="actions" proportion="1" width="75%" height="75%">

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="2%" width="100%" height="96%" layout="vertical-row">
<header id="title" width="96%" height="fit" text_align="center"
word_wrap="true" I18N="In player rankings dialog"
text="Top 10 players"/>
<box x="2%" width="90%" height="60%" align="center" layout="vertical-row"
padding="6">
<list id="top-ten" x="0" y="0" width="100%" height="100%"/>
</box>
<label id="cur-rank" proportion="1" width="90%" align="center"
text_align="center" word_wrap="true" text=""/>
<buttonbar id="options" width="90%" height="10%" align="center">
<icon-button id="ok" width="16" height="16"
icon="gui/green_check.png" text="OK"
label_location="bottom"/>
<icon-button id="refresh" width="16" height="16"
icon="gui/restart.png"
text="Refresh" label_location="bottom"/>
</buttonbar>
<spacer width="20" height="2%" />
</div>
</stkgui>

View File

@ -18,5 +18,6 @@
<box proportion="1" width="100%" layout="vertical-row" padding="6"> <box proportion="1" width="100%" layout="vertical-row" padding="6">
<list id="achievements_list" x="0" y="0" width="100%" height="100%"/> <list id="achievements_list" x="0" y="0" width="100%" height="100%"/>
</box> </box>
<button id="rankings" I18N="In the achievements screen" text="Player rankings"/>
</div> </div>
</stkgui> </stkgui>

View File

@ -21,7 +21,7 @@
<label id="novice_label" proportion="1" height="100%"/> <label id="novice_label" proportion="1" height="100%"/>
</div> </div>
<spacer height="8%" width="1"/> <spacer height="6%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row"> <div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="intermediate" icon="gui/difficulty_medium.png" <icon-button id="intermediate" icon="gui/difficulty_medium.png"
@ -30,7 +30,7 @@
<label id="intermediate_label" proportion="1" height="100%"/> <label id="intermediate_label" proportion="1" height="100%"/>
</div> </div>
<spacer height="8%" width="1"/> <spacer height="6%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row"> <div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="expert" icon="gui/difficulty_hard.png" <icon-button id="expert" icon="gui/difficulty_hard.png"
@ -39,7 +39,16 @@
<label id="difficult_label" proportion="1" height="100%"/> <label id="difficult_label" proportion="1" height="100%"/>
</div> </div>
<spacer height="8%" width="1"/> <spacer height="6%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="supertux" icon="gui/difficulty_best.png"
I18N="Difficulty" text="SuperTux" height="100%"/>
<spacer width="5%" height="1"/>
<label id="supertux_label" proportion="1" height="100%"/>
</div>
<spacer height="2%" width="1"/>
</div> </div>
</stkgui> </stkgui>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
<header id="title" width="100%" text="Race Setup" align="center" text_align="center" />
<spacer height="2%" width="1"/>
<div width="100%" layout="horizontal-row" height="fit">
<label id="race_type" text="Type:" I18N="Type of race, in a challenge"/>
<spacer width="5" height="1"/>
<label id="race_type_val" proportion="1"/>
</div>
<spacer height="2%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="novice" icon="gui/difficulty_easy.png"
I18N="Difficulty" text="Novice" height="100%"/>
<spacer width="5%" height="1"/>
<label id="novice_label" proportion="1" height="100%"/>
</div>
<spacer height="8%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="intermediate" icon="gui/difficulty_medium.png"
I18N="Difficulty" text="Intermediate" height="100%"/>
<spacer width="5%" height="1"/>
<label id="intermediate_label" proportion="1" height="100%"/>
</div>
<spacer height="8%" width="1"/>
<div width="100%" proportion="1" layout="horizontal-row">
<icon-button id="expert" icon="gui/difficulty_hard.png"
I18N="Difficulty" text="Expert" height="100%"/>
<spacer width="5%" height="1"/>
<label id="difficult_label" proportion="1" height="100%"/>
</div>
<spacer height="8%" width="1"/>
</div>
</stkgui>

View File

@ -41,7 +41,7 @@
<div id="vote" x="63%" y="1%" width="37%" height="96%" layout="vertical-row"> <div id="vote" x="63%" y="1%" width="37%" height="96%" layout="vertical-row">
<div width="95%" proportion="2" layout="horizontal-row"> <div width="95%" proportion="2" layout="horizontal-row">
<box proportion="2" height="100%" layout="vertical-row"> <box proportion="2" height="100%" layout="vertical-row">
<label id="vote-text" word_wrap="true" id="text" proportion="3" width="100%" height="100%" text_valign="top"/> <label id="vote-text" word_wrap="true" proportion="3" width="100%" height="100%" text_valign="top"/>
</box> </box>
</div> </div>
</div> </div>

View File

@ -403,17 +403,17 @@
<player-characteristics> <player-characteristics>
<characteristic name="normal" /> <characteristic name="normal" />
<characteristic name="handicap"> <characteristic name="handicap">
<engine brake-factor="*0.8" brake-time-increase="*0.85" max-speed-reverse-ratio="*0.8" /> <engine power="*0.9" max-speed="*0.9" brake-factor="*0.8" brake-time-increase="*0.85" max-speed-reverse-ratio="*0.8" />
<bubblegum duration="*1.5" speed-fraction="*1.5" torque="*1.5" /> <skid time-till-bonus="*1.2 1.0" bonus-speed="*0.9 0.8" bonus-force="*0.9 0.9" />
<zipper duration="*0.8" force="*0.8" speed-gain="*0.8" max-speed-increase="*0.8" /> <bubblegum duration="*1.5" torque="*1.5" />
<swatter duration="*0.8" squash-duration="*1.5" squash-slowdown="*1.8" /> <zipper force="*0.8" speed-gain="*0.8" max-speed-increase="*0.8" />
<swatter duration="*0.8" squash-duration="*1.3" />
<plunger band-max-length="*0.8" band-speed-increase="*0.8" in-face-time="*1.3" /> <plunger band-max-length="*0.8" band-speed-increase="*0.8" in-face-time="*1.3" />
<startup time="*0.8 0.8" boost="*0.8 0.8" /> <startup time="*0.8 0.8" boost="*0.8 0.8" />
<rescue duration="*1.5" /> <rescue duration="*1.5" />
<explosion duration="*1.3" invulnerability-time="*0.7" /> <nitro engine-force="*0.8" max-speed-increase="*0.9" max="*0.8" />
<nitro engine-force="*0.8" consumption="*1.1" max-speed-increase="*0.9" max="*0.8" /> <slipstream min-collect-time="*1.2" add-power="*0.9"
<slipstream length="*0.8" width="*0.8" collect-time="*1.5" use-time="*0.8" max-speed-increase="*0.9" duration-factor="*0.9" />
add-power="*0.8" min-speed="*0.8" max-speed-increase="*0.9" duration="*0.8" />
</characteristic> </characteristic>
</player-characteristics> </player-characteristics>
</characteristics> </characteristics>

File diff suppressed because it is too large Load Diff

View File

@ -113,14 +113,25 @@
<!-- Replay related values, mostly concerned with saving less data <!-- Replay related values, mostly concerned with saving less data
and using interpolation instead. and using interpolation instead.
max-time: Maximum race time that can be saved in a replay/history file. max-frames: Maximum number of transform events that can be saved
delta-t Minumum time between saving consecutive transform events. in a replay/history file. With normal play, 900 are
delta-pos If the interpolated position is within this delta, a enough to store at least one minute, usually more.
transform event is not generated. delta-t Maximum time between saving consecutive transform events.
delta-angle If the interpolated angle is within this delta, The recording will do more transform events when some kart data
a transform event is not generated. --> changes significantly.
<replay max-time="600" delta-t="0.05" delta-pos="0.1" delta-speed If the speed difference exceeds this delta, a
delta-angle="0.5" /> new transform event is generated before maximum time.
delta-steering If the steering angle difference exceeds this delta,
new transform event is generated before maximum time. -->
<replay max-frames="12000" delta-t="0.200" delta-speed="0.6"
delta-steering="0.35" />
<!-- Determines the minimap related values.
size: The size of the minimap (scaled afterwards) 480 = full screen height)
ai-icon: The size of the icons for the AI karts on the minimap.
player-icon: The size of the icons for the player karts. -->
<minimap size="180.0" ai-icon="16.0" player-icon="20.0"/>
<!-- Skidmark data: maximum number of skid marks, and <!-- Skidmark data: maximum number of skid marks, and
time for skidmarks to fade out. Maximum number will over time for skidmarks to fade out. Maximum number will over
@ -284,10 +295,12 @@
distance ahead, the value for the largest distance is used, distance ahead, the value for the largest distance is used,
and similarly if the kart is more than the minimum value and similarly if the kart is more than the minimum value
behind). behind).
speed-cap: Fraction of maximum speed the kart should drive first-speed-cap: Fraction of maximum speed the first AI kart
at. Used to slow down karts that are ahead of the player. should drive at. Used to slow down karts that are ahead of
Note that setting this to a value >1 does NOT increase the player. Note that setting this to a value >1 does NOT
the speed the kart can drive at! increase the speed the kart can drive at!
last-speed-cap: same as first-speed-cap, but for last AI kart.
AI karts in-between use an average of it with first-speed-cap.
collect-item-probability: Probability of the AI actually collect-item-probability: Probability of the AI actually
trying to collect an item (if an item is selected for trying to collect an item (if an item is selected for
collection in the first place). collection in the first place).
@ -304,7 +317,8 @@
item-skill="1" item-skill="1"
collect-avoid-items="false" collect-avoid-items="false"
handle-bomb="false" handle-bomb="false"
speed-cap="-10:1.0 -5:0.9 5:0.8 20:0.7 50:0.6" first-speed-cap="-100:1.0 -50:0.9 0:0.85 100:0.65"
last-speed-cap="-150:0.92 -50:0.75 50:0.6"
max-item-angle="0.7" max-item-angle-high-speed="0.3" max-item-angle="0.7" max-item-angle-high-speed="0.3"
bad-item-closeness="6" bad-item-closeness="6"
collect-item-probability="0:0" collect-item-probability="0:0"
@ -322,7 +336,8 @@
item-skill="2" item-skill="2"
collect-avoid-items="true" collect-avoid-items="true"
handle-bomb="false" handle-bomb="false"
speed-cap="10:1.0 50:0.8" first-speed-cap="20:1.0 60:0.9 100:0.85"
last-speed-cap="-50:0.94 0:0.85 100:0.75"
max-item-angle="0.7" max-item-angle-high-speed="0.3" max-item-angle="0.7" max-item-angle-high-speed="0.3"
bad-item-closeness="6" bad-item-closeness="6"
collect-item-probability="-10:1.0 0:0" collect-item-probability="-10:1.0 0:0"
@ -340,7 +355,8 @@
item-skill="3" item-skill="3"
collect-avoid-items="true" collect-avoid-items="true"
handle-bomb="true" handle-bomb="true"
speed-cap="20:1.0 50:0.8" first-speed-cap="50:1.0 150:0.9"
last-speed-cap="0:0.96 80:0.8"
max-item-angle="0.7" max-item-angle-high-speed="0.3" max-item-angle="0.7" max-item-angle-high-speed="0.3"
bad-item-closeness="6" bad-item-closeness="6"
collect-item-probability="10:1.0 20:0" collect-item-probability="10:1.0 20:0"
@ -358,7 +374,8 @@
item-skill="4" item-skill="4"
collect-avoid-items="true" collect-avoid-items="true"
handle-bomb="true" handle-bomb="true"
speed-cap="0:1.0" first-speed-cap="0:1.0"
last-speed-cap="0:1.0"
max-item-angle="0.7" max-item-angle-high-speed="0.3" max-item-angle="0.7" max-item-angle-high-speed="0.3"
bad-item-closeness="6" bad-item-closeness="6"
collect-item-probability="0:1.0" collect-item-probability="0:1.0"

View File

@ -21,11 +21,6 @@ add_library(enet STATIC
win32.c win32.c
) )
if(MINGW) if(WIN32)
target_link_libraries(enet wsock32 ws2_32 winmm) target_link_libraries(enet wsock32 ws2_32 winmm)
endif() endif()
#if(WIN32)
# find_library(WS2_LIBRARY NAMES "ws2_32" PATHS "C:/Windows/System32")
# target_link_libraries(enet ${WS2_LIBRARY})
#endif()

View File

@ -8,9 +8,6 @@
#define ENET_BUILDING_LIB 1 #define ENET_BUILDING_LIB 1
#include "enet/enet.h" #include "enet/enet.h"
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "winmm.lib")
static enet_uint32 timeBase = 0; static enet_uint32 timeBase = 0;
int int

29
lib/graphics_utils/mipmap/cpusimd.c Normal file → Executable file
View File

@ -45,11 +45,6 @@
#include "cpusimd.h" #include "cpusimd.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
//// ////
@ -66,7 +61,9 @@ const uint32_t CPU_ALIGN16 simd4uOneInv[4] = { ~1, ~1, ~1, ~1 };
const uint32_t CPU_ALIGN16 simd4uTwo[4] = { 2, 2, 2, 2 }; const uint32_t CPU_ALIGN16 simd4uTwo[4] = { 2, 2, 2, 2 };
const uint32_t CPU_ALIGN16 simd4uFour[4] = { 4, 4, 4, 4 }; const uint32_t CPU_ALIGN16 simd4uFour[4] = { 4, 4, 4, 4 };
const float CPU_ALIGN16 simd4fQuarter[4] = { 0.25, 0.25, 0.25, 0.25 }; const float CPU_ALIGN16 simd4fQuarter[4] = { 0.25, 0.25, 0.25, 0.25 };
const float CPU_ALIGN16 simd4fPi[4] = { M_PI, M_PI, M_PI, M_PI }; // Avoid double to float conversion warnings when using M_PI --> use our own PI
#define PI 3.14159265358979323846f
const float CPU_ALIGN16 simd4fPi[4] = { PI, PI, PI, PI };
const float CPU_ALIGN16 simd4fZeroOneTwoThree[4] = { 0.0, 1.0, 2.0, 3.0 }; const float CPU_ALIGN16 simd4fZeroOneTwoThree[4] = { 0.0, 1.0, 2.0, 3.0 };
const uint32_t CPU_ALIGN16 simd4fAlphaMask[4] = { 0x00000000, 0x00000000, 0x00000000, 0xffffffff }; const uint32_t CPU_ALIGN16 simd4fAlphaMask[4] = { 0x00000000, 0x00000000, 0x00000000, 0xffffffff };
const float CPU_ALIGN16 simd4f255[4] = { 255.0f, 255.0f, 255.0f, 255.0f }; const float CPU_ALIGN16 simd4f255[4] = { 255.0f, 255.0f, 255.0f, 255.0f };
@ -102,16 +99,16 @@ const float CPU_ALIGN16 simd4f255Inv[4] = { 1.0f/255.0f, 1.0f/255.0f, 1.0f/255.0
(this is the zlib license) (this is the zlib license)
*/ */
static const float CPU_ALIGN16 simd4f_cephes_FOPI[4] = { 1.27323954473516, 1.27323954473516, 1.27323954473516, 1.27323954473516 }; static const float CPU_ALIGN16 simd4f_cephes_FOPI[4] = { 1.27323954473516f, 1.27323954473516f, 1.27323954473516f, 1.27323954473516f };
static const float CPU_ALIGN16 simd4f_minus_cephes_DP1[4] = { -0.78515625, -0.78515625, -0.78515625, -0.78515625 }; static const float CPU_ALIGN16 simd4f_minus_cephes_DP1[4] = { -0.78515625, -0.78515625, -0.78515625, -0.78515625 };
static const float CPU_ALIGN16 simd4f_minus_cephes_DP2[4] = { -2.4187564849853515625e-4, -2.4187564849853515625e-4, -2.4187564849853515625e-4, -2.4187564849853515625e-4 }; static const float CPU_ALIGN16 simd4f_minus_cephes_DP2[4] = { -2.4187564849853515625e-4, -2.4187564849853515625e-4, -2.4187564849853515625e-4, -2.4187564849853515625e-4 };
static const float CPU_ALIGN16 simd4f_minus_cephes_DP3[4] = { -3.77489497744594108e-8, -3.77489497744594108e-8, -3.77489497744594108e-8, -3.77489497744594108e-8 }; static const float CPU_ALIGN16 simd4f_minus_cephes_DP3[4] = { -3.77489497744594108e-8f, -3.77489497744594108e-8f, -3.77489497744594108e-8f, -3.77489497744594108e-8f };
static const float CPU_ALIGN16 simd4f_sincof_p0[4] = { -1.9515295891E-4, -1.9515295891E-4, -1.9515295891E-4, -1.9515295891E-4 }; static const float CPU_ALIGN16 simd4f_sincof_p0[4] = { -1.9515295891E-4f, -1.9515295891E-4f, -1.9515295891E-4f, -1.9515295891E-4f };
static const float CPU_ALIGN16 simd4f_sincof_p1[4] = { 8.3321608736E-3, 8.3321608736E-3, 8.3321608736E-3, 8.3321608736E-3 }; static const float CPU_ALIGN16 simd4f_sincof_p1[4] = { 8.3321608736E-3f, 8.3321608736E-3f, 8.3321608736E-3f, 8.3321608736E-3f };
static const float CPU_ALIGN16 simd4f_sincof_p2[4] = { -1.6666654611E-1, -1.6666654611E-1, -1.6666654611E-1, -1.6666654611E-1 }; static const float CPU_ALIGN16 simd4f_sincof_p2[4] = { -1.6666654611E-1f, -1.6666654611E-1f, -1.6666654611E-1f, -1.6666654611E-1f };
static const float CPU_ALIGN16 simd4f_coscof_p0[4] = { 2.443315711809948E-005, 2.443315711809948E-005, 2.443315711809948E-005, 2.443315711809948E-005 }; static const float CPU_ALIGN16 simd4f_coscof_p0[4] = { 2.443315711809948E-005f, 2.443315711809948E-005f, 2.443315711809948E-005f, 2.443315711809948E-005f };
static const float CPU_ALIGN16 simd4f_coscof_p1[4] = { -1.388731625493765E-003, -1.388731625493765E-003, -1.388731625493765E-003, -1.388731625493765E-003 }; static const float CPU_ALIGN16 simd4f_coscof_p1[4] = { -1.388731625493765E-003f, -1.388731625493765E-003f, -1.388731625493765E-003f, -1.388731625493765E-003f };
static const float CPU_ALIGN16 simd4f_coscof_p2[4] = { 4.166664568298827E-002, 4.166664568298827E-002, 4.166664568298827E-002, 4.166664568298827E-002 }; static const float CPU_ALIGN16 simd4f_coscof_p2[4] = { 4.166664568298827E-002f, 4.166664568298827E-002f, 4.166664568298827E-002f, 4.166664568298827E-002f };
__m128 simd4f_sin_ps( __m128 x ) __m128 simd4f_sin_ps( __m128 x )
{ {
@ -516,8 +513,8 @@ static inline CC_ALWAYSINLINE __m128 simd4f_fastpow_ps( __m128 arg, uint32_t exp
__m128 ret = arg; __m128 ret = arg;
float corrfactor, powfactor; float corrfactor, powfactor;
/* Apply a constant pre-correction factor. */ /* Apply a constant pre-correction factor. */
corrfactor = exp2( 127.0 * expden / expnum - 127.0 ) * pow( 1.0 * coeffnum / coeffden, 1.0 * expden / expnum ); corrfactor = (float)(exp2( 127.0 * expden / expnum - 127.0 ) * pow( 1.0 * coeffnum / coeffden, 1.0 * expden / expnum ));
powfactor = 1.0 * expnum / expden; powfactor = 1.0f * expnum / expden;
ret = _mm_mul_ps( ret, _mm_set1_ps( corrfactor ) ); ret = _mm_mul_ps( ret, _mm_set1_ps( corrfactor ) );
/* Reinterpret arg as integer to obtain logarithm. */ /* Reinterpret arg as integer to obtain logarithm. */
ret = _mm_cvtepi32_ps( _mm_castps_si128( ret ) ); ret = _mm_cvtepi32_ps( _mm_castps_si128( ret ) );

View File

@ -199,7 +199,24 @@ namespace irr
IRR_KEY_BUTTON_SELECT = 0x111, IRR_KEY_BUTTON_SELECT = 0x111,
IRR_KEY_BUTTON_MODE = 0x112, IRR_KEY_BUTTON_MODE = 0x112,
IRR_KEY_CODES_COUNT = 0x113 // this is not a key, but the amount of keycodes there are. // For Azerty layout
IRR_KEY_AMPERSAND = 0x113,
IRR_KEY_EACUTE = 0x114,
IRR_KEY_QUOTEDBL = 0x115,
IRR_KEY_PARENLEFT = 0x116,
IRR_KEY_EGRAVE = 0x117,
IRR_KEY_CCEDILLA = 0x118,
IRR_KEY_AGRAVE = 0x119,
IRR_KEY_PARENRIGHT = 0x120,
IRR_KEY_UGRAVE = 0x121,
IRR_KEY_COLON = 0x122,
IRR_KEY_DOLLAR = 0x123,
IRR_KEY_EXCLAM = 0x124,
IRR_KEY_TWOSUPERIOR = 0x125,
IRR_KEY_MU = 0x126,
IRR_KEY_SECTION = 0x127,
IRR_KEY_CODES_COUNT = 0x128 // this is not a key, but the amount of keycodes there are.
}; };
} // end namespace irr } // end namespace irr

View File

@ -13,7 +13,7 @@ namespace gui
//You can add more characters if needed //You can add more characters if needed
//For full list please visit http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/kinsoku.html //For full list please visit http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/kinsoku.html
bool UtfNoStarting (wchar_t c) inline bool UtfNoStarting (wchar_t c)
{ {
switch (c) switch (c)
{ {
@ -66,7 +66,7 @@ bool UtfNoStarting (wchar_t c)
} }
} }
bool UtfNoEnding (wchar_t c) inline bool UtfNoEnding (wchar_t c)
{ {
switch (c) switch (c)
{ {
@ -99,7 +99,7 @@ bool UtfNoEnding (wchar_t c)
//Helper function //Helper function
bool breakable (wchar_t c) inline bool breakable (wchar_t c)
{ {
if ((c > 12287 && c < 40960) || //Common CJK words if ((c > 12287 && c < 40960) || //Common CJK words
(c > 44031 && c < 55204) || //Hangul (c > 44031 && c < 55204) || //Hangul

View File

@ -105,7 +105,8 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
Width(param.WindowSize.Width), Height(param.WindowSize.Height), Width(param.WindowSize.Width), Height(param.WindowSize.Height),
WindowHasFocus(false), WindowMinimized(false), WindowHasFocus(false), WindowMinimized(false),
UseXVidMode(false), UseXRandR(false), UseGLXWindow(false), UseXVidMode(false), UseXRandR(false), UseGLXWindow(false),
ExternalWindow(false), AutorepeatSupport(0) ExternalWindow(false), AutorepeatSupport(0), SupportsNetWM(false),
NeedsGrabPointer(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CIrrDeviceLinux"); setDebugName("CIrrDeviceLinux");
@ -477,6 +478,19 @@ bool CIrrDeviceLinux::changeResolution()
if (s == Success) if (s == Success)
UseXRandR = true; UseXRandR = true;
if (UseXRandR && SupportsNetWM)
{
XRRPanning* panning = XRRGetPanning(display, res, output->crtc);
if ((panning->width != Width && panning->width != 0) ||
(panning->height != Height && panning->height != 0))
{
NeedsGrabPointer = true;
}
XRRFreePanning(panning);
}
XRRFreeCrtcInfo(crtc); XRRFreeCrtcInfo(crtc);
XRRFreeOutputInfo(output); XRRFreeOutputInfo(output);
@ -614,6 +628,40 @@ static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig, boo
#endif #endif
#endif #endif
void CIrrDeviceLinux::grabPointer(bool grab)
{
#ifdef _IRR_COMPILE_WITH_X11_
if (grab)
{
int result = 0;
for (int i = 0; i < 500; i++)
{
const unsigned int mask = ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask;
int result = XGrabPointer(display, window, True, mask,
GrabModeAsync, GrabModeAsync,
window, None, CurrentTime);
if (result == GrabSuccess)
break;
usleep(1000);
}
if (result != GrabSuccess)
{
os::Printer::log("Couldn't grab pointer.", ELL_WARNING);
}
}
else
{
XUngrabPointer(display, CurrentTime);
}
#endif
}
bool CIrrDeviceLinux::createWindow() bool CIrrDeviceLinux::createWindow()
{ {
#ifdef _IRR_COMPILE_WITH_X11_ #ifdef _IRR_COMPILE_WITH_X11_
@ -632,6 +680,24 @@ bool CIrrDeviceLinux::createWindow()
} }
screennr = DefaultScreen(display); screennr = DefaultScreen(display);
Atom *list;
Atom type;
int form;
unsigned long remain, len;
Atom WMCheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", false);
Status s = XGetWindowProperty(display, DefaultRootWindow(display),
WMCheck, 0L, 1L, False, XA_WINDOW,
&type, &form, &len, &remain,
(unsigned char **)&list);
if (s == Success)
{
XFree(list);
SupportsNetWM = (len > 0);
}
changeResolution(); changeResolution();
@ -954,30 +1020,10 @@ bool CIrrDeviceLinux::createWindow()
attributes.event_mask |= PointerMotionMask | attributes.event_mask |= PointerMotionMask |
ButtonPressMask | KeyPressMask | ButtonPressMask | KeyPressMask |
ButtonReleaseMask | KeyReleaseMask; ButtonReleaseMask | KeyReleaseMask;
bool netWM = false;
Atom *list;
Atom type;
int form;
unsigned long remain, len;
Atom WMCheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", false);
Status s = XGetWindowProperty(display, DefaultRootWindow(display),
WMCheck, 0L, 1L, False, XA_WINDOW,
&type, &form, &len, &remain,
(unsigned char **)&list);
if (s == Success)
{
XFree(list);
netWM = (len > 0);
}
if (!CreationParams.WindowId) if (!CreationParams.WindowId)
{ {
attributes.override_redirect = !netWM && CreationParams.Fullscreen; attributes.override_redirect = !SupportsNetWM && CreationParams.Fullscreen;
// create new Window // create new Window
window = XCreateWindow(display, window = XCreateWindow(display,
@ -1010,7 +1056,7 @@ bool CIrrDeviceLinux::createWindow()
bool has_display_size = (Width == display_width && Height == display_height); bool has_display_size = (Width == display_width && Height == display_height);
if (netWM && (CreationParams.Fullscreen || has_display_size)) if (SupportsNetWM && (CreationParams.Fullscreen || has_display_size))
{ {
Atom WMStateAtom = XInternAtom(display, "_NET_WM_STATE", true); Atom WMStateAtom = XInternAtom(display, "_NET_WM_STATE", true);
Atom WMStateAtom1 = None; Atom WMStateAtom1 = None;
@ -1077,10 +1123,15 @@ bool CIrrDeviceLinux::createWindow()
if (!changed) if (!changed)
{ {
os::Printer::log("Warning! Got timeout when changing window state", ELL_WARNING); os::Printer::log("Warning! Got timeout when changing window state", ELL_WARNING);
} }
if (NeedsGrabPointer)
{
grabPointer(true);
}
} }
if (!netWM && CreationParams.Fullscreen) if (!SupportsNetWM && CreationParams.Fullscreen)
{ {
XSetInputFocus(display, window, RevertToParent, CurrentTime); XSetInputFocus(display, window, RevertToParent, CurrentTime);
int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync, int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync,
@ -1178,7 +1229,7 @@ bool CIrrDeviceLinux::createWindow()
CreationParams.WindowSize.Width = Width; CreationParams.WindowSize.Width = Width;
CreationParams.WindowSize.Height = Height; CreationParams.WindowSize.Height = Height;
if (netWM == true) if (SupportsNetWM == true)
{ {
Atom opaque_region = XInternAtom(display, "_NET_WM_OPAQUE_REGION", true); Atom opaque_region = XInternAtom(display, "_NET_WM_OPAQUE_REGION", true);
@ -1493,7 +1544,7 @@ int CIrrDeviceLinux::getNumlockMask(Display* display)
EKEY_CODE CIrrDeviceLinux::getKeyCode(XEvent &event) EKEY_CODE CIrrDeviceLinux::getKeyCode(XEvent &event)
{ {
EKEY_CODE keyCode = (EKEY_CODE)0; int keyCode = 0;
SKeyMap mp; SKeyMap mp;
// First check for numpad keys // First check for numpad keys
@ -1515,30 +1566,25 @@ EKEY_CODE CIrrDeviceLinux::getKeyCode(XEvent &event)
const s32 idx = KeyMap.binary_search(mp); const s32 idx = KeyMap.binary_search(mp);
if (idx != -1) if (idx != -1)
{ {
keyCode = (EKEY_CODE)KeyMap[idx].Win32Key; keyCode = KeyMap[idx].Win32Key;
} }
if (keyCode == 0) if (keyCode == 0)
{ {
// Any value is better than none, that allows at least using the keys. // Any value is better than none, that allows at least using the keys.
// Worst case is that some keys will be identical, still better than _all_ // Worst case is that some keys will be identical, still better than _all_
// unknown keys being identical. // unknown keys being identical.
if ( !mp.X11Key ) if (mp.X11Key)
{ {
keyCode = (EKEY_CODE)event.xkey.keycode; keyCode = (int)IRR_KEY_CODES_COUNT + mp.X11Key;
os::Printer::log("No such X11Key, using event keycode", core::stringc(event.xkey.keycode).c_str(), ELL_INFORMATION);
}
else if (idx == -1)
{
keyCode = (EKEY_CODE)mp.X11Key;
os::Printer::log("EKEY_CODE not found, using orig. X11 keycode", core::stringc(mp.X11Key).c_str(), ELL_INFORMATION);
} }
else else
{ {
keyCode = (EKEY_CODE)mp.X11Key; keyCode = (int)IRR_KEY_CODES_COUNT + event.xkey.keycode;
os::Printer::log("EKEY_CODE is 0, using orig. X11 keycode", core::stringc(mp.X11Key).c_str(), ELL_INFORMATION);
} }
os::Printer::log("EKEY_CODE is 0, fallback keycode", core::stringc(keyCode).c_str(), ELL_INFORMATION);
} }
return keyCode; return (EKEY_CODE)keyCode;
} }
#endif #endif
@ -1619,10 +1665,18 @@ bool CIrrDeviceLinux::run()
break; break;
case FocusIn: case FocusIn:
if (NeedsGrabPointer)
{
grabPointer(true);
}
WindowHasFocus=true; WindowHasFocus=true;
break; break;
case FocusOut: case FocusOut:
if (NeedsGrabPointer)
{
grabPointer(false);
}
WindowHasFocus=false; WindowHasFocus=false;
break; break;
@ -2441,16 +2495,16 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_ISO_Level3_Shift, IRR_KEY_RMENU)); KeyMap.push_back(SKeyMap(XK_ISO_Level3_Shift, IRR_KEY_RMENU));
KeyMap.push_back(SKeyMap(XK_Menu, IRR_KEY_MENU)); KeyMap.push_back(SKeyMap(XK_Menu, IRR_KEY_MENU));
KeyMap.push_back(SKeyMap(XK_space, IRR_KEY_SPACE)); KeyMap.push_back(SKeyMap(XK_space, IRR_KEY_SPACE));
KeyMap.push_back(SKeyMap(XK_exclam, 0)); //? KeyMap.push_back(SKeyMap(XK_exclam, IRR_KEY_EXCLAM));
KeyMap.push_back(SKeyMap(XK_quotedbl, 0)); //? KeyMap.push_back(SKeyMap(XK_quotedbl, IRR_KEY_QUOTEDBL));
KeyMap.push_back(SKeyMap(XK_section, 0)); //? KeyMap.push_back(SKeyMap(XK_section, IRR_KEY_SECTION)); //?
KeyMap.push_back(SKeyMap(XK_numbersign, IRR_KEY_OEM_2)); KeyMap.push_back(SKeyMap(XK_numbersign, IRR_KEY_OEM_2));
KeyMap.push_back(SKeyMap(XK_dollar, 0)); //? KeyMap.push_back(SKeyMap(XK_dollar, IRR_KEY_DOLLAR));
KeyMap.push_back(SKeyMap(XK_percent, 0)); //? KeyMap.push_back(SKeyMap(XK_percent, 0)); //?
KeyMap.push_back(SKeyMap(XK_ampersand, 0)); //? KeyMap.push_back(SKeyMap(XK_ampersand, IRR_KEY_AMPERSAND));
KeyMap.push_back(SKeyMap(XK_apostrophe, IRR_KEY_OEM_7)); KeyMap.push_back(SKeyMap(XK_apostrophe, IRR_KEY_OEM_7));
KeyMap.push_back(SKeyMap(XK_parenleft, 0)); //? KeyMap.push_back(SKeyMap(XK_parenleft, IRR_KEY_PARENLEFT));
KeyMap.push_back(SKeyMap(XK_parenright, 0)); //? KeyMap.push_back(SKeyMap(XK_parenright, IRR_KEY_PARENRIGHT));
KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //? KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //?
KeyMap.push_back(SKeyMap(XK_plus, IRR_KEY_PLUS)); //? KeyMap.push_back(SKeyMap(XK_plus, IRR_KEY_PLUS)); //?
KeyMap.push_back(SKeyMap(XK_comma, IRR_KEY_COMMA)); //? KeyMap.push_back(SKeyMap(XK_comma, IRR_KEY_COMMA)); //?
@ -2467,14 +2521,14 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_7, IRR_KEY_7)); KeyMap.push_back(SKeyMap(XK_7, IRR_KEY_7));
KeyMap.push_back(SKeyMap(XK_8, IRR_KEY_8)); KeyMap.push_back(SKeyMap(XK_8, IRR_KEY_8));
KeyMap.push_back(SKeyMap(XK_9, IRR_KEY_9)); KeyMap.push_back(SKeyMap(XK_9, IRR_KEY_9));
KeyMap.push_back(SKeyMap(XK_colon, 0)); //? KeyMap.push_back(SKeyMap(XK_colon, IRR_KEY_COLON));
KeyMap.push_back(SKeyMap(XK_semicolon, IRR_KEY_OEM_1)); KeyMap.push_back(SKeyMap(XK_semicolon, IRR_KEY_OEM_1));
KeyMap.push_back(SKeyMap(XK_less, IRR_KEY_OEM_102)); KeyMap.push_back(SKeyMap(XK_less, IRR_KEY_OEM_102));
KeyMap.push_back(SKeyMap(XK_equal, IRR_KEY_PLUS)); KeyMap.push_back(SKeyMap(XK_equal, IRR_KEY_PLUS));
KeyMap.push_back(SKeyMap(XK_greater, 0)); //? KeyMap.push_back(SKeyMap(XK_greater, 0)); //?
KeyMap.push_back(SKeyMap(XK_question, 0)); //? KeyMap.push_back(SKeyMap(XK_question, 0)); //?
KeyMap.push_back(SKeyMap(XK_at, IRR_KEY_2)); //? KeyMap.push_back(SKeyMap(XK_at, IRR_KEY_2)); //?
KeyMap.push_back(SKeyMap(XK_mu, 0)); //? KeyMap.push_back(SKeyMap(XK_mu, IRR_KEY_MU)); //?
KeyMap.push_back(SKeyMap(XK_EuroSign, 0)); //? KeyMap.push_back(SKeyMap(XK_EuroSign, 0)); //?
KeyMap.push_back(SKeyMap(XK_A, IRR_KEY_A)); KeyMap.push_back(SKeyMap(XK_A, IRR_KEY_A));
KeyMap.push_back(SKeyMap(XK_B, IRR_KEY_B)); KeyMap.push_back(SKeyMap(XK_B, IRR_KEY_B));
@ -2542,6 +2596,12 @@ void CIrrDeviceLinux::createKeyMap()
KeyMap.push_back(SKeyMap(XK_udiaeresis, IRR_KEY_OEM_1)); KeyMap.push_back(SKeyMap(XK_udiaeresis, IRR_KEY_OEM_1));
KeyMap.push_back(SKeyMap(XK_Super_L, IRR_KEY_LWIN)); KeyMap.push_back(SKeyMap(XK_Super_L, IRR_KEY_LWIN));
KeyMap.push_back(SKeyMap(XK_Super_R, IRR_KEY_RWIN)); KeyMap.push_back(SKeyMap(XK_Super_R, IRR_KEY_RWIN));
KeyMap.push_back(SKeyMap(XK_agrave, IRR_KEY_AGRAVE));
KeyMap.push_back(SKeyMap(XK_ccedilla, IRR_KEY_CCEDILLA ));
KeyMap.push_back(SKeyMap(XK_eacute, IRR_KEY_EACUTE));
KeyMap.push_back(SKeyMap(XK_egrave, IRR_KEY_EGRAVE));
KeyMap.push_back(SKeyMap(XK_ugrave, IRR_KEY_UGRAVE));
KeyMap.push_back(SKeyMap(XK_twosuperior, IRR_KEY_TWOSUPERIOR));
KeyMap.sort(); KeyMap.sort();
#endif #endif

View File

@ -158,6 +158,7 @@ namespace irr
bool restoreResolution(); bool restoreResolution();
bool changeResolution(); bool changeResolution();
void grabPointer(bool grab);
#ifdef _IRR_COMPILE_WITH_X11_ #ifdef _IRR_COMPILE_WITH_X11_
bool createInputContext(); bool createInputContext();
@ -434,6 +435,8 @@ namespace irr
bool UseGLXWindow; bool UseGLXWindow;
bool ExternalWindow; bool ExternalWindow;
int AutorepeatSupport; int AutorepeatSupport;
bool SupportsNetWM;
bool NeedsGrabPointer;
struct SKeyMap struct SKeyMap
{ {

View File

@ -13,7 +13,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
OPTION(BUILD_SQUISH_WITH_OPENMP "Build with OpenMP." OFF) OPTION(BUILD_SQUISH_WITH_OPENMP "Build with OpenMP." OFF)
OPTION(BUILD_SQUISH_WITH_SSE2 "Build with SSE2." ON) if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") OR
(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64"))
OPTION(BUILD_SQUISH_WITH_SSE2 "Build with SSE2." OFF)
else()
OPTION(BUILD_SQUISH_WITH_SSE2 "Build with SSE2." ON)
endif()
OPTION(BUILD_SQUISH_WITH_ALTIVEC "Build with Altivec." OFF) OPTION(BUILD_SQUISH_WITH_ALTIVEC "Build with Altivec." OFF)
OPTION(BUILD_SHARED_LIBS "Build shared libraries." OFF) OPTION(BUILD_SHARED_LIBS "Build shared libraries." OFF)

View File

@ -68,8 +68,8 @@ void Achievement::load(const XMLNode *node)
*/ */
void Achievement::save(UTFWriter &out) void Achievement::save(UTFWriter &out)
{ {
out << L" <achievement id=\"" << m_id << L"\" " out << " <achievement id=\"" << m_id << "\" "
<< L"achieved=\"" << m_achieved << "\""; << "achieved=\"" << m_achieved << "\"";
if (isAchieved()) if (isAchieved())
{ {
out << "/>\n"; out << "/>\n";

View File

@ -94,14 +94,14 @@ void AchievementsStatus::add(Achievement *achievement)
*/ */
void AchievementsStatus::save(UTFWriter &out) void AchievementsStatus::save(UTFWriter &out)
{ {
out << L" <achievements online=\"" << m_online << L"\"> \n"; out << " <achievements online=\"" << m_online << "\"> \n";
std::map<uint32_t, Achievement*>::const_iterator i; std::map<uint32_t, Achievement*>::const_iterator i;
for(i = m_achievements.begin(); i != m_achievements.end(); i++) for(i = m_achievements.begin(); i != m_achievements.end(); i++)
{ {
if (i->second != NULL) if (i->second != NULL)
i->second->save(out); i->second->save(out);
} }
out << L" </achievements>\n"; out << " </achievements>\n";
} // save } // save
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -43,6 +43,7 @@ ChallengeData::ChallengeData(const std::string& filename)
m_gp_id = ""; m_gp_id = "";
m_version = 0; m_version = 0;
m_num_trophies = 0; m_num_trophies = 0;
m_is_unlock_list = false;
m_is_ghost_replay = false; m_is_ghost_replay = false;
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++) for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++)
@ -66,7 +67,7 @@ ChallengeData::ChallengeData(const std::string& filename)
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
setId(StringUtils::removeExtension(StringUtils::getBasename(filename))); setChallengeId(StringUtils::removeExtension(StringUtils::getBasename(filename)));
root->get("version", &m_version); root->get("version", &m_version);
// No need to get the rest of the data if this challenge // No need to get the rest of the data if this challenge
@ -79,7 +80,48 @@ ChallengeData::ChallengeData(const std::string& filename)
return; return;
} }
m_is_unlock_list = false;
const XMLNode* unlock_list_node = root->getNode("unlock_list");
if (unlock_list_node != NULL)
{
std::string list;
unlock_list_node->get("list", &list);
m_is_unlock_list = (list=="true");
}
std::vector<XMLNode*> unlocks;
root->getNodes("unlock", unlocks);
for(unsigned int i=0; i<unlocks.size(); i++)
{
std::string s;
if(unlocks[i]->get("kart", &s))
setUnlocks(s, ChallengeData::UNLOCK_KART);
else if(unlocks[i]->get("track", &s))
addUnlockTrackReward(s);
else if(unlocks[i]->get("gp", &s))
setUnlocks(s, ChallengeData::UNLOCK_GP);
else if(unlocks[i]->get("mode", &s))
setUnlocks(s, ChallengeData::UNLOCK_MODE);
else if(unlocks[i]->get("difficulty", &s))
setUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY);
else
{
Log::warn("ChallengeData", "Unknown unlock entry. Must be one of kart, track, gp, mode, difficulty.");
throw std::runtime_error("Unknown unlock entry");
}
}
const XMLNode* requirements_node = root->getNode("requirements");
if (requirements_node == NULL)
{
throw std::runtime_error("Challenge file " + filename +
" has no <requirements> node!");
}
requirements_node->get("trophies", &m_num_trophies);
//Don't check further if this is an unlock list
if(m_is_unlock_list)
return;
const XMLNode* mode_node = root->getNode("mode"); const XMLNode* mode_node = root->getNode("mode");
if (mode_node == NULL) if (mode_node == NULL)
@ -149,27 +191,19 @@ ChallengeData::ChallengeData(const std::string& filename)
} }
} }
const XMLNode* requirements_node = root->getNode("requirements");
if (requirements_node == NULL)
{
throw std::runtime_error("Challenge file " + filename +
" has no <requirements> node!");
}
requirements_node->get("trophies", &m_num_trophies);
const XMLNode* difficulties[RaceManager::DIFFICULTY_COUNT]; const XMLNode* difficulties[RaceManager::DIFFICULTY_COUNT];
difficulties[0] = root->getNode("easy"); difficulties[0] = root->getNode("easy");
difficulties[1] = root->getNode("medium"); difficulties[1] = root->getNode("medium");
difficulties[2] = root->getNode("hard"); difficulties[2] = root->getNode("hard");
difficulties[3] = root->getNode("best");
// Note that the challenges can only be done in three difficulties
if (difficulties[0] == NULL || difficulties[1] == NULL || if (difficulties[0] == NULL || difficulties[1] == NULL ||
difficulties[2] == NULL) difficulties[2] == NULL || difficulties[3] == NULL)
{ {
error("<easy> or <medium> or <hard>"); error("<easy> or <medium> or <hard> or <best>");
} }
for (int d=0; d<=RaceManager::DIFFICULTY_HARD; d++) for (int d=0; d<=RaceManager::DIFFICULTY_BEST; d++)
{ {
const XMLNode* karts_node = difficulties[d]->getNode("karts"); const XMLNode* karts_node = difficulties[d]->getNode("karts");
if (karts_node == NULL) error("<karts .../>"); if (karts_node == NULL) error("<karts .../>");
@ -229,28 +263,6 @@ ChallengeData::ChallengeData(const std::string& filename)
if (requirements_node->get("energy", &energy)) m_energy[d] = energy; if (requirements_node->get("energy", &energy)) m_energy[d] = energy;
} }
std::vector<XMLNode*> unlocks;
root->getNodes("unlock", unlocks);
for(unsigned int i=0; i<unlocks.size(); i++)
{
std::string s;
if(unlocks[i]->get("kart", &s))
setUnlocks(s, ChallengeData::UNLOCK_KART);
else if(unlocks[i]->get("track", &s))
addUnlockTrackReward(s);
else if(unlocks[i]->get("gp", &s))
setUnlocks(s, ChallengeData::UNLOCK_GP);
else if(unlocks[i]->get("mode", &s))
setUnlocks(s, ChallengeData::UNLOCK_MODE);
else if(unlocks[i]->get("difficulty", &s))
setUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY);
else
{
Log::warn("ChallengeData", "Unknown unlock entry. Must be one of kart, track, gp, mode, difficulty.");
throw std::runtime_error("Unknown unlock entry");
}
}
} // ChallengeData } // ChallengeData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -486,7 +498,7 @@ bool ChallengeData::isChallengeFulfilled() const
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Returns true if this GP challenge is fulfilled. /** Returns true if this GP challenge is fulfilled.
*/ */
bool ChallengeData::isGPFulfilled() const ChallengeData::GPLevel ChallengeData::isGPFulfilled() const
{ {
int d = race_manager->getDifficulty(); int d = race_manager->getDifficulty();
@ -496,14 +508,25 @@ bool ChallengeData::isGPFulfilled() const
race_manager->getMinorMode() != m_minor || race_manager->getMinorMode() != m_minor ||
race_manager->getGrandPrix().getId() != m_gp_id || race_manager->getGrandPrix().getId() != m_gp_id ||
race_manager->getNumberOfKarts() < (unsigned int)m_default_num_karts[d] || race_manager->getNumberOfKarts() < (unsigned int)m_default_num_karts[d] ||
race_manager->getNumPlayers() > 1) return false; race_manager->getNumPlayers() > 1) return GP_NONE;
// check if the player came first. // check if the player came first.
// rank == 0 if first, 1 if second, etc.
const int rank = race_manager->getLocalPlayerGPRank(0); const int rank = race_manager->getLocalPlayerGPRank(0);
if (rank != 0) return false; // In superior difficulty levels, losing a place means
// getting a cup of the inferior level rather than
return true; // nothing at all
int unlock_level = d - rank;
if (unlock_level == 3)
return GP_BEST;
if (unlock_level == 2)
return GP_HARD;
if (unlock_level == 1)
return GP_MEDIUM;
if (unlock_level == 0)
return GP_EASY;
return GP_NONE;
} // isGPFulfilled } // isGPFulfilled
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -641,4 +664,3 @@ void ChallengeData::addUnlockKartReward(const std::string &internal_name,
feature.m_user_name = user_name; feature.m_user_name = user_name;
m_feature.push_back(feature); m_feature.push_back(feature);
} // addUnlockKartReward } // addUnlockKartReward

View File

@ -44,6 +44,17 @@ public:
UNLOCK_KART, UNLOCK_KART,
UNLOCK_DIFFICULTY UNLOCK_DIFFICULTY
}; };
/** The level of completion of a GP challenge
*/
enum GPLevel
{
GP_NONE,
GP_EASY,
GP_MEDIUM,
GP_HARD,
GP_BEST
};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
class UnlockableFeature class UnlockableFeature
{ {
@ -95,6 +106,7 @@ private:
std::string m_filename; std::string m_filename;
/** Version number of the challenge. */ /** Version number of the challenge. */
int m_version; int m_version;
bool m_is_unlock_list;
bool m_is_ghost_replay; bool m_is_ghost_replay;
void setUnlocks(const std::string &id, void setUnlocks(const std::string &id,
@ -120,7 +132,7 @@ public:
virtual void check() const; virtual void check() const;
virtual bool isChallengeFulfilled() const; virtual bool isChallengeFulfilled() const;
virtual bool isGPFulfilled() const; virtual GPLevel isGPFulfilled() const;
void addUnlockTrackReward(const std::string &track_name); void addUnlockTrackReward(const std::string &track_name);
void addUnlockModeReward(const std::string &internal_mode_name, void addUnlockModeReward(const std::string &internal_mode_name,
const irr::core::stringw &user_mode_name); const irr::core::stringw &user_mode_name);
@ -142,11 +154,11 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the id of the challenge. */ /** Returns the id of the challenge. */
const std::string &getId() const { return m_id; } const std::string &getChallengeId() const { return m_id; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Sets the id of this challenge. */ /** Sets the id of this challenge. */
void setId(const std::string& s) { m_id = s; } void setChallengeId(const std::string& s) { m_id = s; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the track associated with this challenge. */ /** Returns the track associated with this challenge. */
@ -185,6 +197,9 @@ public:
/** Returns if this challenge is using ghost replay. */ /** Returns if this challenge is using ghost replay. */
bool isGhostReplay() const { return m_is_ghost_replay; } bool isGhostReplay() const { return m_is_ghost_replay; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns if this challenge is an unlock list. */
bool isUnlockList() const { return m_is_unlock_list; }
// ------------------------------------------------------------------------
/** Returns the challenge mode of this challenge. */ /** Returns the challenge mode of this challenge. */
ChallengeModeType getMode() const { return m_mode; } ChallengeModeType getMode() const { return m_mode; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -196,9 +211,9 @@ public:
const irr::core::stringw getChallengeDescription() const; const irr::core::stringw getChallengeDescription() const;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the minimum position the player must have in order to win. /** Returns the maximum position the player must have in order to win.
*/ */
int getPosition(RaceManager::Difficulty difficulty) const int getMaxPosition(RaceManager::Difficulty difficulty) const
{ {
return m_position[difficulty]; return m_position[difficulty];
} // getPosition } // getPosition

View File

@ -35,18 +35,19 @@
*/ */
void ChallengeStatus::load(const XMLNode* challenges_node) void ChallengeStatus::load(const XMLNode* challenges_node)
{ {
const XMLNode* node = challenges_node->getNode( m_data->getId() ); const XMLNode* node = challenges_node->getNode( m_data->getChallengeId() );
if(node == NULL) if(node == NULL)
{ {
Log::info("ChallengeStatus", "Couldn't find node <%s> in challenge list." Log::info("ChallengeStatus", "Couldn't find node <%s> in challenge list."
"(If this is the first time you play this is normal)\n", "(If this is the first time you play this is normal)\n",
m_data->getId().c_str()); m_data->getChallengeId().c_str());
return; return;
} }
m_state[0] = CH_INACTIVE; m_state[0] = CH_INACTIVE;
m_state[1] = CH_INACTIVE; m_state[1] = CH_INACTIVE;
m_state[2] = CH_INACTIVE; m_state[2] = CH_INACTIVE;
m_state[3] = CH_INACTIVE;
std::string solved; std::string solved;
if (node->get("solved", &solved)) if (node->get("solved", &solved))
@ -64,6 +65,13 @@ void ChallengeStatus::load(const XMLNode* challenges_node)
m_state[1] = CH_SOLVED; m_state[1] = CH_SOLVED;
m_state[2] = CH_SOLVED; m_state[2] = CH_SOLVED;
} }
else if (solved == "best")
{
m_state[0] = CH_SOLVED;
m_state[1] = CH_SOLVED;
m_state[2] = CH_SOLVED;
m_state[3] = CH_SOLVED;
}
} // if has 'solved' attribute } // if has 'solved' attribute
} // load } // load
@ -78,19 +86,33 @@ void ChallengeStatus::setSolved(RaceManager::Difficulty d)
{ {
m_state[curr] = CH_SOLVED; m_state[curr] = CH_SOLVED;
} }
} } // setSolved
// ------------------------------------------------------------------------
bool ChallengeStatus::isUnlockList()
{
return m_data->isUnlockList();
} // isUnlockList
// ------------------------------------------------------------------------
bool ChallengeStatus::isGrandPrix()
{
return m_data->isGrandPrix();
} // isUnlockList
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ChallengeStatus::save(UTFWriter& writer) void ChallengeStatus::save(UTFWriter& writer)
{ {
writer << L" <" << m_data->getId(); writer << " <" << m_data->getChallengeId();
if (isSolved(RaceManager::DIFFICULTY_HARD)) if (isSolved(RaceManager::DIFFICULTY_BEST))
writer << L" solved=\"hard\"/>\n"; writer << " solved=\"best\"/>\n";
else if (isSolved(RaceManager::DIFFICULTY_HARD))
writer << " solved=\"hard\"/>\n";
else if (isSolved(RaceManager::DIFFICULTY_MEDIUM)) else if (isSolved(RaceManager::DIFFICULTY_MEDIUM))
writer << L" solved=\"medium\"/>\n"; writer << " solved=\"medium\"/>\n";
else if (isSolved(RaceManager::DIFFICULTY_EASY)) else if (isSolved(RaceManager::DIFFICULTY_EASY))
writer << L" solved=\"easy\"/>\n"; writer << " solved=\"easy\"/>\n";
else else
writer << L" solved=\"none\"/>\n"; writer << " solved=\"none\"/>\n";
} // save } // save

View File

@ -57,6 +57,7 @@ private:
enum {CH_INACTIVE, // challenge not yet possible enum {CH_INACTIVE, // challenge not yet possible
CH_ACTIVE, // challenge possible, but not yet solved CH_ACTIVE, // challenge possible, but not yet solved
CH_SOLVED} // challenge was solved CH_SOLVED} // challenge was solved
m_state[RaceManager::DIFFICULTY_COUNT]; m_state[RaceManager::DIFFICULTY_COUNT];
/** Pointer to the original challenge data. */ /** Pointer to the original challenge data. */
@ -69,6 +70,7 @@ public:
m_state[RaceManager::DIFFICULTY_EASY] = CH_INACTIVE; m_state[RaceManager::DIFFICULTY_EASY] = CH_INACTIVE;
m_state[RaceManager::DIFFICULTY_MEDIUM] = CH_INACTIVE; m_state[RaceManager::DIFFICULTY_MEDIUM] = CH_INACTIVE;
m_state[RaceManager::DIFFICULTY_HARD] = CH_INACTIVE; m_state[RaceManager::DIFFICULTY_HARD] = CH_INACTIVE;
m_state[RaceManager::DIFFICULTY_BEST] = CH_INACTIVE;
} }
virtual ~ChallengeStatus() {}; virtual ~ChallengeStatus() {};
void load(const XMLNode* config); void load(const XMLNode* config);
@ -88,7 +90,7 @@ public:
bool isSolvedAtAnyDifficulty() const bool isSolvedAtAnyDifficulty() const
{ {
return m_state[0]==CH_SOLVED || m_state[1]==CH_SOLVED || return m_state[0]==CH_SOLVED || m_state[1]==CH_SOLVED ||
m_state[2]==CH_SOLVED; m_state[2]==CH_SOLVED || m_state[3]==CH_SOLVED;
} // isSolvedAtAnyDifficulty } // isSolvedAtAnyDifficulty
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** True if this challenge is active at the given difficulty. /** True if this challenge is active at the given difficulty.
@ -105,6 +107,13 @@ public:
m_state[d] = CH_ACTIVE; m_state[d] = CH_ACTIVE;
} // setActive } // setActive
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns if this challenge is only an unlock list */
bool isUnlockList();
// ------------------------------------------------------------------------
/** Returns if this challenge is a grand prix */
bool isGrandPrix();
// ------------------------------------------------------------------------
/** Returns a pointer to the actual Challenge data. /** Returns a pointer to the actual Challenge data.
*/ */
const ChallengeData* getData() const { return m_data; } const ChallengeData* getData() const { return m_data; }

View File

@ -30,12 +30,14 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
StoryModeStatus::StoryModeStatus(const XMLNode *node) StoryModeStatus::StoryModeStatus(const XMLNode *node)
{ {
m_points = 0; m_points = 0;
m_first_time = true; m_next_unlock_points = 0;
m_easy_challenges = 0; m_first_time = true;
m_medium_challenges = 0; m_easy_challenges = 0;
m_hard_challenges = 0; m_medium_challenges = 0;
m_current_challenge = NULL; m_hard_challenges = 0;
m_best_challenges = 0;
m_current_challenge = NULL;
// If there is saved data, load it // If there is saved data, load it
if(node) if(node)
@ -62,7 +64,7 @@ StoryModeStatus::~StoryModeStatus()
*/ */
void StoryModeStatus::addStatus(ChallengeStatus *cs) void StoryModeStatus::addStatus(ChallengeStatus *cs)
{ {
m_challenges_state[cs->getData()->getId()] = cs; m_challenges_state[cs->getData()->getChallengeId()] = cs;
} // addStatus } // addStatus
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -78,9 +80,11 @@ bool StoryModeStatus::isLocked(const std::string& feature)
void StoryModeStatus::computeActive() void StoryModeStatus::computeActive()
{ {
m_points = 0; m_points = 0;
m_next_unlock_points = 0;
m_easy_challenges = 0; m_easy_challenges = 0;
m_medium_challenges = 0; m_medium_challenges = 0;
m_hard_challenges = 0; m_hard_challenges = 0;
m_best_challenges = 0;
m_locked_features.clear(); // start afresh m_locked_features.clear(); // start afresh
@ -111,20 +115,32 @@ void StoryModeStatus::computeActive()
unlockFeature(i->second, RaceManager::DIFFICULTY_HARD, unlockFeature(i->second, RaceManager::DIFFICULTY_HARD,
/*save*/ false); /*save*/ false);
} }
if (i->second->isSolved(RaceManager::DIFFICULTY_BEST))
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
{ {
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]; unlockFeature(i->second, RaceManager::DIFFICULTY_BEST,
/*save*/ false);
}
int gp_factor = i->second->isGrandPrix() ? GP_FACTOR : 1;
if (i->second->isSolved(RaceManager::DIFFICULTY_BEST) && !i->second->isUnlockList())
{
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_BEST]*gp_factor;
m_best_challenges++;
}
else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD) && !i->second->isUnlockList())
{
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]*gp_factor;
m_hard_challenges++; m_hard_challenges++;
} }
else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM)) else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM) && !i->second->isUnlockList())
{ {
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]; m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]*gp_factor;
m_medium_challenges++; m_medium_challenges++;
} }
else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY)) else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY) && !i->second->isUnlockList())
{ {
m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]; m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]*gp_factor;
m_easy_challenges++; m_easy_challenges++;
} }
} }
@ -135,29 +151,40 @@ void StoryModeStatus::computeActive()
lockFeature(i->second); lockFeature(i->second);
} }
if (i->second->isSolved(RaceManager::DIFFICULTY_HARD)) if (i->second->isSolved(RaceManager::DIFFICULTY_BEST))
{ {
// challenge beaten at hardest, nothing more to do here // challenge beaten at hardest, nothing more to do here
continue; continue;
} }
else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD))
{
i->second->setActive(RaceManager::DIFFICULTY_BEST);
}
else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM)) else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM))
{ {
i->second->setActive(RaceManager::DIFFICULTY_BEST);
i->second->setActive(RaceManager::DIFFICULTY_HARD); i->second->setActive(RaceManager::DIFFICULTY_HARD);
} }
else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY)) else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY))
{ {
i->second->setActive(RaceManager::DIFFICULTY_BEST);
i->second->setActive(RaceManager::DIFFICULTY_HARD); i->second->setActive(RaceManager::DIFFICULTY_HARD);
i->second->setActive(RaceManager::DIFFICULTY_MEDIUM); i->second->setActive(RaceManager::DIFFICULTY_MEDIUM);
} }
else else
{ {
i->second->setActive(RaceManager::DIFFICULTY_BEST);
i->second->setActive(RaceManager::DIFFICULTY_HARD); i->second->setActive(RaceManager::DIFFICULTY_HARD);
i->second->setActive(RaceManager::DIFFICULTY_MEDIUM); i->second->setActive(RaceManager::DIFFICULTY_MEDIUM);
i->second->setActive(RaceManager::DIFFICULTY_EASY); i->second->setActive(RaceManager::DIFFICULTY_EASY);
} }
} // for i } // for i
// now we have the number of points. Actually lock the tracks // now we have the number of points.
unlockFeatureByList();
//Actually lock the tracks
for (i = m_challenges_state.begin(); i != m_challenges_state.end(); i++) for (i = m_challenges_state.begin(); i != m_challenges_state.end(); i++)
{ {
if (m_points < i->second->getData()->getNumTrophies()) if (m_points < i->second->getData()->getNumTrophies())
@ -173,12 +200,37 @@ void StoryModeStatus::computeActive()
} }
} }
} }
clearUnlocked();
} // computeActive } // computeActive
//-----------------------------------------------------------------------------
void StoryModeStatus::unlockFeatureByList()
{
// test if we have unlocked a feature requiring a certain number of points
std::map<std::string, ChallengeStatus*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if (i->second->isUnlockList())
{
if (i->second->isSolvedAtAnyDifficulty())
continue;
bool newly_solved = unlock_manager->unlockByPoints(m_points,i->second);
// Add to list of recently unlocked features
if(newly_solved)
m_unlocked_features.push_back(i->second->getData());
//Retrieve the smallest number of points for the next unlockable
if (i->second->getData()->getNumTrophies() > m_points && (m_next_unlock_points == 0
|| i->second->getData()->getNumTrophies() < m_next_unlock_points) )
m_next_unlock_points = i->second->getData()->getNumTrophies();
}
}
} //unlockFeatureByList
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void StoryModeStatus::lockFeature(ChallengeStatus *challenge_status) void StoryModeStatus::lockFeature(ChallengeStatus *challenge_status)
@ -216,8 +268,10 @@ void StoryModeStatus::unlockFeature(ChallengeStatus* c, RaceManager::Difficulty
m_locked_features.erase(p); m_locked_features.erase(p);
} }
// Add to list of recently unlocked features // Add to list of recently unlocked features if the challenge is newly completed
m_unlocked_features.push_back(c->getData()); if (!c->isSolvedAtAnyDifficulty())
m_unlocked_features.push_back(c->getData());
c->setSolved(d); // reset isActive flag c->setSolved(d); // reset isActive flag
// Save the new unlock information // Save the new unlock information
@ -250,6 +304,10 @@ void StoryModeStatus::raceFinished()
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge), unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge),
race_manager->getDifficulty()); race_manager->getDifficulty());
} // if isActive && challenge solved } // if isActive && challenge solved
//This updates the number of points.
//It then calls unlockFeatureByList which checks the specially unlocked features (by points, etc)
computeActive();
} // raceFinished } // raceFinished
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -259,11 +317,33 @@ void StoryModeStatus::raceFinished()
void StoryModeStatus::grandPrixFinished() void StoryModeStatus::grandPrixFinished()
{ {
if(m_current_challenge && if(m_current_challenge &&
m_current_challenge->isActive(race_manager->getDifficulty()) && m_current_challenge->isActive(race_manager->getDifficulty()) )
m_current_challenge->getData()->isGPFulfilled() )
{ {
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge), ChallengeData::GPLevel unlock_level = m_current_challenge->getData()->isGPFulfilled();
race_manager->getDifficulty());
RaceManager::Difficulty difficulty = RaceManager::DIFFICULTY_EASY;
switch (unlock_level)
{
case ChallengeData::GP_NONE:
race_manager->setCoinTarget(0);
return; //No cup unlocked
case ChallengeData::GP_EASY:
difficulty = RaceManager::DIFFICULTY_EASY;
break;
case ChallengeData::GP_MEDIUM:
difficulty = RaceManager::DIFFICULTY_MEDIUM;
break;
case ChallengeData::GP_HARD:
difficulty = RaceManager::DIFFICULTY_HARD;
break;
case ChallengeData::GP_BEST:
difficulty = RaceManager::DIFFICULTY_BEST;
break;
}
race_manager->setDifficulty(difficulty);
unlockFeature(const_cast<ChallengeStatus*>(m_current_challenge), difficulty);
} // if isActive && challenge solved } // if isActive && challenge solved
race_manager->setCoinTarget(0); race_manager->setCoinTarget(0);
@ -275,7 +355,7 @@ void StoryModeStatus::grandPrixFinished()
*/ */
void StoryModeStatus::save(UTFWriter &out) void StoryModeStatus::save(UTFWriter &out)
{ {
out << L" <story-mode first-time=\"" << m_first_time << L"\">\n"; out << " <story-mode first-time=\"" << m_first_time << L"\">\n";
std::map<std::string, ChallengeStatus*>::const_iterator i; std::map<std::string, ChallengeStatus*>::const_iterator i;
for(i = m_challenges_state.begin(); for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++) i != m_challenges_state.end(); i++)
@ -283,5 +363,5 @@ void StoryModeStatus::save(UTFWriter &out)
if (i->second != NULL) if (i->second != NULL)
i->second->save(out); i->second->save(out);
} }
out << L" </story-mode>\n"; out << " </story-mode>\n";
} // save } // save

View File

@ -19,6 +19,7 @@
#ifndef GAME_SLOT_HPP #ifndef GAME_SLOT_HPP
#define GAME_SLOT_HPP #define GAME_SLOT_HPP
#include "challenges/challenge_data.hpp"
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
#include <irrString.h> #include <irrString.h>
@ -33,7 +34,8 @@ class ChallengeStatus;
class UTFWriter; class UTFWriter;
class XMLNode; class XMLNode;
const int CHALLENGE_POINTS[] = { 8, 9, 10 }; const int CHALLENGE_POINTS[] = { 6, 7, 8, 10 };
const int GP_FACTOR = 3;
/** This class contains the progression through challenges for the story mode. /** This class contains the progression through challenges for the story mode.
* It maintains a list of all challenges in a mapping of challenge id to * It maintains a list of all challenges in a mapping of challenge id to
@ -60,6 +62,7 @@ private:
const ChallengeStatus *m_current_challenge; const ChallengeStatus *m_current_challenge;
int m_points; int m_points;
int m_next_unlock_points;
/** Set to false after the initial stuff (intro, select kart, etc.) */ /** Set to false after the initial stuff (intro, select kart, etc.) */
bool m_first_time; bool m_first_time;
@ -67,6 +70,7 @@ private:
int m_easy_challenges; int m_easy_challenges;
int m_medium_challenges; int m_medium_challenges;
int m_hard_challenges; int m_hard_challenges;
int m_best_challenges;
public: public:
@ -75,6 +79,7 @@ public:
void computeActive(); void computeActive();
bool isLocked (const std::string& feature); bool isLocked (const std::string& feature);
void unlockFeatureByList();
void lockFeature (ChallengeStatus *challenge); void lockFeature (ChallengeStatus *challenge);
void unlockFeature (ChallengeStatus* c, RaceManager::Difficulty d, void unlockFeature (ChallengeStatus* c, RaceManager::Difficulty d,
bool do_save=true); bool do_save=true);
@ -96,15 +101,21 @@ public:
/** Returns the number of points accumulated. */ /** Returns the number of points accumulated. */
int getPoints () const { return m_points; } int getPoints () const { return m_points; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the number of points needed by the next unlockable. 0 if none. */
int getNextUnlockPoints () const { return m_next_unlock_points; }
// ------------------------------------------------------------------------
/** Returns the number of fulfilled challenges at easy level. */ /** Returns the number of fulfilled challenges at easy level. */
int getNumEasyTrophies () const { return m_easy_challenges; } int getNumEasyTrophies () const { return m_easy_challenges; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/* Returns the number of fulfilled challenges at medium level. */ /* Returns the number of fulfilled challenges at medium level. */
int getNumMediumTrophies() const { return m_medium_challenges; } int getNumMediumTrophies() const { return m_medium_challenges; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the number of fulfilled challenges at har level. */ /** Returns the number of fulfilled challenges at hard level. */
int getNumHardTrophies () const { return m_hard_challenges; } int getNumHardTrophies () const { return m_hard_challenges; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the number of fulfilled challenges at best level. */
int getNumBestTrophies () const { return m_best_challenges; }
// ------------------------------------------------------------------------
/** Sets if this is the first time the intro is shown. */ /** Sets if this is the first time the intro is shown. */
void setFirstTime(bool ft) { m_first_time = ft; } void setFirstTime(bool ft) { m_first_time = ft; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -23,6 +23,7 @@
#include "audio/sfx_manager.hpp" #include "audio/sfx_manager.hpp"
#include "challenges/challenge_data.hpp" #include "challenges/challenge_data.hpp"
#include "challenges/challenge_status.hpp" #include "challenges/challenge_status.hpp"
#include "challenges/story_mode_status.hpp"
#include "config/player_manager.hpp" #include "config/player_manager.hpp"
#include "config/player_profile.hpp" #include "config/player_profile.hpp"
#include "config/user_config.hpp" #include "config/user_config.hpp"
@ -142,19 +143,30 @@ void UnlockManager::addOrFreeChallenge(ChallengeData *c)
{ {
if(isSupportedVersion(*c)) if(isSupportedVersion(*c))
{ {
m_all_challenges[c->getId()]=c; m_all_challenges[c->getChallengeId()]=c;
if (c->isUnlockList())
addListChallenge(c);
} }
else else
{ {
Log::warn("Challenge", "Challenge '%s' is not supported - ignored.", Log::warn("Challenge", "Challenge '%s' is not supported - ignored.",
c->getId().c_str()); c->getChallengeId().c_str());
delete c; delete c;
} }
} // addOrFreeChallenge } // addOrFreeChallenge
//-----------------------------------------------------------------------------
/** Add a challenge to the unlock challenges list
* \param c The challenge that is either stored or freed.
*/
void UnlockManager::addListChallenge(ChallengeData *c)
{
m_list_challenges[c->getChallengeId()]=c;
} // addListChallenge
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Reads a challenge from the given filename. The challenge will then either /** Reads a challenge from the given filename. The challenge will then either
* be stored, or (if the challenge version is not supported anymore * be stored, or (if the challenge version is not supported anymore, freed)
* \param filename Name of the challenge file to read. * \param filename Name of the challenge file to read.
*/ */
void UnlockManager::addChallenge(const std::string& filename) void UnlockManager::addChallenge(const std::string& filename)
@ -228,20 +240,25 @@ bool UnlockManager::isSupportedVersion(const ChallengeData &challenge)
{ {
// Test if challenge version number is in between minimum // Test if challenge version number is in between minimum
// and maximum supported version. // and maximum supported version.
return (challenge.getVersion()>=2 && challenge.getVersion()<=2); return (challenge.getVersion()>=3 && challenge.getVersion()<=3);
} // isSupportedVersion } // isSupportedVersion
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This functions finds what new tracks, GP and karts have been unlocked
*/
void UnlockManager::findWhatWasUnlocked(int points_before, int points_now, void UnlockManager::findWhatWasUnlocked(int points_before, int points_now,
std::vector<std::string>& tracks, std::vector<std::string>& tracks,
std::vector<std::string>& gps) std::vector<std::string>& gps,
std::vector<std::string>& karts,
std::vector<const ChallengeData*>& unlocked)
{ {
ChallengeData* c = NULL;
for (AllChallengesType::iterator it = m_all_challenges.begin(); for (AllChallengesType::iterator it = m_all_challenges.begin();
it != m_all_challenges.end(); it++) it != m_all_challenges.end(); it++)
{ {
ChallengeData* c = it->second; c = it->second;
if (c->getNumTrophies() > points_before && if (c->getNumTrophies() > points_before &&
c->getNumTrophies() <= points_now ) c->getNumTrophies() <= points_now )
{ {
@ -257,4 +274,36 @@ void UnlockManager::findWhatWasUnlocked(int points_before, int points_now,
} }
} }
} }
}
for (unsigned int n = 0; n < unlocked.size(); n++)
{
std::vector<ChallengeData::UnlockableFeature> features = unlocked[n]->getFeatures();
for (unsigned int i = 0; i < features.size(); i++)
{
if( features[i].m_type == ChallengeData::UNLOCK_KART )
karts.push_back(features[i].m_name);
}
}
//std::vector<const ChallengeData*>
// getRecentlyCompletedChallenges()
} // findWhatWasUnlocked
//-----------------------------------------------------------------------------
/** This functions sets as completed the "challenges" requiring a certain number
* of points, to unlock features.
* Returns true if the challenge has been completed
*/
bool UnlockManager::unlockByPoints(int points, ChallengeStatus* unlock_list)
{
//TODO : add support for other conditions (achievements...) for alternative unlock paths
if( unlock_list!=NULL && unlock_list->getData()->getNumTrophies() <= points)
{
unlock_list->setSolved(RaceManager::DIFFICULTY_BEST);
return true;
}
return false;
} // unlockByPoints
/* EOF */

View File

@ -44,12 +44,16 @@ private:
typedef std::map<std::string, ChallengeData*> AllChallengesType; typedef std::map<std::string, ChallengeData*> AllChallengesType;
AllChallengesType m_all_challenges; AllChallengesType m_all_challenges;
/* The challenges who don't have a race, only unlockables */
AllChallengesType m_list_challenges;
void readAllChallengesInDirs(const std::vector<std::string>* all_dirs); void readAllChallengesInDirs(const std::vector<std::string>* all_dirs);
public: public:
UnlockManager (); UnlockManager ();
~UnlockManager (); ~UnlockManager ();
void addOrFreeChallenge(ChallengeData *c); void addOrFreeChallenge(ChallengeData *c);
void addListChallenge(ChallengeData *c);
void addChallenge (const std::string& filename); void addChallenge (const std::string& filename);
const ChallengeData *getChallengeData(const std::string& id); const ChallengeData *getChallengeData(const std::string& id);
@ -61,7 +65,10 @@ public:
void findWhatWasUnlocked(int pointsBefore, int pointsNow, void findWhatWasUnlocked(int pointsBefore, int pointsNow,
std::vector<std::string>& tracks, std::vector<std::string>& tracks,
std::vector<std::string>& gps); std::vector<std::string>& gps,
std::vector<std::string>& karts,
std::vector<const ChallengeData*>& unlocked);
bool unlockByPoints(int points, ChallengeStatus* unlock_list);
StoryModeStatus *createStoryModeStatus(const XMLNode *node=NULL); StoryModeStatus *createStoryModeStatus(const XMLNode *node=NULL);

View File

@ -261,14 +261,14 @@ void PlayerManager::save()
std::string filename = file_manager->getUserConfigFile("players.xml"); std::string filename = file_manager->getUserConfigFile("players.xml");
try try
{ {
UTFWriter players_file(filename.c_str()); UTFWriter players_file(filename.c_str(), false);
players_file << L"<?xml version=\"1.0\"?>\n"; players_file << "<?xml version=\"1.0\"?>\n";
players_file << L"<players version=\"1\" >\n"; players_file << "<players version=\"1\" >\n";
if(m_current_player) if(m_current_player)
{ {
players_file << L" <current player=\"" players_file << " <current player=\""
<< StringUtils::xmlEncode(m_current_player->getName(true/*ignoreRTL*/)) << L"\"/>\n"; << StringUtils::xmlEncode(m_current_player->getName(true/*ignoreRTL*/)) << L"\"/>\n";
} }
@ -278,7 +278,7 @@ void PlayerManager::save()
if(!player->isGuestAccount()) if(!player->isGuestAccount())
player->save(players_file); player->save(players_file);
} }
players_file << L"</players>\n"; players_file << "</players>\n";
players_file.close(); players_file.close();
} }
catch (std::runtime_error& e) catch (std::runtime_error& e)

View File

@ -87,7 +87,7 @@ PlayerProfile::PlayerProfile(const XMLNode* node)
node->get("saved-session", &m_saved_session ); node->get("saved-session", &m_saved_session );
node->get("saved-user", &m_saved_user_id ); node->get("saved-user", &m_saved_user_id );
node->get("saved-token", &m_saved_token ); node->get("saved-token", &m_saved_token );
node->get("last-online-name", &m_last_online_name ); node->getAndDecode("last-online-name", &m_last_online_name );
node->get("last-was-online", &m_last_was_online ); node->get("last-was-online", &m_last_was_online );
node->get("remember-password", &m_remember_password); node->get("remember-password", &m_remember_password);
node->get("icon-filename", &m_icon_filename ); node->get("icon-filename", &m_icon_filename );
@ -200,21 +200,21 @@ const std::string PlayerProfile::getIconFilename() const
*/ */
void PlayerProfile::save(UTFWriter &out) void PlayerProfile::save(UTFWriter &out)
{ {
out << L" <player name=\"" << StringUtils::xmlEncode(m_local_name) out << " <player name=\"" << StringUtils::xmlEncode(m_local_name)
<< L"\" guest=\"" << m_is_guest_account << "\" guest=\"" << m_is_guest_account
<< L"\" use-frequency=\"" << m_use_frequency << L"\"\n"; << "\" use-frequency=\"" << m_use_frequency << "\"\n";
out << L" icon-filename=\"" << m_icon_filename << L"\"\n"; out << " icon-filename=\"" << m_icon_filename << "\"\n";
out << L" unique-id=\"" << m_unique_id out << " unique-id=\"" << m_unique_id
<< L"\" saved-session=\"" << m_saved_session << L"\"\n"; << "\" saved-session=\"" << m_saved_session << "\"\n";
out << L" saved-user=\"" << m_saved_user_id out << " saved-user=\"" << m_saved_user_id
<< L"\" saved-token=\"" << m_saved_token << L"\"\n"; << "\" saved-token=\"" << m_saved_token << "\"\n";
out << L" last-online-name=\"" << m_last_online_name out << " last-online-name=\"" << StringUtils::xmlEncode(m_last_online_name)
<< L"\" last-was-online=\"" << m_last_was_online << L"\"\n"; << "\" last-was-online=\"" << m_last_was_online << "\"\n";
out << L" remember-password=\"" << m_remember_password << L"\"\n"; out << " remember-password=\"" << m_remember_password << "\"\n";
out << L" default-kart-color=\"" << m_default_kart_color << L"\">\n"; out << " default-kart-color=\"" << m_default_kart_color << "\">\n";
{ {
if(m_story_mode_status) if(m_story_mode_status)
m_story_mode_status->save(out); m_story_mode_status->save(out);
@ -222,7 +222,7 @@ void PlayerProfile::save(UTFWriter &out)
if(m_achievements_status) if(m_achievements_status)
m_achievements_status->save(out); m_achievements_status->save(out);
} }
out << L" </player>\n"; out << " </player>\n";
} // save } // save
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -230,6 +230,8 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
unsigned int getPoints() const { return m_story_mode_status->getPoints(); } unsigned int getPoints() const { return m_story_mode_status->getPoints(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
unsigned int getNextUnlockPoints() const { return m_story_mode_status->getNextUnlockPoints(); }
// ------------------------------------------------------------------------
void setFirstTime(bool b) { m_story_mode_status->setFirstTime(b); } void setFirstTime(bool b) { m_story_mode_status->setFirstTime(b); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool isFirstTime() const { return m_story_mode_status->isFirstTime(); } bool isFirstTime() const { return m_story_mode_status->isFirstTime(); }
@ -263,7 +265,11 @@ public:
unsigned int getNumHardTrophies() const unsigned int getNumHardTrophies() const
{ {
return m_story_mode_status->getNumHardTrophies(); return m_story_mode_status->getNumHardTrophies();
} // getNumHardTropies } // getNumHardTrophies
unsigned int getNumBestTrophies() const
{
return m_story_mode_status->getNumBestTrophies();
} // getNumBestTrophies
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
AchievementsStatus* getAchievementsStatus() AchievementsStatus* getAchievementsStatus()
{ {

View File

@ -150,10 +150,13 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_leader_time_per_kart, "leader time-per-kart" ); CHECK_NEG(m_leader_time_per_kart, "leader time-per-kart" );
CHECK_NEG(m_penalty_ticks, "penalty-time" ); CHECK_NEG(m_penalty_ticks, "penalty-time" );
CHECK_NEG(m_max_display_news, "max-display-news" ); CHECK_NEG(m_max_display_news, "max-display-news" );
CHECK_NEG(m_replay_max_time, "replay max-time" ); CHECK_NEG(m_replay_max_frames, "replay max-frames" );
CHECK_NEG(m_replay_delta_angle, "replay delta-angle" ); CHECK_NEG(m_replay_delta_steering, "replay delta-steering" );
CHECK_NEG(m_replay_delta_pos2, "replay delta-position" ); CHECK_NEG(m_replay_delta_speed, "replay delta-speed " );
CHECK_NEG(m_replay_dt, "replay delta-t" ); CHECK_NEG(m_replay_dt, "replay delta-t" );
CHECK_NEG(m_minimap_size, "minimap size" );
CHECK_NEG(m_minimap_ai_icon, "minimap ai_icon" );
CHECK_NEG(m_minimap_player_icon, "minimap player_icon" );
CHECK_NEG(m_smooth_angle_limit, "physics smooth-angle-limit" ); CHECK_NEG(m_smooth_angle_limit, "physics smooth-angle-limit" );
CHECK_NEG(m_default_track_friction, "physics default-track-friction"); CHECK_NEG(m_default_track_friction, "physics default-track-friction");
CHECK_NEG(m_physics_fps, "physics fps" ); CHECK_NEG(m_physics_fps, "physics fps" );
@ -161,7 +164,6 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_default_moveable_friction, "physics default-moveable-friction"); CHECK_NEG(m_default_moveable_friction, "physics default-moveable-friction");
// Square distance to make distance checks cheaper (no sqrt) // Square distance to make distance checks cheaper (no sqrt)
m_replay_delta_pos2 *= m_replay_delta_pos2;
m_default_kart_properties->checkAllSet(filename); m_default_kart_properties->checkAllSet(filename);
} // load } // load
@ -192,10 +194,13 @@ void STKConfig::init_defaults()
m_min_server_version = -100; m_min_server_version = -100;
m_max_server_version = -100; m_max_server_version = -100;
m_max_display_news = -100; m_max_display_news = -100;
m_replay_max_time = -100; m_replay_max_frames = -100;
m_replay_delta_angle = -100; m_replay_delta_steering = -100;
m_replay_delta_pos2 = -100; m_replay_delta_speed = -100;
m_replay_dt = -100; m_replay_dt = -100;
m_minimap_size = -100;
m_minimap_ai_icon = -100;
m_minimap_player_icon = -100;
m_network_state_frequeny = -100; m_network_state_frequeny = -100;
m_title_music = NULL; m_title_music = NULL;
m_smooth_normals = false; m_smooth_normals = false;
@ -399,13 +404,20 @@ void STKConfig::getAllData(const XMLNode * root)
if(const XMLNode *replay_node = root->getNode("replay")) if(const XMLNode *replay_node = root->getNode("replay"))
{ {
replay_node->get("delta-angle", &m_replay_delta_angle); replay_node->get("delta-steering", &m_replay_delta_steering);
replay_node->get("delta-pos", &m_replay_delta_pos2 ); replay_node->get("delta-speed", &m_replay_delta_speed );
replay_node->get("delta-t", &m_replay_dt ); replay_node->get("delta-t", &m_replay_dt );
replay_node->get("max-time", &m_replay_max_time ); replay_node->get("max-frames", &m_replay_max_frames );
} }
if(const XMLNode *replay_node = root->getNode("minimap"))
{
replay_node->get("size", &m_minimap_size );
replay_node->get("ai-icon", &m_minimap_ai_icon );
replay_node->get("player-icon", &m_minimap_player_icon );
}
if (const XMLNode *fonts_list = root->getNode("fonts-list")) if (const XMLNode *fonts_list = root->getNode("fonts-list"))
{ {
fonts_list->get("normal-ttf", &m_normal_ttf); fonts_list->get("normal-ttf", &m_normal_ttf);

View File

@ -149,19 +149,26 @@ public:
/** Filename of the title music to play.*/ /** Filename of the title music to play.*/
MusicInformation *m_title_music; MusicInformation *m_title_music;
/** Maximum time of a replay. */ /** Maximum number of transform events of a replay. */
int m_replay_max_time; int m_replay_max_frames;
/** Minimum time between consecutive saved tranform events. */ /** Maximum time between consecutive saved tranform events. */
float m_replay_dt; float m_replay_dt;
/** Maximum difference between interpolated and actual position. If the /** If the speed difference with the last transform event
* difference is larger than this, a new event is generated. */ * is larger than this, a new event is generated. */
float m_replay_delta_pos2; float m_replay_delta_speed;
/** A heading difference of more than that will trigger a new event to /** A steering difference of more than that will trigger a new event to
* be generated. */ * be generated. */
float m_replay_delta_angle; float m_replay_delta_steering;
/** The minimap size */
float m_minimap_size;
/* The size of icons for AIs and human players, respectively */
float m_minimap_ai_icon;
float m_minimap_player_icon;
/** The field of view for 1, 2, 3, 4 player split screen. */ /** The field of view for 1, 2, 3, 4 player split screen. */
float m_camera_fov[MAX_PLAYER_COUNT]; float m_camera_fov[MAX_PLAYER_COUNT];

View File

@ -715,11 +715,28 @@ namespace UserConfigParams
&m_network_group, "Enable chatting in networking lobby, if off than " &m_network_group, "Enable chatting in networking lobby, if off than "
"no chat message will be displayed from any players.")); "no chat message will be displayed from any players."));
PARAM_PREFIX FloatUserConfigParam m_voting_timeout PARAM_PREFIX FloatUserConfigParam m_voting_timeout
PARAM_DEFAULT(FloatUserConfigParam(10.0f, "voting-timeout", PARAM_DEFAULT(FloatUserConfigParam(20.0f, "voting-timeout",
&m_network_group, "Timeout in seconds for voting tracks in server.")); &m_network_group, "Timeout in seconds for voting tracks in server."));
PARAM_PREFIX FloatUserConfigParam m_validation_timeout
PARAM_DEFAULT(FloatUserConfigParam(20.0f, "validation-timeout",
&m_network_group, "Timeout in seconds for validation of clients."));
PARAM_PREFIX IntUserConfigParam m_server_max_players PARAM_PREFIX IntUserConfigParam m_server_max_players
PARAM_DEFAULT(IntUserConfigParam(12, "server_max_players", PARAM_DEFAULT(IntUserConfigParam(12, "server_max_players",
&m_network_group, "Maximum number of players on the server.")); &m_network_group, "Maximum number of players on the server."));
PARAM_PREFIX BoolUserConfigParam m_firewalled_server
PARAM_DEFAULT(BoolUserConfigParam(true, "firewalled-server",
&m_network_group, "Disable it to turn off all stun related code "
"in server, for official server hosting use only."));
PARAM_PREFIX FloatUserConfigParam m_start_game_counter
PARAM_DEFAULT(FloatUserConfigParam(30.0f, "start-game-counter",
&m_network_group, "Time to wait before entering kart selection screen "
"if satisfied start-game-threshold below for owner less or ranked "
"server."));
PARAM_PREFIX FloatUserConfigParam m_start_game_threshold
PARAM_DEFAULT(FloatUserConfigParam(0.7f, "start-game-threshold",
&m_network_group, "Only auto start kart selection when number of "
"connected player is larger than max player * this value, for "
"owner less or ranked server, after start-game-counter."));
PARAM_PREFIX StringToUIntUserConfigParam m_server_ban_list PARAM_PREFIX StringToUIntUserConfigParam m_server_ban_list
PARAM_DEFAULT(StringToUIntUserConfigParam("server_ban_list", PARAM_DEFAULT(StringToUIntUserConfigParam("server_ban_list",

View File

@ -44,6 +44,7 @@ void CentralVideoSettings::init()
hasSSBO = false; hasSSBO = false;
hasImageLoadStore = false; hasImageLoadStore = false;
hasTextureCompression = false; hasTextureCompression = false;
hasTextureCompressionSRGB = false;
hasUBO = false; hasUBO = false;
hasExplicitAttribLocation = false; hasExplicitAttribLocation = false;
hasGS = false; hasGS = false;
@ -53,19 +54,12 @@ void CentralVideoSettings::init()
hasSamplerObjects = false; hasSamplerObjects = false;
hasVertexType2101010Rev = false; hasVertexType2101010Rev = false;
hasInstancedArrays = false; hasInstancedArrays = false;
#if defined(USE_GLES2)
hasBGRA = false; hasBGRA = false;
hasColorBufferFloat = false; hasColorBufferFloat = false;
#endif
m_need_vertex_id_workaround = false; m_need_vertex_id_workaround = false;
// Call to glGetIntegerv should not be made if --no-graphics is used // Call to glGetIntegerv should not be made if --no-graphics is used
if (!ProfileWorld::isNoGraphics()) if (!ProfileWorld::isNoGraphics())
{
}
if (!ProfileWorld::isNoGraphics())
{ {
glGetIntegerv(GL_MAJOR_VERSION, &m_gl_major_version); glGetIntegerv(GL_MAJOR_VERSION, &m_gl_major_version);
glGetIntegerv(GL_MINOR_VERSION, &m_gl_minor_version); glGetIntegerv(GL_MINOR_VERSION, &m_gl_minor_version);
@ -193,6 +187,10 @@ void CentralVideoSettings::init()
m_supports_sp = isARBInstancedArraysUsable() && m_supports_sp = isARBInstancedArraysUsable() &&
isARBVertexType2101010RevUsable() && isARBSamplerObjectsUsable() && isARBVertexType2101010RevUsable() && isARBSamplerObjectsUsable() &&
isARBExplicitAttribLocationUsable(); isARBExplicitAttribLocationUsable();
hasTextureCompressionSRGB = true;
hasBGRA = true;
hasColorBufferFloat = true;
#else #else
if (m_glsl == true) if (m_glsl == true)
@ -202,6 +200,7 @@ void CentralVideoSettings::init()
hasSamplerObjects = true; hasSamplerObjects = true;
hasVertexType2101010Rev = true; hasVertexType2101010Rev = true;
hasInstancedArrays = true; hasInstancedArrays = true;
hasPixelBufferObject = true;
} }
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXPLICIT_ATTRIB_LOCATION) && if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXPLICIT_ATTRIB_LOCATION) &&
@ -232,6 +231,22 @@ void CentralVideoSettings::init()
hasColorBufferFloat = true; hasColorBufferFloat = true;
Log::info("GLDriver", "EXT Color Buffer Float Present"); Log::info("GLDriver", "EXT Color Buffer Float Present");
} }
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXT_TEXTURE_COMPRESSION_S3TC) &&
(hasGLExtension("GL_EXT_texture_compression_s3tc") ||
hasGLExtension("GL_ANGLE_texture_compression_dxt5")))
{
hasTextureCompression = true;
Log::info("GLDriver", "EXT Texture Compression S3TC Present");
}
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXT_TEXTURE_COMPRESSION_S3TC) &&
(hasGLExtension("GL_EXT_texture_compression_s3tc_srgb") ||
hasGLExtension("GL_NV_sRGB_formats")))
{
hasTextureCompressionSRGB = true;
Log::info("GLDriver", "EXT Texture Compression S3TC sRGB Present");
}
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_VERTEX_ID_WORKING)) if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_VERTEX_ID_WORKING))
{ {
@ -315,6 +330,11 @@ bool CentralVideoSettings::isEXTTextureCompressionS3TCUsable() const
return hasTextureCompression; return hasTextureCompression;
} }
bool CentralVideoSettings::isEXTTextureCompressionS3TCSRGBUsable() const
{
return hasTextureCompression && hasTextureCompressionSRGB;
}
bool CentralVideoSettings::isARBBufferStorageUsable() const bool CentralVideoSettings::isARBBufferStorageUsable() const
{ {
@ -361,7 +381,6 @@ bool CentralVideoSettings::isEXTTextureFilterAnisotropicUsable() const
return hasTextureFilterAnisotropic; return hasTextureFilterAnisotropic;
} }
#if defined(USE_GLES2)
bool CentralVideoSettings::isEXTTextureFormatBGRA8888Usable() const bool CentralVideoSettings::isEXTTextureFormatBGRA8888Usable() const
{ {
return hasBGRA; return hasBGRA;
@ -371,7 +390,6 @@ bool CentralVideoSettings::isEXTColorBufferFloatUsable() const
{ {
return hasColorBufferFloat; return hasColorBufferFloat;
} }
#endif
bool CentralVideoSettings::supportsComputeShadersFiltering() const bool CentralVideoSettings::supportsComputeShadersFiltering() const
{ {

View File

@ -36,6 +36,7 @@ private:
bool hasExplicitAttribLocation; bool hasExplicitAttribLocation;
bool hasGS; bool hasGS;
bool hasTextureCompression; bool hasTextureCompression;
bool hasTextureCompressionSRGB;
bool hasAtomics; bool hasAtomics;
bool hasSSBO; bool hasSSBO;
bool hasImageLoadStore; bool hasImageLoadStore;
@ -45,12 +46,8 @@ private:
bool hasSamplerObjects; bool hasSamplerObjects;
bool hasVertexType2101010Rev; bool hasVertexType2101010Rev;
bool hasInstancedArrays; bool hasInstancedArrays;
#if defined(USE_GLES2)
bool hasBGRA; bool hasBGRA;
bool hasColorBufferFloat; bool hasColorBufferFloat;
#endif
bool m_need_vertex_id_workaround; bool m_need_vertex_id_workaround;
public: public:
static bool m_supports_sp; static bool m_supports_sp;
@ -65,6 +62,7 @@ public:
// Extension is available and safe to use // Extension is available and safe to use
bool isARBUniformBufferObjectUsable() const; bool isARBUniformBufferObjectUsable() const;
bool isEXTTextureCompressionS3TCUsable() const; bool isEXTTextureCompressionS3TCUsable() const;
bool isEXTTextureCompressionS3TCSRGBUsable() const;
bool isARBTextureViewUsable() const; bool isARBTextureViewUsable() const;
bool isARBGeometryShadersUsable() const; bool isARBGeometryShadersUsable() const;
bool isARBTextureStorageUsable() const; bool isARBTextureStorageUsable() const;
@ -81,11 +79,8 @@ public:
bool isARBSamplerObjectsUsable() const; bool isARBSamplerObjectsUsable() const;
bool isARBVertexType2101010RevUsable() const; bool isARBVertexType2101010RevUsable() const;
bool isARBInstancedArraysUsable() const; bool isARBInstancedArraysUsable() const;
#if defined(USE_GLES2)
bool isEXTTextureFormatBGRA8888Usable() const; bool isEXTTextureFormatBGRA8888Usable() const;
bool isEXTColorBufferFloatUsable() const; bool isEXTColorBufferFloatUsable() const;
#endif
// Are all required extensions available for feature support // Are all required extensions available for feature support
bool supportsComputeShadersFiltering() const; bool supportsComputeShadersFiltering() const;

View File

@ -62,6 +62,12 @@ extern "C" {
#define GL_BGRA 0x80E1 #define GL_BGRA 0x80E1
#define GL_BGR 0x80E0 #define GL_BGR 0x80E0
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE #define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
#endif
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
#endif #endif
#else #else

View File

@ -62,6 +62,7 @@
#include "physics/physics.hpp" #include "physics/physics.hpp"
#include "scriptengine/property_animator.hpp" #include "scriptengine/property_animator.hpp"
#include "states_screens/dialogs/confirm_resolution_dialog.hpp" #include "states_screens/dialogs/confirm_resolution_dialog.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/state_manager.hpp" #include "states_screens/state_manager.hpp"
#include "tracks/track_manager.hpp" #include "tracks/track_manager.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
@ -615,6 +616,7 @@ void IrrDriver::initDevice()
(int x, int y, int w, int h, unsigned int f, unsigned int t, void* d) (int x, int y, int w, int h, unsigned int f, unsigned int t, void* d)
{ glReadPixels(x, y, w, h, f, t, d); }); { glReadPixels(x, y, w, h, f, t, d); });
#ifndef USE_GLES2
ogrRegPBOFunctions([](int n, unsigned int* b) { glGenBuffers(n, b); }, ogrRegPBOFunctions([](int n, unsigned int* b) { glGenBuffers(n, b); },
[](unsigned int t, unsigned int b) { glBindBuffer(t, b); }, [](unsigned int t, unsigned int b) { glBindBuffer(t, b); },
[](unsigned int t, ptrdiff_t s, const void* d, unsigned int u) [](unsigned int t, ptrdiff_t s, const void* d, unsigned int u)
@ -622,6 +624,16 @@ void IrrDriver::initDevice()
[](int n, const unsigned int* b) { glDeleteBuffers(n, b); }, [](int n, const unsigned int* b) { glDeleteBuffers(n, b); },
[](unsigned int t, unsigned int a) { return glMapBuffer(t, a); }, [](unsigned int t, unsigned int a) { return glMapBuffer(t, a); },
[](unsigned int t) { return glUnmapBuffer(t); }); [](unsigned int t) { return glUnmapBuffer(t); });
#else
ogrRegPBOFunctionsRange([](int n, unsigned int* b) { glGenBuffers(n, b); },
[](unsigned int t, unsigned int b) { glBindBuffer(t, b); },
[](unsigned int t, ptrdiff_t s, const void* d, unsigned int u)
{ glBufferData(t, s, d, u); },
[](int n, const unsigned int* b) { glDeleteBuffers(n, b); },
[](unsigned int t, ptrdiff_t o, ptrdiff_t l, unsigned int a)
{ return glMapBufferRange(t, o, l, a); },
[](unsigned int t) { return glUnmapBuffer(t); });
#endif
#endif #endif
@ -728,6 +740,13 @@ void IrrDriver::setMaxTextureSize()
att.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(max, max)); att.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(max, max));
} // setMaxTextureSize } // setMaxTextureSize
// ----------------------------------------------------------------------------
void IrrDriver::unsetMaxTextureSize()
{
io::IAttributes &att = m_video_driver->getNonConstDriverAttributes();
att.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(2048, 2048));
} // unsetMaxTextureSize
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void IrrDriver::cleanSunInterposer() void IrrDriver::cleanSunInterposer()
{ {
@ -1715,9 +1734,9 @@ void IrrDriver::displayFPS()
no_trust--; no_trust--;
static video::SColor fpsColor = video::SColor(255, 0, 0, 0); static video::SColor fpsColor = video::SColor(255, 0, 0, 0);
font->draw( L"FPS: ...", core::rect< s32 >(100,0,400,50), fpsColor, font->draw(StringUtils::insertValues (L"FPS: ... Ping: %dms",
false ); NetworkingLobby::getInstance()->getServerPing()),
core::rect< s32 >(100,0,400,50), fpsColor, false);
return; return;
} }
@ -1738,22 +1757,26 @@ void IrrDriver::displayFPS()
{ {
fps_string = StringUtils::insertValues fps_string = StringUtils::insertValues
(L"FPS: %d/%d/%d - PolyCount: %d Solid, " (L"FPS: %d/%d/%d - PolyCount: %d Solid, "
"%d Shadows - LightDist : %d, Total skinning joints: %d", "%d Shadows - LightDist : %d, Total skinning joints: %d, "
"Ping: %dms",
min, fps, max, SP::sp_solid_poly_count, min, fps, max, SP::sp_solid_poly_count,
SP::sp_shadow_poly_count, m_last_light_bucket_distance, SP::sp_shadow_poly_count, m_last_light_bucket_distance,
m_skinning_joint); m_skinning_joint,
NetworkingLobby::getInstance()->getServerPing());
} }
else else
{ {
if (CVS->isGLSL()) if (CVS->isGLSL())
{ {
fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, fps_string = _("FPS: %d/%d/%d - %d KTris, Ping: %dms", min, fps,
SP::sp_solid_poly_count / 1000); max, SP::sp_solid_poly_count / 1000,
NetworkingLobby::getInstance()->getServerPing());
} }
else else
{ {
fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, fps_string = _("FPS: %d/%d/%d - %d KTris, Ping: %dms", min, fps,
(int)roundf(kilotris)); max, (int)roundf(kilotris),
NetworkingLobby::getInstance()->getServerPing());
} }
} }
@ -1944,6 +1967,12 @@ void IrrDriver::setRecording(bool val)
{ {
ogrStopCapture(); ogrStopCapture();
} }
#else
Log::error("Recorder", "Recording unavailable, STK was compiled without "
"recording support. Please re-compile STK with libopenglrecorder "
"to enable recording. If you got SuperTuxKart from your distribution's "
"repositories, please use the official binaries, or contact your "
"distributions's package mantainers.");
#endif #endif
} // setRecording } // setRecording

View File

@ -197,6 +197,7 @@ public:
void initDevice(); void initDevice();
void reset(); void reset();
void setMaxTextureSize(); void setMaxTextureSize();
void unsetMaxTextureSize();
void getOpenGLData(std::string *vendor, std::string *renderer, void getOpenGLData(std::string *vendor, std::string *renderer,
std::string *version); std::string *version);

View File

@ -92,7 +92,6 @@ RTT::RTT(unsigned int width, unsigned int height, float rtt_scale,
GLint diffuse_specular_internal_format = GL_R11F_G11F_B10F; GLint diffuse_specular_internal_format = GL_R11F_G11F_B10F;
GLint type = GL_FLOAT; GLint type = GL_FLOAT;
#if defined(USE_GLES2)
if (!CVS->isEXTColorBufferFloatUsable()) if (!CVS->isEXTColorBufferFloatUsable())
{ {
rgba_internal_format = GL_RGBA8; rgba_internal_format = GL_RGBA8;
@ -104,7 +103,7 @@ RTT::RTT(unsigned int width, unsigned int height, float rtt_scale,
diffuse_specular_internal_format = GL_RGBA8; diffuse_specular_internal_format = GL_RGBA8;
type = GL_UNSIGNED_BYTE; type = GL_UNSIGNED_BYTE;
} }
#endif
if (!CVS->isDeferredEnabled()) if (!CVS->isDeferredEnabled())
{ {
// RTT is used in only deferred shading which need hdr framebuffer // RTT is used in only deferred shading which need hdr framebuffer

View File

@ -123,10 +123,8 @@ void ShaderBasedRenderer::renderSkybox(const scene::ICameraSceneNode *camera) co
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ShaderBasedRenderer::renderSSAO() const void ShaderBasedRenderer::renderSSAO() const
{ {
#if defined(USE_GLES2)
if (!CVS->isEXTColorBufferFloatUsable()) if (!CVS->isEXTColorBufferFloatUsable())
return; return;
#endif
m_rtts->getFBO(FBO_SSAO).bind(); m_rtts->getFBO(FBO_SSAO).bind();
glClearColor(1., 1., 1., 1.); glClearColor(1., 1., 1., 1.);

View File

@ -421,6 +421,8 @@ void SPMeshBuffer::enableTextureMatrix(unsigned mat_id)
assert(mat_id < m_stk_material.size()); assert(mat_id < m_stk_material.size());
// Make the 31 bit in normal to be 1 // Make the 31 bit in normal to be 1
uploadGLMesh(); uploadGLMesh();
if (m_vbo == 0 || m_ibo == 0)
return;
auto& ret = m_stk_material[mat_id]; auto& ret = m_stk_material[mat_id];
glBindBuffer(GL_ARRAY_BUFFER, m_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
std::set<uint16_t> used_vertices; std::set<uint16_t> used_vertices;

View File

@ -29,14 +29,14 @@
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
#include <squish.h> #include <squish.h>
static_assert(squish::kColourClusterFit == (1 << 5), "Wrong header"); static_assert(squish::kColourClusterFit == (1 << 5), "Wrong header");
static_assert(squish::kColourRangeFit == (1 << 6), "Wrong header"); static_assert(squish::kColourRangeFit == (1 << 6), "Wrong header");
static_assert(squish::kColourIterativeClusterFit == (1 << 8), "Wrong header"); static_assert(squish::kColourIterativeClusterFit == (1 << 8), "Wrong header");
#endif #endif
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
extern "C" extern "C"
{ {
#include <mipmap/img.h> #include <mipmap/img.h>
@ -46,7 +46,7 @@ extern "C"
#include <numeric> #include <numeric>
#if !defined(USE_GLES2) #if !defined(ANDROID)
static const uint8_t CACHE_VERSION = 1; static const uint8_t CACHE_VERSION = 1;
#endif #endif
@ -68,18 +68,26 @@ SPTexture::SPTexture(const std::string& path, Material* m, bool undo_srgb,
return; return;
} }
std::string cache_subdir = "hd/"; std::string cache_subdir = "hd";
if ((UserConfigParams::m_high_definition_textures & 0x01) == 0x01) if ((UserConfigParams::m_high_definition_textures & 0x01) == 0x01)
{ {
cache_subdir = "hd/"; cache_subdir = "hd";
} }
else else
{ {
cache_subdir = StringUtils::insertValues("resized_%i/", cache_subdir = StringUtils::insertValues("resized_%i",
(int)UserConfigParams::m_max_texture_size); (int)UserConfigParams::m_max_texture_size);
} }
#ifdef USE_GLES2
if (m_undo_srgb && !CVS->isEXTTextureCompressionS3TCSRGBUsable())
{
cache_subdir += "-linear";
}
#endif
m_cache_directory = file_manager->getCachedTexturesDir() + m_cache_directory = file_manager->getCachedTexturesDir() +
cache_subdir + container_id; cache_subdir + "/" + container_id;
file_manager->checkAndCreateDirectoryP(m_cache_directory); file_manager->checkAndCreateDirectoryP(m_cache_directory);
#endif #endif
@ -204,7 +212,11 @@ std::shared_ptr<video::IImage> SPTexture::getTextureImage() const
#ifndef USE_GLES2 #ifndef USE_GLES2
} }
#endif #endif
if (m_undo_srgb && !use_tex_compress)
bool force_undo_srgb = use_tex_compress &&
!CVS->isEXTTextureCompressionS3TCSRGBUsable();
if (m_undo_srgb && (!use_tex_compress || force_undo_srgb))
{ {
data[i * 4] = srgb255ToLinear(data[i * 4]); data[i * 4] = srgb255ToLinear(data[i * 4]);
data[i * 4 + 1] = srgb255ToLinear(data[i * 4 + 1]); data[i * 4 + 1] = srgb255ToLinear(data[i * 4 + 1]);
@ -221,9 +233,9 @@ bool SPTexture::compressedTexImage2d(std::shared_ptr<video::IImage> texture,
<core::dimension2du, unsigned> >& <core::dimension2du, unsigned> >&
mipmap_sizes) mipmap_sizes)
{ {
#if !defined(SERVER_ONLY) && !defined(USE_GLES2) #if !defined(SERVER_ONLY) && !defined(ANDROID)
unsigned format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; unsigned format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
if (m_undo_srgb) if (m_undo_srgb && CVS->isEXTTextureCompressionS3TCSRGBUsable())
{ {
format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
} }
@ -319,7 +331,7 @@ bool SPTexture::saveCompressedTexture(std::shared_ptr<video::IImage> texture,
<core::dimension2du, unsigned> >& sizes, <core::dimension2du, unsigned> >& sizes,
const std::string& cache_location) const std::string& cache_location)
{ {
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !defined(SERVER_ONLY) && !defined(ANDROID)
const unsigned total_size = std::accumulate(sizes.begin(), sizes.end(), 0, const unsigned total_size = std::accumulate(sizes.begin(), sizes.end(), 0,
[] (const unsigned int previous, const std::pair [] (const unsigned int previous, const std::pair
<core::dimension2du, unsigned>& cur_sizes) <core::dimension2du, unsigned>& cur_sizes)
@ -384,7 +396,7 @@ std::shared_ptr<video::IImage> SPTexture::getTextureCache(const std::string& p,
std::vector<std::pair<core::dimension2du, unsigned> >* sizes) std::vector<std::pair<core::dimension2du, unsigned> >* sizes)
{ {
std::shared_ptr<video::IImage> cache; std::shared_ptr<video::IImage> cache;
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
io::IReadFile* file = irr::io::createReadFile(p.c_str()); io::IReadFile* file = irr::io::createReadFile(p.c_str());
if (file == NULL) if (file == NULL)
{ {
@ -444,6 +456,8 @@ bool SPTexture::threadedLoad()
std::shared_ptr<video::IImage> image = getTextureImage(); std::shared_ptr<video::IImage> image = getTextureImage();
if (!image) if (!image)
{ {
m_width.store(2);
m_height.store(2);
return true; return true;
} }
std::shared_ptr<video::IImage> mask = getMask(image->getDimension()); std::shared_ptr<video::IImage> mask = getMask(image->getDimension());
@ -472,7 +486,7 @@ bool SPTexture::threadedLoad()
} }
else else
{ {
#ifndef USE_GLES2 #ifndef ANDROID
if (UserConfigParams::m_hq_mipmap && image->getDimension().Width > 1 && if (UserConfigParams::m_hq_mipmap && image->getDimension().Width > 1 &&
image->getDimension().Height > 1) image->getDimension().Height > 1)
{ {
@ -642,12 +656,6 @@ void SPTexture::applyMask(video::IImage* texture, video::IImage* mask)
} }
} // applyMask } // applyMask
// ----------------------------------------------------------------------------
bool SPTexture::initialized() const
{
return m_width.load() != 0 && m_height.load() != 0;
} // initialized
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void SPTexture::generateQuickMipmap(std::shared_ptr<video::IImage> first_image, void SPTexture::generateQuickMipmap(std::shared_ptr<video::IImage> first_image,
const std::vector<std::pair const std::vector<std::pair
@ -676,7 +684,7 @@ void SPTexture::generateHQMipmap(void* in,
<core::dimension2du, unsigned> >& mms, <core::dimension2du, unsigned> >& mms,
uint8_t* out) uint8_t* out)
{ {
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
imMipmapCascade cascade; imMipmapCascade cascade;
imReduceOptions options; imReduceOptions options;
imReduceSetOptions(&options, imReduceSetOptions(&options,
@ -708,7 +716,7 @@ void SPTexture::generateHQMipmap(void* in,
void SPTexture::squishCompressImage(uint8_t* rgba, int width, int height, void SPTexture::squishCompressImage(uint8_t* rgba, int width, int height,
int pitch, void* blocks, unsigned flags) int pitch, void* blocks, unsigned flags)
{ {
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
// This function is copied from CompressImage in libsquish to avoid omp // This function is copied from CompressImage in libsquish to avoid omp
// if enabled by shared libsquish, because we are already using // if enabled by shared libsquish, because we are already using
// multiple thread // multiple thread
@ -758,7 +766,7 @@ std::vector<std::pair<core::dimension2du, unsigned> >
{ {
std::vector<std::pair<core::dimension2du, unsigned> > mipmap_sizes; std::vector<std::pair<core::dimension2du, unsigned> > mipmap_sizes;
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(ANDROID))
unsigned width = image->getDimension().Width; unsigned width = image->getDimension().Width;
unsigned height = image->getDimension().Height; unsigned height = image->getDimension().Height;
mipmap_sizes.emplace_back(core::dimension2du(width, height), 0); mipmap_sizes.emplace_back(core::dimension2du(width, height), 0);

View File

@ -183,7 +183,8 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
GLuint getOpenGLTextureName() const { return m_texture_name; } GLuint getOpenGLTextureName() const { return m_texture_name; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool initialized() const; bool initialized() const
{ return m_width.load() != 0 && m_height.load() != 0; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
unsigned getWidth() const { return m_width.load(); } unsigned getWidth() const { return m_width.load(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

File diff suppressed because one or more lines are too long

View File

@ -1099,14 +1099,14 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
int row; int row;
int id; int id;
int iterations = 0; // a safeguard to avoid infinite loops (should not happen normally) unsigned int iterations = 0; // a safeguard to avoid infinite loops (should not happen normally)
while (!findItemInRows(name.c_str(), &row, &id)) while (!findItemInRows(name.c_str(), &row, &id))
{ {
// if we get here it means the item is scrolled out. Try to find it. // if we get here it means the item is scrolled out. Try to find it.
scroll(1, evenIfDeactivated); scroll(1, evenIfDeactivated);
if (iterations > 50) if (iterations > m_items.size())
{ {
Log::error("DynamicRibbonWidget::setSelection", "Cannot find item %d (%s)", item_id, name.c_str()); Log::error("DynamicRibbonWidget::setSelection", "Cannot find item %d (%s)", item_id, name.c_str());
return false; return false;

View File

@ -94,7 +94,7 @@ namespace GUIEngine
virtual ~IconButtonWidget() {}; virtual ~IconButtonWidget() {};
/** \brief Implement callback from base class Widget */ /** \brief Implement callback from base class Widget */
virtual void add(); virtual void add() OVERRIDE;
/** /**
* \brief Call this if scale mode is SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO. * \brief Call this if scale mode is SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO.

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