Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7a2988273 | ||
|
|
8691dfb2d4 | ||
|
|
edde451551 | ||
|
|
851bd36ce1 | ||
|
|
27bcdb341e | ||
|
|
17649cc502 | ||
|
|
f4c8c72e16 | ||
|
|
b6027e0f18 | ||
|
|
9d94473c05 | ||
|
|
85c05098b1 | ||
|
|
0e9e2af89e | ||
|
|
08f407c55c | ||
|
|
fe8dcdf478 | ||
|
|
6281b479ac | ||
|
|
489182749b | ||
|
|
d3ce304d28 | ||
|
|
d5c403dfe3 | ||
|
|
9f0d22c013 | ||
|
|
bf3b88e458 | ||
|
|
2ab2953879 | ||
|
|
c1ebcf8165 | ||
|
|
92b37d6de4 | ||
|
|
5ad6be3d5b | ||
|
|
c7b01b8e23 | ||
|
|
b45a5cec2e | ||
|
|
745df386e4 | ||
|
|
b9cb30bbd7 | ||
|
|
8b4cd23329 | ||
|
|
19f107d23f | ||
|
|
d7684d7cea | ||
|
|
2dbffbe7fd | ||
|
|
e841ae4526 | ||
|
|
17867219a0 | ||
|
|
45b750c01b | ||
|
|
cb58631b5a | ||
|
|
0333054ca6 | ||
|
|
a65d4b0829 | ||
|
|
21793191c4 | ||
|
|
99d1c48e0a | ||
|
|
001c7b30ee | ||
|
|
3d95cdc76f | ||
|
|
0b162984a5 | ||
|
|
a48b88d890 | ||
|
|
2b075e7f0f | ||
|
|
4df5a269e8 | ||
|
|
4049067c50 | ||
|
|
2b8e5c09d0 | ||
|
|
d88bebae1e | ||
|
|
5b42b43dee | ||
|
|
7b707a3546 | ||
|
|
5c2286f556 | ||
|
|
7f2f62be11 | ||
|
|
6b7bc2c67e | ||
|
|
80c8e2ace3 | ||
|
|
60dc171700 | ||
|
|
cc77d63f5b | ||
|
|
822fa73b07 | ||
|
|
b0251cf0b1 | ||
|
|
43152ff3ed | ||
|
|
e31ea79602 | ||
|
|
5a72ef711c | ||
|
|
b2447f114f | ||
|
|
c22da37992 | ||
|
|
7ac674aebd | ||
|
|
12ea4bc76f |
@@ -2,12 +2,15 @@
|
||||
* Ghost replay races by Benau
|
||||
* Battle mode AI by Benau
|
||||
* Soccer mode AI by Benau
|
||||
* New icy soccer field by samuncle and Benau
|
||||
* New subsea track by samuncle
|
||||
* New volcano track by Ponzino
|
||||
* TTF font rendering by Benau
|
||||
* Kart properties refactor by Flakebi
|
||||
* Scripting work under the hood
|
||||
* Work on the track editor by mhp
|
||||
* Tweak to challenges
|
||||
* New farm track song by 0zone0ne and Krobonil
|
||||
* Bugfixes
|
||||
|
||||
## SuperTuxKart 0.9.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# root CMakeLists for the SuperTuxKart project
|
||||
project(SuperTuxKart)
|
||||
set(PROJECT_VERSION "0.9.1")
|
||||
set(PROJECT_VERSION "0.9.2")
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
if(NOT (CMAKE_MAJOR_VERSION VERSION_LESS 3))
|
||||
@@ -68,6 +68,7 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/lib/enet")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include")
|
||||
|
||||
# Build glew library
|
||||
add_definitions(-DGLEW_NO_GLU)
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include")
|
||||
|
||||
@@ -365,6 +366,11 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FreeBSD does not search in /usr/local/lib, but at least Freetype is installed there :(
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
|
||||
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 :
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# SuperTuxKart Installation Instructions
|
||||
|
||||
Note: If you obtained this source code from Github, you also need to download the game assets from Sourceforge using SVN.
|
||||
Note: If you obtained this source code from Github, you also need to download
|
||||
the game assets from Sourceforge using SVN.
|
||||
|
||||
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
|
||||
|
||||
@@ -26,8 +27,10 @@ First, make sure that you have the following packages installed:
|
||||
Ubuntu command:
|
||||
|
||||
```
|
||||
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \
|
||||
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev libfreetype6-dev
|
||||
sudo apt-get install build-essential cmake libbluetooth-dev \
|
||||
libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
|
||||
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
|
||||
mesa-common-dev pkg-config zlib1g-dev
|
||||
```
|
||||
|
||||
Unpack the files from the tarball like this:
|
||||
|
||||
BIN
data/CREDITS
BIN
data/CREDITS
Binary file not shown.
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.8.1</string>
|
||||
<string>0.9.2-rc1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>SPTK</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.8.1</string>
|
||||
<string>0.9.2-rc1</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="cocoa_temple" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
<requirements trophies="5"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
||||
19
data/challenges/volcano_island.challenge
Normal file
19
data/challenges/volcano_island.challenge
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="volcano_island" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
||||
@@ -5,7 +5,7 @@
|
||||
<track id="greenvalley" laps="2" reverse="false" />
|
||||
<track id="mansion" laps="3" reverse="false" />
|
||||
<track id="stk_enterprise" laps="3" reverse="false" />
|
||||
<track id="city" laps="2" reverse="false" />
|
||||
<track id="volcano_island" laps="2" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/>
|
||||
<card contains="Intel" os="osx" disable="GI"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Intel" os="linux" version="<16.0" disable="FramebufferSRGBCapable"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Intel" os="windows" disable="TextureCompressionS3TC"/>
|
||||
@@ -15,11 +16,11 @@
|
||||
<card contains="NVIDIA" disable="ShaderAtomicCounters"/>
|
||||
<card contains="Mesa" os="linux" version="<10.3" disable="BufferStorage"/>
|
||||
<card contains="Mesa" os="linux" version="<10.3" disable="DriverRecentEnough"/>
|
||||
<card contains="Mesa" os="linux" version="<10.6" disable="GeometryShader4"/>
|
||||
<card contains="Mesa" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Mesa" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Gallium" os="linux" version="<10.3" disable="BufferStorage"/>
|
||||
<card contains="Gallium" os="linux" version="<10.3" disable="DriverRecentEnough"/>
|
||||
<card contains="Gallium" os="linux" version="<10.6" disable="GeometryShader4"/>
|
||||
<card contains="Gallium" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Gallium" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<!-- On osx radeon appears to have different version numbers, e.g.
|
||||
1.32.20 -->
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<!--
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
-->
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"
|
||||
I18N="Section in the profile screen" text="Achievements"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
<!--<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>-->
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"
|
||||
I18N="Section in the profile screen" text="Friends"/>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
<!--<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>-->
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 23 KiB |
1190
data/po/ar.po
1190
data/po/ar.po
File diff suppressed because it is too large
Load Diff
3801
data/po/be.po
3801
data/po/be.po
File diff suppressed because it is too large
Load Diff
2502
data/po/bg.po
2502
data/po/bg.po
File diff suppressed because it is too large
Load Diff
3793
data/po/bn.po
3793
data/po/bn.po
File diff suppressed because it is too large
Load Diff
1429
data/po/br.po
1429
data/po/br.po
File diff suppressed because it is too large
Load Diff
3797
data/po/bs.po
3797
data/po/bs.po
File diff suppressed because it is too large
Load Diff
1146
data/po/ca.po
1146
data/po/ca.po
File diff suppressed because it is too large
Load Diff
1155
data/po/cs.po
1155
data/po/cs.po
File diff suppressed because it is too large
Load Diff
1538
data/po/da.po
1538
data/po/da.po
File diff suppressed because it is too large
Load Diff
1178
data/po/de.po
1178
data/po/de.po
File diff suppressed because it is too large
Load Diff
1565
data/po/el.po
1565
data/po/el.po
File diff suppressed because it is too large
Load Diff
1100
data/po/en_AU.po
1100
data/po/en_AU.po
File diff suppressed because it is too large
Load Diff
1100
data/po/en_GB.po
1100
data/po/en_GB.po
File diff suppressed because it is too large
Load Diff
3793
data/po/eo.po
3793
data/po/eo.po
File diff suppressed because it is too large
Load Diff
1147
data/po/es.po
1147
data/po/es.po
File diff suppressed because it is too large
Load Diff
1202
data/po/eu.po
1202
data/po/eu.po
File diff suppressed because it is too large
Load Diff
3789
data/po/fa.po
3789
data/po/fa.po
File diff suppressed because it is too large
Load Diff
1148
data/po/fi.po
1148
data/po/fi.po
File diff suppressed because it is too large
Load Diff
1321
data/po/fr.po
1321
data/po/fr.po
File diff suppressed because it is too large
Load Diff
1102
data/po/fr_CA.po
1102
data/po/fr_CA.po
File diff suppressed because it is too large
Load Diff
3804
data/po/ga.po
3804
data/po/ga.po
File diff suppressed because it is too large
Load Diff
1154
data/po/gd.po
1154
data/po/gd.po
File diff suppressed because it is too large
Load Diff
2051
data/po/gl.po
2051
data/po/gl.po
File diff suppressed because it is too large
Load Diff
1144
data/po/he.po
1144
data/po/he.po
File diff suppressed because it is too large
Load Diff
3793
data/po/hi.po
3793
data/po/hi.po
File diff suppressed because it is too large
Load Diff
3797
data/po/hr.po
3797
data/po/hr.po
File diff suppressed because it is too large
Load Diff
2132
data/po/hu.po
2132
data/po/hu.po
File diff suppressed because it is too large
Load Diff
3793
data/po/hy.po
3793
data/po/hy.po
File diff suppressed because it is too large
Load Diff
3789
data/po/id.po
3789
data/po/id.po
File diff suppressed because it is too large
Load Diff
3793
data/po/is.po
3793
data/po/is.po
File diff suppressed because it is too large
Load Diff
1535
data/po/it.po
1535
data/po/it.po
File diff suppressed because it is too large
Load Diff
1154
data/po/ja.po
1154
data/po/ja.po
File diff suppressed because it is too large
Load Diff
3794
data/po/jbo.po
3794
data/po/jbo.po
File diff suppressed because it is too large
Load Diff
1125
data/po/ko.po
1125
data/po/ko.po
File diff suppressed because it is too large
Load Diff
1350
data/po/kw.po
1350
data/po/kw.po
File diff suppressed because it is too large
Load Diff
3789
data/po/ky.po
3789
data/po/ky.po
File diff suppressed because it is too large
Load Diff
2391
data/po/la.po
2391
data/po/la.po
File diff suppressed because it is too large
Load Diff
1221
data/po/lt.po
1221
data/po/lt.po
File diff suppressed because it is too large
Load Diff
1151
data/po/lv.po
1151
data/po/lv.po
File diff suppressed because it is too large
Load Diff
3792
data/po/mn_MN.po
3792
data/po/mn_MN.po
File diff suppressed because it is too large
Load Diff
1273
data/po/nb.po
1273
data/po/nb.po
File diff suppressed because it is too large
Load Diff
3792
data/po/nb_NO.po
3792
data/po/nb_NO.po
File diff suppressed because it is too large
Load Diff
1160
data/po/nl.po
1160
data/po/nl.po
File diff suppressed because it is too large
Load Diff
1150
data/po/nn.po
1150
data/po/nn.po
File diff suppressed because it is too large
Load Diff
3792
data/po/no.po
3792
data/po/no.po
File diff suppressed because it is too large
Load Diff
3792
data/po/no_NO.po
3792
data/po/no_NO.po
File diff suppressed because it is too large
Load Diff
3792
data/po/oc.po
3792
data/po/oc.po
File diff suppressed because it is too large
Load Diff
3793
data/po/os.po
3793
data/po/os.po
File diff suppressed because it is too large
Load Diff
1163
data/po/pl.po
1163
data/po/pl.po
File diff suppressed because it is too large
Load Diff
1136
data/po/pt.po
1136
data/po/pt.po
File diff suppressed because it is too large
Load Diff
1146
data/po/pt_BR.po
1146
data/po/pt_BR.po
File diff suppressed because it is too large
Load Diff
3796
data/po/ro.po
3796
data/po/ro.po
File diff suppressed because it is too large
Load Diff
1161
data/po/ru.po
1161
data/po/ru.po
File diff suppressed because it is too large
Load Diff
3792
data/po/sc.po
3792
data/po/sc.po
File diff suppressed because it is too large
Load Diff
3793
data/po/sco.po
3793
data/po/sco.po
File diff suppressed because it is too large
Load Diff
1380
data/po/sk.po
1380
data/po/sk.po
File diff suppressed because it is too large
Load Diff
1156
data/po/sl.po
1156
data/po/sl.po
File diff suppressed because it is too large
Load Diff
3793
data/po/sq.po
3793
data/po/sq.po
File diff suppressed because it is too large
Load Diff
1748
data/po/sr.po
1748
data/po/sr.po
File diff suppressed because it is too large
Load Diff
1385
data/po/sv.po
1385
data/po/sv.po
File diff suppressed because it is too large
Load Diff
1192
data/po/tr.po
1192
data/po/tr.po
File diff suppressed because it is too large
Load Diff
2432
data/po/tt.po
2432
data/po/tt.po
File diff suppressed because it is too large
Load Diff
1453
data/po/uk.po
1453
data/po/uk.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# A simple script that adds all authors from transifex, which are
|
||||
# listed in comments at the beginning of the file, to the
|
||||
# 'translator-credits' translations - where launchpad added them
|
||||
@@ -19,75 +19,79 @@ import re
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)!=2:
|
||||
if len(sys.argv) < 2:
|
||||
print "Usage: getpo_authors.py PATH_TO_PO_FILE"
|
||||
sys.exit(-1)
|
||||
|
||||
f = open(sys.argv[1], "r")
|
||||
if not f:
|
||||
print "Can not find", sys.argv[1]
|
||||
exit
|
||||
lines = f.readlines()
|
||||
for filename in sys.argv[1:]:
|
||||
print("Processing file ", filename)
|
||||
f = open(filename, "r")
|
||||
if not f:
|
||||
print "Can not find", filename
|
||||
exit
|
||||
lines = f.readlines()
|
||||
|
||||
f.close()
|
||||
f.close()
|
||||
|
||||
new_authors = []
|
||||
found = 0
|
||||
new_authors = []
|
||||
found = 0
|
||||
|
||||
# Find all authors with a simple finite state machine:
|
||||
contributions = -1
|
||||
line_count = 0
|
||||
for i in lines:
|
||||
line = i[:-1] # remove \n
|
||||
if line=="# Translators:":
|
||||
found = 1
|
||||
elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR":
|
||||
new_authors.append(line[2:])
|
||||
elif line[:5]=="msgid":
|
||||
found = 0
|
||||
elif line[:31]== "msgstr \"Launchpad Contributions":
|
||||
contributions = line_count
|
||||
line_count = line_count + 1
|
||||
# Find all authors with a simple finite state machine:
|
||||
contributions = -1
|
||||
line_count = 0
|
||||
for i in lines:
|
||||
line = i[:-1] # remove \n
|
||||
if line=="# Translators:":
|
||||
found = 1
|
||||
elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR":
|
||||
new_authors.append(line[2:])
|
||||
elif line[:5]=="msgid":
|
||||
found = 0
|
||||
elif line[:31]== "msgstr \"Launchpad Contributions":
|
||||
contributions = line_count
|
||||
line_count = line_count + 1
|
||||
|
||||
|
||||
# Delete all email addresses - not sure if the authors
|
||||
# would want them to be published
|
||||
email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least
|
||||
for i in range(len(new_authors)):
|
||||
g = email.search(new_authors[i])
|
||||
if g:
|
||||
new_authors[i] = new_authors[i][:g.start()] \
|
||||
+ new_authors[i][g.end():]
|
||||
# Delete all email addresses - not sure if the authors
|
||||
# would want them to be published
|
||||
email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least
|
||||
for i in range(len(new_authors)):
|
||||
g = email.search(new_authors[i])
|
||||
if g:
|
||||
new_authors[i] = new_authors[i][:g.start()] \
|
||||
+ new_authors[i][g.end():]
|
||||
|
||||
# Get the old authors from the translator-credits string:
|
||||
if contributions>0:
|
||||
# Ignore the first entry, which is "msgstr ...", and the
|
||||
# last two characters, which are the '"\n'.
|
||||
old_authors = lines[contributions][:-2].split("\\n")[1:]
|
||||
for i in range(len(old_authors)):
|
||||
old_authors[i] = old_authors[i].strip()
|
||||
else:
|
||||
old_authors=[]
|
||||
|
||||
all_authors = old_authors + new_authors;
|
||||
all_authors = sorted(all_authors, key=lambda x: x.lower())
|
||||
all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "")
|
||||
# Get the old authors from the translator-credits string:
|
||||
if contributions>0:
|
||||
# Ignore the first entry, which is "msgstr ...", and the
|
||||
# last two characters, which are the '"\n'.
|
||||
old_authors = lines[contributions][:-2].split("\\n")[1:]
|
||||
for i in range(len(old_authors)):
|
||||
old_authors[i] = old_authors[i].strip()
|
||||
else:
|
||||
old_authors=[]
|
||||
|
||||
all_authors = old_authors + new_authors;
|
||||
all_authors = sorted(all_authors, key=lambda x: x.lower())
|
||||
all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "")
|
||||
|
||||
credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string
|
||||
# If no old authors exists, write a new entry:
|
||||
if contributions==-1:
|
||||
lines.append("\n")
|
||||
lines.append("#: src/states_screens/credits.cpp:209\n")
|
||||
lines.append("msgid \"translator-credits\"\n")
|
||||
lines.append(credits_line)
|
||||
else:
|
||||
# Otherwise just replace the old contribution string
|
||||
lines[contributions] = credits_line
|
||||
credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string
|
||||
# If no old authors exists, write a new entry:
|
||||
if contributions==-1:
|
||||
lines.append("\n")
|
||||
lines.append("#: src/states_screens/credits.cpp:209\n")
|
||||
lines.append("msgid \"translator-credits\"\n")
|
||||
lines.append(credits_line)
|
||||
else:
|
||||
# Otherwise just replace the old contribution string
|
||||
lines[contributions] = credits_line
|
||||
|
||||
|
||||
# Overwrite old file
|
||||
f = open(sys.argv[1], "w")
|
||||
for i in lines:
|
||||
f.write(i)
|
||||
f.close()
|
||||
# Overwrite old file
|
||||
f = open(filename, "w")
|
||||
for i in lines:
|
||||
f.write(i)
|
||||
f.close()
|
||||
|
||||
print("Done with ", filename)
|
||||
|
||||
|
||||
3789
data/po/uz.po
3789
data/po/uz.po
File diff suppressed because it is too large
Load Diff
3789
data/po/vi.po
3789
data/po/vi.po
File diff suppressed because it is too large
Load Diff
3788
data/po/zh.po
3788
data/po/zh.po
File diff suppressed because it is too large
Load Diff
1144
data/po/zh_CN.po
1144
data/po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1148
data/po/zh_TW.po
1148
data/po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ out vec4 FragColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 eyedir = vec3(gl_FragCoord.xy / screen, 1.);
|
||||
vec3 eyedir = vec3(mod(gl_FragCoord.xy, screen) / screen, 1.);
|
||||
eyedir = 2.0 * eyedir - 1.0;
|
||||
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
|
||||
tmp /= tmp.w;
|
||||
|
||||
@@ -40,7 +40,7 @@ void main(void)
|
||||
float bl = 0.0;
|
||||
float m = log2(r) + 6 + log2(invSamples);
|
||||
|
||||
float theta = 2. * 3.14 * tau * .5 * invSamples + phi;
|
||||
float theta = mod(2. * 3.14 * tau * .5 * invSamples + phi, 6.283185307179586);
|
||||
vec2 rotations = vec2(cos(theta), sin(theta)) * screen;
|
||||
vec2 offset = vec2(cos(invSamples), sin(invSamples));
|
||||
|
||||
|
||||
1
data/supertuxkart.0.9.2
Normal file
1
data/supertuxkart.0.9.2
Normal file
@@ -0,0 +1 @@
|
||||
supertuxkart.0.9.2
|
||||
@@ -8,28 +8,28 @@
|
||||
<summary>A racing game</summary>
|
||||
<description>
|
||||
<p>
|
||||
SuperTuxKart is a fun 3D kart racing game.
|
||||
You can play with up to 4 friends on one PC, racing against each other or
|
||||
just try to beat the computer.
|
||||
Supertuxkart is a free 3D kart racing game, with a focus on having fun over
|
||||
realism. You can play with up to 4 friends on one PC, racing against each
|
||||
other, or try to beat the computer in single-player mode.
|
||||
</p>
|
||||
<p>
|
||||
See the great lighthouse or drive through the sand and visit the pyramids.
|
||||
Race underground or in space, watching the stars passing by.
|
||||
Have some rest under the palms on the beach (watching the other karts
|
||||
overtaking you :) ).
|
||||
But don't eat the bananas! Watch for bowling balls, plungers, bubble gum
|
||||
and cakes thrown by opponents.
|
||||
Race underground or in space, watching the stars pass by. Or rest under the
|
||||
palm trees on the beach, watching the other karts overtake you. But don't eat
|
||||
the bananas! Watch for bowling balls, plungers, bubble gum and cakes thrown by
|
||||
your opponents.
|
||||
</p>
|
||||
<p>
|
||||
You can do a single race against other karts, compete in one of several
|
||||
Grand Prix, try to beat the high score in time trials on your own, play
|
||||
battle mode against your friends, and more!
|
||||
You can do a single race against other karts, compete in one of several Grand
|
||||
Prix, try to beat the high score in time trials on your own, play battle mode
|
||||
against the computer or your friends, and more!
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">http://supertuxkart.sourceforge.net/</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4d/SuperTuxKart_0.8_screenshot.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/1/1f/SuperTuxKart_0.8_screenshot4.jpg</screenshot>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4e/Supertuxkart-0.9-screenshot-2.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/a/a9/Supertuxkart-0.9-screenshot-1.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/6/63/Supertuxkart-0.9-screenshot-3.jpg</screenshot>
|
||||
</screenshots>
|
||||
<updatecontact>supertuxkart-devel@lists.sourceforge.net</updatecontact>
|
||||
</application>
|
||||
|
||||
@@ -10,9 +10,9 @@ endif()
|
||||
find_package(OpenGL REQUIRED)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
||||
add_library(glew STATIC
|
||||
include/GL/glew.h include/GL/glxew.h include/GL/wglew.h
|
||||
src/glew.c src/glewinfo.c
|
||||
)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
||||
@@ -46,6 +46,7 @@ void CentralVideoSettings::init()
|
||||
hasMultiDrawIndirect = false;
|
||||
hasTextureCompression = false;
|
||||
hasUBO = false;
|
||||
hasExplicitAttribLocation = false;
|
||||
hasGS = false;
|
||||
|
||||
m_GI_has_artifact = false;
|
||||
@@ -154,11 +155,24 @@ void CentralVideoSettings::init()
|
||||
hasUBO = true;
|
||||
Log::info("GLDriver", "ARB Uniform Buffer Object Present");
|
||||
}
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER4) &&
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXPLICIT_ATTRIB_LOCATION) &&
|
||||
hasGLExtension("GL_ARB_explicit_attrib_location")) {
|
||||
hasExplicitAttribLocation = true;
|
||||
Log::info("GLDriver", "ARB Explicit Attrib Location Present");
|
||||
}
|
||||
#if defined(__linux__)
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER) &&
|
||||
(m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 2))) {
|
||||
hasGS = true;
|
||||
Log::info("GLDriver", "Geometry Shaders Present");
|
||||
}
|
||||
#else
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER) &&
|
||||
hasGLExtension("GL_ARB_geometry_shader4")) {
|
||||
hasGS = true;
|
||||
Log::info("GLDriver", "ARB Geometry Shader 4 Present");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only unset the high def textures if they are set as default. If the
|
||||
// user has enabled them (bit 1 set), then leave them enabled.
|
||||
@@ -229,7 +243,7 @@ bool CentralVideoSettings::needsSRGBCapableVisualWorkaround() const
|
||||
return m_need_srgb_visual_workaround;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::isARBGeometryShader4Usable() const
|
||||
bool CentralVideoSettings::isARBGeometryShadersUsable() const
|
||||
{
|
||||
return hasGS;
|
||||
}
|
||||
@@ -239,6 +253,11 @@ bool CentralVideoSettings::isARBUniformBufferObjectUsable() const
|
||||
return hasUBO;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::isARBExplicitAttribLocationUsable() const
|
||||
{
|
||||
return hasExplicitAttribLocation;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::isEXTTextureCompressionS3TCUsable() const
|
||||
{
|
||||
return hasTextureCompression;
|
||||
@@ -311,12 +330,12 @@ bool CentralVideoSettings::isARBMultiDrawIndirectUsable() const
|
||||
|
||||
bool CentralVideoSettings::supportsShadows() const
|
||||
{
|
||||
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable();
|
||||
return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable();
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::supportsGlobalIllumination() const
|
||||
{
|
||||
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable() && !m_GI_has_artifact;
|
||||
return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable() && !m_GI_has_artifact;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::supportsIndirectInstancingRendering() const
|
||||
|
||||
@@ -35,6 +35,7 @@ private:
|
||||
bool hasTextureView;
|
||||
bool hasBindlessTexture;
|
||||
bool hasUBO;
|
||||
bool hasExplicitAttribLocation;
|
||||
bool hasGS;
|
||||
bool hasTextureCompression;
|
||||
bool hasAtomics;
|
||||
@@ -60,7 +61,7 @@ public:
|
||||
bool isARBUniformBufferObjectUsable() const;
|
||||
bool isEXTTextureCompressionS3TCUsable() const;
|
||||
bool isARBTextureViewUsable() const;
|
||||
bool isARBGeometryShader4Usable() const;
|
||||
bool isARBGeometryShadersUsable() const;
|
||||
bool isARBTextureStorageUsable() const;
|
||||
bool isAMDVertexShaderLayerUsable() const;
|
||||
bool isARBComputeShaderUsable() const;
|
||||
@@ -73,6 +74,7 @@ public:
|
||||
bool isARBShaderStorageBufferObjectUsable() const;
|
||||
bool isARBImageLoadStoreUsable() const;
|
||||
bool isARBMultiDrawIndirectUsable() const;
|
||||
bool isARBExplicitAttribLocationUsable() const;
|
||||
|
||||
|
||||
// Are all required extensions available for feature support
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace GraphicsRestrictions
|
||||
|
||||
const char *m_names_of_restrictions[] = {
|
||||
"UniformBufferObject",
|
||||
"GeometryShader4",
|
||||
"GeometryShader",
|
||||
"DrawIndirect",
|
||||
"TextureView",
|
||||
"TextureStorage",
|
||||
@@ -56,6 +56,7 @@ namespace GraphicsRestrictions
|
||||
"BindlessTexture",
|
||||
"TextureCompressionS3TC",
|
||||
"AMDVertexShaderLayer",
|
||||
"ExplicitAttribLocation",
|
||||
"DriverRecentEnough",
|
||||
"HighDefinitionTextures",
|
||||
"AdvancedPipeline",
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace GraphicsRestrictions
|
||||
enum GraphicsRestrictionsType
|
||||
{
|
||||
GR_UNIFORM_BUFFER_OBJECT,
|
||||
GR_GEOMETRY_SHADER4,
|
||||
GR_GEOMETRY_SHADER,
|
||||
GR_DRAW_INDIRECT,
|
||||
GR_TEXTURE_VIEW,
|
||||
GR_TEXTURE_STORAGE,
|
||||
@@ -50,6 +50,7 @@ namespace GraphicsRestrictions
|
||||
GR_BINDLESS_TEXTURE,
|
||||
GR_EXT_TEXTURE_COMPRESSION_S3TC,
|
||||
GR_AMD_VERTEX_SHADER_LAYER,
|
||||
GR_EXPLICIT_ATTRIB_LOCATION,
|
||||
GR_DRIVER_RECENT_ENOUGH,
|
||||
GR_HIGHDEFINITION_TEXTURES,
|
||||
GR_ADVANCED_PIPELINE,
|
||||
|
||||
@@ -674,7 +674,7 @@ void IrrDriver::renderGlow(std::vector<GlowData>& glows)
|
||||
node->render();
|
||||
}
|
||||
|
||||
if (CVS->supportsIndirectInstancingRendering())
|
||||
if (CVS->supportsIndirectInstancingRendering() && CVS->isARBExplicitAttribLocationUsable())
|
||||
{
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd);
|
||||
InstancedColorizeShader::getInstance()->use();
|
||||
|
||||
@@ -83,6 +83,9 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
|
||||
if (CVS->isARBExplicitAttribLocationUsable())
|
||||
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
||||
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
|
||||
@@ -299,6 +299,7 @@ void Skybox::generateSpecularCubemap()
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
} // generateSpecularCubemap
|
||||
|
||||
|
||||
|
||||
@@ -419,8 +419,7 @@ void initTexturesTransparent(GLMesh &mesh)
|
||||
{
|
||||
if (!mesh.textures[0])
|
||||
{
|
||||
Log::fatal("STKMesh", "Missing texture for material transparent");
|
||||
return;
|
||||
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||
}
|
||||
compressTexture(mesh.textures[0], true);
|
||||
if (CVS->isAZDOEnabled())
|
||||
|
||||
@@ -532,10 +532,9 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
for (unsigned int j = 0; j < used_location.size(); j++)
|
||||
{
|
||||
if (!found) continue;
|
||||
Vec3 d = BattleGraph::get()
|
||||
->getPolyOfNode(used_location[j]).getCenter() -
|
||||
BattleGraph::get()->getPolyOfNode(node).getCenter();
|
||||
found = d.length_2d() > MIN_DIST;
|
||||
float test_distance = BattleGraph::get()
|
||||
->getDistance(used_location[j], node);
|
||||
found = test_distance > MIN_DIST;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
|
||||
@@ -283,23 +283,24 @@ void AIBaseController::crashed(const Material *m)
|
||||
} // crashed(Material)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void AIBaseController::checkPosition(const Vec3 &point,
|
||||
posData *pos_data,
|
||||
Vec3 *lc) const
|
||||
void AIBaseController::checkPosition(const Vec3 &point, posData *pos_data,
|
||||
Vec3 *lc, bool use_front_xyz) const
|
||||
{
|
||||
// Convert to local coordinates from the point of view of current kart
|
||||
btQuaternion q(btVector3(0, 1, 0), -m_kart->getHeading());
|
||||
Vec3 p = point - m_kart->getXYZ();
|
||||
Vec3 p = point -
|
||||
(use_front_xyz ? m_kart->getFrontXYZ() : m_kart->getXYZ());
|
||||
Vec3 local_coordinates = quatRotate(q, p);
|
||||
|
||||
// Save local coordinates for later use if needed
|
||||
if (lc) *lc = local_coordinates;
|
||||
|
||||
// on_side: tell whether it's left or right hand side
|
||||
if (pos_data == NULL) return;
|
||||
// lhs: tell whether it's left or right hand side
|
||||
if (local_coordinates.getX() < 0)
|
||||
pos_data->on_side = true;
|
||||
pos_data->lhs = true;
|
||||
else
|
||||
pos_data->on_side = false;
|
||||
pos_data->lhs = false;
|
||||
|
||||
// behind: tell whether it's behind or not
|
||||
if (local_coordinates.getZ() < 0)
|
||||
@@ -309,6 +310,6 @@ void AIBaseController::checkPosition(const Vec3 &point,
|
||||
|
||||
pos_data->angle = atan2(fabsf(local_coordinates.getX()),
|
||||
fabsf(local_coordinates.getZ()));
|
||||
pos_data->distance = p.length_2d();
|
||||
pos_data->distance = p.length();
|
||||
|
||||
} // checkPosition
|
||||
|
||||
@@ -65,7 +65,7 @@ protected:
|
||||
static int m_test_ai;
|
||||
|
||||
/** Position info structure of targets. */
|
||||
struct posData {bool behind; bool on_side; float angle; float distance;};
|
||||
struct posData {bool behind; bool lhs; float angle; float distance;};
|
||||
|
||||
void setControllerName(const std::string &name);
|
||||
float steerToPoint(const Vec3 &point);
|
||||
@@ -77,7 +77,9 @@ protected:
|
||||
/** This can be called to detect if the kart is stuck (i.e. repeatedly
|
||||
* hitting part of the track). */
|
||||
bool isStuck() const { return m_stuck; }
|
||||
void checkPosition(const Vec3&, posData*, Vec3* lc = NULL) const;
|
||||
void checkPosition(const Vec3&, posData*,
|
||||
Vec3* lc = NULL,
|
||||
bool use_front_xyz = false) const;
|
||||
|
||||
public:
|
||||
AIBaseController(AbstractKart *kart);
|
||||
|
||||
@@ -29,10 +29,20 @@
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
int ArenaAI::m_test_node_for_banana = BattleGraph::UNKNOWN_POLY;
|
||||
|
||||
bool isNodeWithBanana(const std::pair<const Item*, int>& item_pair)
|
||||
{
|
||||
return item_pair.second == ArenaAI::m_test_node_for_banana &&
|
||||
item_pair.first->getType() == Item::ITEM_BANANA &&
|
||||
!item_pair.first->wasCollected();
|
||||
}
|
||||
|
||||
ArenaAI::ArenaAI(AbstractKart *kart)
|
||||
: AIBaseController(kart)
|
||||
{
|
||||
m_debug_sphere = NULL;
|
||||
m_debug_sphere_next = NULL;
|
||||
} // ArenaAI
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -41,6 +51,8 @@ ArenaAI::ArenaAI(AbstractKart *kart)
|
||||
void ArenaAI::reset()
|
||||
{
|
||||
m_target_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_current_forward_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_current_forward_point = Vec3(0, 0, 0);
|
||||
m_adjusting_side = false;
|
||||
m_closest_kart = NULL;
|
||||
m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
|
||||
@@ -49,14 +61,17 @@ void ArenaAI::reset()
|
||||
m_cur_kart_pos_data = {0};
|
||||
m_is_stuck = false;
|
||||
m_is_uturn = false;
|
||||
m_avoiding_banana = false;
|
||||
m_target_point = Vec3(0, 0, 0);
|
||||
m_time_since_last_shot = 0.0f;
|
||||
m_time_since_driving = 0.0f;
|
||||
m_time_since_reversing = 0.0f;
|
||||
m_time_since_uturn = 0.0f;
|
||||
m_turn_radius = 0.0f;
|
||||
m_turn_angle = 0.0f;
|
||||
m_on_node.clear();
|
||||
m_path_corners.clear();
|
||||
m_portals.clear();
|
||||
m_aiming_points.clear();
|
||||
m_aiming_nodes.clear();
|
||||
|
||||
m_cur_difficulty = race_manager->getDifficulty();
|
||||
AIBaseController::reset();
|
||||
@@ -72,10 +87,14 @@ void ArenaAI::update(float dt)
|
||||
// This is used to enable firing an item backwards.
|
||||
m_controls->m_look_back = false;
|
||||
m_controls->m_nitro = false;
|
||||
m_avoiding_banana = false;
|
||||
|
||||
// Don't do anything if there is currently a kart animations shown.
|
||||
if (m_kart->getKartAnimation())
|
||||
{
|
||||
resetAfterStop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWaiting())
|
||||
{
|
||||
@@ -90,16 +109,16 @@ void ArenaAI::update(float dt)
|
||||
findClosestKart(true);
|
||||
findTarget();
|
||||
handleArenaItems(dt);
|
||||
handleArenaBanana();
|
||||
|
||||
if (m_kart->getSpeed() > 15.0f && m_cur_kart_pos_data.angle < 0.2f)
|
||||
if (m_kart->getSpeed() > 15.0f && m_turn_angle < 20)
|
||||
{
|
||||
// Only use nitro when target is straight
|
||||
// Only use nitro when turn angle is big (180 - angle)
|
||||
m_controls->m_nitro = true;
|
||||
}
|
||||
|
||||
if (m_is_uturn)
|
||||
{
|
||||
resetAfterStop();
|
||||
handleArenaUTurn(dt);
|
||||
}
|
||||
else
|
||||
@@ -113,6 +132,129 @@ void ArenaAI::update(float dt)
|
||||
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ArenaAI::updateAimingPosition()
|
||||
{
|
||||
// Notice: we use the point ahead of kart to determine next node,
|
||||
// to compensate the time difference between steering
|
||||
m_current_forward_point =
|
||||
m_kart->getTrans()(Vec3(0, 0, m_kart->getKartLength()));
|
||||
m_current_forward_node = BattleGraph::get()->pointToNode
|
||||
(m_current_forward_node, m_current_forward_point,
|
||||
false/*ignore_vertical*/);
|
||||
|
||||
// Use current node if forward node is unknown, or near the target
|
||||
const int forward = (m_current_forward_node == BattleGraph::UNKNOWN_POLY ||
|
||||
m_current_forward_node == m_target_node ||
|
||||
getCurrentNode() == m_target_node ? getCurrentNode() :
|
||||
m_current_forward_node);
|
||||
|
||||
if (forward == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY)
|
||||
return false;
|
||||
|
||||
if (forward == m_target_node)
|
||||
{
|
||||
m_aiming_points.push_back(BattleGraph::get()
|
||||
->getPolyOfNode(forward).getCenter());
|
||||
m_aiming_points.push_back(m_target_point);
|
||||
|
||||
m_aiming_nodes.insert(forward);
|
||||
m_aiming_nodes.insert(getCurrentNode());
|
||||
return true;
|
||||
}
|
||||
|
||||
const int next_node = BattleGraph::get()
|
||||
->getNextShortestPathPoly(forward, m_target_node);
|
||||
if (next_node == BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
Log::error("ArenaAI", "Next node is unknown, did you forget to link"
|
||||
"adjacent face in navmesh?");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_aiming_points.push_back(BattleGraph::get()
|
||||
->getPolyOfNode(forward).getCenter());
|
||||
m_aiming_points.push_back(BattleGraph::get()
|
||||
->getPolyOfNode(next_node).getCenter());
|
||||
|
||||
m_aiming_nodes.insert(forward);
|
||||
m_aiming_nodes.insert(next_node);
|
||||
m_aiming_nodes.insert(getCurrentNode());
|
||||
|
||||
return true;
|
||||
} // updateAimingPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function sets the steering.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void ArenaAI::handleArenaSteering(const float dt)
|
||||
{
|
||||
const int current_node = getCurrentNode();
|
||||
|
||||
if (current_node == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_aiming_points.clear();
|
||||
m_aiming_nodes.clear();
|
||||
const bool found_position = updateAimingPosition();
|
||||
if (ignorePathFinding())
|
||||
{
|
||||
// Steer directly
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.lhs;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (found_position)
|
||||
{
|
||||
updateBananaLocation();
|
||||
assert(m_aiming_points.size() == 2);
|
||||
updateTurnRadius(m_kart->getXYZ(), m_aiming_points[0],
|
||||
m_aiming_points[1]);
|
||||
m_target_point = m_aiming_points[1];
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setVisible(true);
|
||||
m_debug_sphere_next->setVisible(true);
|
||||
m_debug_sphere->setPosition(m_aiming_points[0].toIrrVector());
|
||||
m_debug_sphere_next->setPosition(m_aiming_points[1].toIrrVector());
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.lhs;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing (go straight) if no targets found
|
||||
setSteering(0.0f, dt);
|
||||
return;
|
||||
}
|
||||
} // handleSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::checkIfStuck(const float dt)
|
||||
{
|
||||
@@ -154,6 +296,7 @@ void ArenaAI::checkIfStuck(const float dt)
|
||||
*/
|
||||
void ArenaAI::handleArenaAcceleration(const float dt)
|
||||
{
|
||||
|
||||
if (m_controls->m_brake)
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
@@ -173,7 +316,7 @@ void ArenaAI::handleArenaUTurn(const float dt)
|
||||
|
||||
if (fabsf(m_kart->getSpeed()) >
|
||||
(m_kart->getKartProperties()->getEngineMaxSpeed() / 5)
|
||||
&& m_kart->getSpeed() < 0) // Try to emulate reverse like human players
|
||||
&& m_kart->getSpeed() < 0) // Try to emulate reverse like human players
|
||||
m_controls->m_accel = -0.06f;
|
||||
else
|
||||
m_controls->m_accel = -5.0f;
|
||||
@@ -201,6 +344,7 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
|
||||
{
|
||||
if (!m_is_stuck || m_is_uturn) return false;
|
||||
|
||||
resetAfterStop();
|
||||
setSteering(0.0f, dt);
|
||||
|
||||
if (fabsf(m_kart->getSpeed()) >
|
||||
@@ -223,287 +367,76 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
|
||||
} // handleArenaUnstuck
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function sets the steering.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void ArenaAI::handleArenaSteering(const float dt)
|
||||
void ArenaAI::updateBananaLocation()
|
||||
{
|
||||
const int current_node = getCurrentNode();
|
||||
|
||||
if (current_node == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
if (m_target_node == current_node)
|
||||
{
|
||||
// Very close to the item, steer directly
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.on_side;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
else if (m_target_node != current_node)
|
||||
{
|
||||
findPortals(current_node, m_target_node);
|
||||
stringPull(m_kart->getXYZ(), m_target_point);
|
||||
if (m_path_corners.size() > 0)
|
||||
m_target_point = m_path_corners[0];
|
||||
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.on_side;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Do nothing (go straight) if no targets found
|
||||
setSteering(0.0f, dt);
|
||||
return;
|
||||
}
|
||||
} // handleSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::handleArenaBanana()
|
||||
{
|
||||
if (m_is_uturn) return;
|
||||
|
||||
const std::vector< std::pair<const Item*, int> >& item_list =
|
||||
std::vector<std::pair<const Item*, int>>& item_list =
|
||||
BattleGraph::get()->getItemList();
|
||||
const unsigned int items_count = item_list.size();
|
||||
for (unsigned int i = 0; i < items_count; ++i)
|
||||
|
||||
std::set<int>::iterator node = m_aiming_nodes.begin();
|
||||
while (node != m_aiming_nodes.end())
|
||||
{
|
||||
const Item* item = item_list[i].first;
|
||||
if (item->getType() == Item::ITEM_BANANA && !item->wasCollected())
|
||||
m_test_node_for_banana = *node;
|
||||
std::vector<std::pair<const Item*, int>>::iterator it =
|
||||
std::find_if(item_list.begin(), item_list.end(), isNodeWithBanana);
|
||||
|
||||
if (it != item_list.end())
|
||||
{
|
||||
posData banana_pos = {0};
|
||||
Vec3 banana_lc(0, 0, 0);
|
||||
checkPosition(item->getXYZ(), &banana_pos, &banana_lc);
|
||||
if (banana_pos.angle < 0.2f && banana_pos.distance < 7.5f &&
|
||||
!banana_pos.behind)
|
||||
Vec3 banana_lc;
|
||||
checkPosition(it->first->getXYZ(), NULL, &banana_lc,
|
||||
true/*use_front_xyz*/);
|
||||
|
||||
// If satisfy the below condition, AI should not eat banana:
|
||||
// banana_lc.z() < 0.0f, behind the kart
|
||||
if (banana_lc.z() < 0.0f)
|
||||
{
|
||||
// Check whether it's straight ahead towards a banana
|
||||
// If so, adjust target point
|
||||
banana_lc = (banana_pos.on_side ? banana_lc + Vec3 (2, 0, 0) :
|
||||
banana_lc - Vec3 (2, 0, 0));
|
||||
m_target_point = m_kart->getTrans()(banana_lc);
|
||||
m_target_node = BattleGraph::get()
|
||||
->pointToNode(getCurrentNode(), m_target_point,
|
||||
false/*ignore_vertical*/);
|
||||
|
||||
// Handle one banana only
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // handleArenaBanana
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function finds the polyon edges(portals) that the AI will cross before
|
||||
* reaching its destination. We start from the current polygon and call
|
||||
* BattleGraph::getNextShortestPathPoly() to find the next polygon on the shortest
|
||||
* path to the destination. Then find the common edge between the current
|
||||
* poly and the next poly, store it and step through the channel.
|
||||
*
|
||||
* 1----2----3 In this case, the portals are:
|
||||
* |strt| | (2,5) (4,5) (10,7) (10,9) (11,12)
|
||||
* 6----5----4
|
||||
* | |
|
||||
* 7----10----11----14
|
||||
* | | | end |
|
||||
* 8----9-----12----13
|
||||
*
|
||||
* \param start The start node(polygon) of the channel.
|
||||
* \param end The end node(polygon) of the channel.
|
||||
*/
|
||||
void ArenaAI::findPortals(int start, int end)
|
||||
{
|
||||
int this_node = start;
|
||||
|
||||
// We can't use NULL because NULL==0 which is a valid node, so we initialize
|
||||
// with a value that is always invalid.
|
||||
int next_node = -999;
|
||||
|
||||
m_portals.clear();
|
||||
|
||||
while (next_node != end && this_node != -1 && next_node != -1 && this_node != end)
|
||||
{
|
||||
next_node = BattleGraph::get()->getNextShortestPathPoly(this_node, end);
|
||||
if (next_node == BattleGraph::UNKNOWN_POLY || next_node == -999) return;
|
||||
|
||||
std::vector<int> this_node_verts =
|
||||
NavMesh::get()->getNavPoly(this_node).getVerticesIndex();
|
||||
std::vector<int> next_node_verts=
|
||||
NavMesh::get()->getNavPoly(next_node).getVerticesIndex();
|
||||
|
||||
// this_node_verts and next_node_verts hold vertices of polygons in CCW order
|
||||
// We reverse next_node_verts so it becomes easy to compare edges in the next step
|
||||
std::reverse(next_node_verts.begin(),next_node_verts.end());
|
||||
|
||||
Vec3 portalLeft, portalRight;
|
||||
//bool flag = 0;
|
||||
for (unsigned int n_i = 0; n_i < next_node_verts.size(); n_i++)
|
||||
{
|
||||
for (unsigned int t_i = 0; t_i < this_node_verts.size(); t_i++)
|
||||
{
|
||||
if ((next_node_verts[n_i] == this_node_verts[t_i]) &&
|
||||
(next_node_verts[(n_i+1)%next_node_verts.size()] ==
|
||||
this_node_verts[(t_i+1)%this_node_verts.size()]))
|
||||
{
|
||||
portalLeft = NavMesh::get()->
|
||||
getVertex(this_node_verts[(t_i+1)%this_node_verts.size()]);
|
||||
|
||||
portalRight = NavMesh::get()->getVertex(this_node_verts[t_i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_portals.push_back(std::make_pair(portalLeft, portalRight));
|
||||
// for debugging:
|
||||
//m_debug_sphere->setPosition((portalLeft).toIrrVector());
|
||||
this_node = next_node;
|
||||
}
|
||||
} // findPortals
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function implements the funnel algorithm for finding shortest paths
|
||||
* through a polygon channel. This means that we should move from corner to
|
||||
* corner to move on the most straight and shortest path to the destination.
|
||||
* This can be visualized as pulling a string from the end point to the start.
|
||||
* The string will bend at the corners, and this algorithm will find those
|
||||
* corners using portals from findPortals(). The AI will aim at the first
|
||||
* corner and the rest can be used for estimating the curve (braking).
|
||||
*
|
||||
* 1----2----3 In this case, the corners are:
|
||||
* |strt| | <5,10,end>
|
||||
* 6----5----4
|
||||
* | |
|
||||
* 7----10----11----14
|
||||
* | | | end |
|
||||
* 8----9-----12----13
|
||||
*
|
||||
* \param start_pos The start position (usually the AI's current position).
|
||||
* \param end_pos The end position (m_target_point).
|
||||
*/
|
||||
void ArenaAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
{
|
||||
Vec3 funnel_apex = start_pos;
|
||||
Vec3 funnel_left = m_portals[0].first;
|
||||
Vec3 funnel_right = m_portals[0].second;
|
||||
unsigned int apex_index=0, fun_left_index=0, fun_right_index=0;
|
||||
m_portals.push_back(std::make_pair(end_pos, end_pos));
|
||||
m_path_corners.clear();
|
||||
const float eps=0.0001f;
|
||||
|
||||
for (unsigned int i = 0; i < m_portals.size(); i++)
|
||||
{
|
||||
Vec3 portal_left = m_portals[i].first;
|
||||
Vec3 portal_right = m_portals[i].second;
|
||||
|
||||
//Compute for left edge
|
||||
if ((funnel_left == funnel_apex) ||
|
||||
portal_left.sideOfLine2D(funnel_apex, funnel_left) <= -eps)
|
||||
{
|
||||
funnel_left = 0.98f*portal_left + 0.02f*portal_right;
|
||||
//funnel_left = portal_left;
|
||||
fun_left_index = i;
|
||||
|
||||
if (portal_left.sideOfLine2D(funnel_apex, funnel_right) < -eps)
|
||||
{
|
||||
funnel_apex = funnel_right;
|
||||
apex_index = fun_right_index;
|
||||
m_path_corners.push_back(funnel_apex);
|
||||
|
||||
funnel_left = funnel_apex;
|
||||
funnel_right = funnel_apex;
|
||||
i = apex_index;
|
||||
node++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the node AI will pass has a banana, adjust the aim position
|
||||
banana_lc = (banana_lc.x() < 0 ? banana_lc + Vec3(5, 0, 0) :
|
||||
banana_lc - Vec3(5, 0, 0));
|
||||
m_aiming_points[1] = m_kart->getTrans()(banana_lc);
|
||||
m_avoiding_banana = true;
|
||||
// Handle one banana only
|
||||
return;
|
||||
}
|
||||
|
||||
//Compute for right edge
|
||||
if ((funnel_right == funnel_apex) ||
|
||||
portal_right.sideOfLine2D(funnel_apex, funnel_right) >= eps)
|
||||
{
|
||||
funnel_right = 0.98f*portal_right + 0.02f*portal_left;
|
||||
//funnel_right = portal_right;
|
||||
fun_right_index = i;
|
||||
|
||||
if (portal_right.sideOfLine2D(funnel_apex, funnel_left) > eps)
|
||||
{
|
||||
funnel_apex = funnel_left;
|
||||
apex_index = fun_left_index;
|
||||
m_path_corners.push_back(funnel_apex);
|
||||
|
||||
funnel_left = funnel_apex;
|
||||
funnel_right = funnel_apex;
|
||||
i = apex_index;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
node++;
|
||||
}
|
||||
|
||||
//Push end_pos to m_path_corners so if no corners, we aim at target
|
||||
m_path_corners.push_back(end_pos);
|
||||
} // stringPull
|
||||
} // updateBananaLocation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function handles braking. It calls determineTurnRadius() to find out
|
||||
* the curve radius. Depending on the turn radius, it finds out the maximum
|
||||
/** This function handles braking. It used the turn radius found by
|
||||
* updateTurnRadius(). Depending on the turn radius, it finds out the maximum
|
||||
* speed. If the current speed is greater than the max speed and a set minimum
|
||||
* speed, brakes are applied.
|
||||
*/
|
||||
void ArenaAI::handleArenaBraking()
|
||||
{
|
||||
m_controls->m_brake = false;
|
||||
|
||||
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
// A kart will not brake when the speed is already slower than this
|
||||
// value. This prevents a kart from going too slow (or even backwards)
|
||||
// in tight curves.
|
||||
const float MIN_SPEED = 5.0f;
|
||||
|
||||
std::vector<Vec3> points;
|
||||
if (forceBraking() && m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
// Brake now
|
||||
m_controls->m_brake = true;
|
||||
return;
|
||||
}
|
||||
|
||||
points.push_back(m_kart->getXYZ());
|
||||
points.push_back(m_path_corners[0]);
|
||||
points.push_back((m_path_corners.size()>=2) ? m_path_corners[1] : m_path_corners[0]);
|
||||
m_controls->m_brake = false;
|
||||
|
||||
float current_curve_radius = determineTurnRadius(points);
|
||||
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
Vec3 d1 = m_kart->getXYZ() - m_target_point;
|
||||
Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
|
||||
if (d1.length2_2d() < d2.length2_2d())
|
||||
current_curve_radius = d1.length_2d();
|
||||
if (m_aiming_points.empty()) return;
|
||||
|
||||
float max_turn_speed = m_kart->getSpeedForTurnRadius(current_curve_radius);
|
||||
const float max_turn_speed = m_kart->getSpeedForTurnRadius(m_turn_radius);
|
||||
|
||||
if (m_kart->getSpeed() > max_turn_speed &&
|
||||
if (m_kart->getSpeed() > 1.25f * max_turn_speed &&
|
||||
fabsf(m_controls->m_steer) > 0.95f &&
|
||||
m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
m_controls->m_brake = true;
|
||||
@@ -512,60 +445,58 @@ void ArenaAI::handleArenaBraking()
|
||||
} // handleArenaBraking
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** The turn radius is determined by fitting a parabola to 3 points: current
|
||||
* location of AI, first corner and the second corner. Once the constants are
|
||||
* computed, a formula is used to find the radius of curvature at the kart's
|
||||
* current location.
|
||||
* NOTE: This method does not apply enough braking, should think of something
|
||||
* else.
|
||||
*/
|
||||
float ArenaAI::determineTurnRadius( std::vector<Vec3>& points )
|
||||
void ArenaAI::updateTurnRadius(const Vec3& p1, const Vec3& p2,
|
||||
const Vec3& p3)
|
||||
{
|
||||
// Declaring variables
|
||||
float a, b;
|
||||
irr::core::CMatrix4<float> A;
|
||||
irr::core::CMatrix4<float> X;
|
||||
irr::core::CMatrix4<float> B;
|
||||
// First use cosine formula to find out the angle made by the distance
|
||||
// between kart (point one) to point two and point two between point three
|
||||
const float a = (p1 - p2).length();
|
||||
const float b = (p2 - p3).length();
|
||||
const float c = (p1 - p3).length();
|
||||
const float angle = 180 - findAngleFrom3Edges(a, b, c);
|
||||
|
||||
//Populating matrices
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
// Only calculate radius if not almost straight line
|
||||
if (angle > 1 && angle < 179)
|
||||
{
|
||||
A(i, 0) = points[i].x()*points[i].x();
|
||||
A(i, 1) = points[i].x();
|
||||
A(i, 2) = 1.0f;
|
||||
A(i, 3) = 0.0f;
|
||||
// angle
|
||||
// ^
|
||||
// a / \ b
|
||||
// 90/\ /\90
|
||||
// \ / \ /
|
||||
// \ /
|
||||
// \ /
|
||||
// \ /
|
||||
// |
|
||||
// Try to estimate the turn radius with the help of a kite-like
|
||||
// polygon as shown, find out the lowest angle which is
|
||||
// (4 - 2) * 180 - 90 - 90 - angle (180 - angle from above)
|
||||
// Then we use this value as the angle of a sector of circle,
|
||||
// a + b as the arc length, then the radius can be calculated easily
|
||||
m_turn_radius = ((a + b) / (angle / 360)) / M_PI / 2;
|
||||
}
|
||||
A(3, 0) = A(3, 1) = A(3, 2) = 0.0f;
|
||||
A(3, 3) = 1.0f;
|
||||
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
else
|
||||
{
|
||||
B(i, 0) = points[i].z();
|
||||
B(i, 1) = 0.0f;
|
||||
B(i, 2) = 0.0f;
|
||||
B(i, 3) = 0.0f;
|
||||
// Return large radius so no braking is needed otherwise
|
||||
m_turn_radius = 45.0f;
|
||||
}
|
||||
B(3, 0) = B(3, 1) = B(3, 2) = B(3, 3) = 0.0f;
|
||||
m_turn_angle = angle;
|
||||
|
||||
//Computing inverse : X = inv(A)*B
|
||||
irr::core::CMatrix4<float> invA;
|
||||
if (!A.getInverse(invA))
|
||||
return -1;
|
||||
} // updateTurnRadius
|
||||
|
||||
X = invA*B;
|
||||
a = X(0, 0);
|
||||
b = X(0, 1);
|
||||
//c = X(0, 2);
|
||||
//-----------------------------------------------------------------------------
|
||||
float ArenaAI::findAngleFrom3Edges(float a, float b, float c)
|
||||
{
|
||||
// Cosine forumla : c2 = a2 + b2 - 2ab cos C
|
||||
float test_value = ((c * c) - (a * a) - (b * b)) / (-(2 * a * b));
|
||||
// Prevent error
|
||||
if (test_value < -1)
|
||||
test_value = -1;
|
||||
else if (test_value > 1)
|
||||
test_value = 1;
|
||||
|
||||
float x = points.front().x();
|
||||
//float z = a*pow(x, 2) + b*x + c;
|
||||
float dx_by_dz = 2*a*x + b;
|
||||
float d2x_by_dz = 2*a;
|
||||
return acosf(test_value) * RAD_TO_DEGREE;
|
||||
|
||||
float radius = pow(abs(1 + pow(dx_by_dz, 2)), 1.5f)/ abs(d2x_by_dz);
|
||||
|
||||
return radius;
|
||||
} // determineTurnRadius
|
||||
} // findAngleFrom3Edges
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::handleArenaItems(const float dt)
|
||||
@@ -663,7 +594,8 @@ void ArenaAI::handleArenaItems(const float dt)
|
||||
if (m_time_since_last_shot < 1.0f) break;
|
||||
|
||||
if (m_closest_kart_pos_data.distance < 6.0f &&
|
||||
(difficulty || perfect_aim))
|
||||
(difficulty || perfect_aim) &&
|
||||
!m_closest_kart->isInvulnerable())
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = fire_behind;
|
||||
@@ -755,14 +687,15 @@ void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
|
||||
m_kart->getKartProperties()->getNitroSmallContainer()))
|
||||
continue; // Ignore nitro when already has some
|
||||
|
||||
Vec3 d = item->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance &&
|
||||
float test_distance = BattleGraph::get()
|
||||
->getDistance(item_list[i].second, getCurrentNode());
|
||||
if (test_distance <= distance &&
|
||||
(item->getType() == Item::ITEM_BONUS_BOX ||
|
||||
item->getType() == Item::ITEM_NITRO_BIG ||
|
||||
item->getType() == Item::ITEM_NITRO_SMALL))
|
||||
{
|
||||
closest_item_num = i;
|
||||
distance = d.length_2d();
|
||||
distance = test_distance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ protected:
|
||||
/** For debugging purpose: a sphere indicating where the AI
|
||||
* is targeting at. */
|
||||
irr::scene::ISceneNode *m_debug_sphere;
|
||||
irr::scene::ISceneNode *m_debug_sphere_next;
|
||||
|
||||
/** The node(poly) at which the target point lies in. */
|
||||
int m_target_node;
|
||||
@@ -63,7 +64,10 @@ protected:
|
||||
/** The target point. */
|
||||
Vec3 m_target_point;
|
||||
|
||||
void collectItemInArena(Vec3*, int*) const;
|
||||
bool m_avoiding_banana;
|
||||
|
||||
void collectItemInArena(Vec3*, int*) const;
|
||||
float findAngleFrom3Edges(float a, float b, float c);
|
||||
private:
|
||||
/** Used by handleArenaUTurn, it tells whether to do left or right
|
||||
* turning when steering is overridden. */
|
||||
@@ -81,15 +85,7 @@ private:
|
||||
|
||||
/** Holds the unique node ai has driven through, useful to tell if AI is
|
||||
* stuck by determine the size of this set. */
|
||||
std::set <int> m_on_node;
|
||||
|
||||
/** Holds the corner points computed using the funnel algorithm that the AI
|
||||
* will eventaully move through. See stringPull(). */
|
||||
std::vector<Vec3> m_path_corners;
|
||||
|
||||
/** Holds the set of portals that the kart will cross when moving through
|
||||
* polygon channel. See findPortals(). */
|
||||
std::vector<std::pair<Vec3,Vec3> > m_portals;
|
||||
std::set<int> m_on_node;
|
||||
|
||||
/** Time an item has been collected and not used. */
|
||||
float m_time_since_last_shot;
|
||||
@@ -103,22 +99,35 @@ private:
|
||||
/** This is a timer that counts down when the kart is doing u-turn. */
|
||||
float m_time_since_uturn;
|
||||
|
||||
float m_turn_radius;
|
||||
float m_turn_angle;
|
||||
|
||||
Vec3 m_current_forward_point;
|
||||
int m_current_forward_node;
|
||||
|
||||
std::set<int> m_aiming_nodes;
|
||||
std::vector<Vec3> m_aiming_points;
|
||||
|
||||
void checkIfStuck(const float dt);
|
||||
float determineTurnRadius(std::vector<Vec3>& points);
|
||||
void findPortals(int start, int end);
|
||||
void handleArenaAcceleration(const float dt);
|
||||
void handleArenaBanana();
|
||||
void handleArenaBraking();
|
||||
void handleArenaItems(const float dt);
|
||||
void handleArenaSteering(const float dt);
|
||||
void handleArenaUTurn(const float dt);
|
||||
bool handleArenaUnstuck(const float dt);
|
||||
void stringPull(const Vec3&, const Vec3&);
|
||||
bool updateAimingPosition();
|
||||
void updateBananaLocation();
|
||||
void updateTurnRadius(const Vec3& p1, const Vec3& p2,
|
||||
const Vec3& p3);
|
||||
virtual int getCurrentNode() const = 0;
|
||||
virtual bool isWaiting() const = 0;
|
||||
virtual void resetAfterStop() {};
|
||||
virtual void findClosestKart(bool use_difficulty) = 0;
|
||||
virtual void findTarget() = 0;
|
||||
virtual bool forceBraking() { return m_avoiding_banana; }
|
||||
virtual bool ignorePathFinding() { return false; }
|
||||
public:
|
||||
static int m_test_node_for_banana;
|
||||
ArenaAI(AbstractKart *kart);
|
||||
virtual ~ArenaAI() {};
|
||||
virtual void update (float delta);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user