Merge remote-tracking branch 'origin/master' into network-item-debugging
This commit is contained in:
commit
35deb3970b
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="abyss" laps="3"/>
|
||||
<track id="abyss" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="candela_city" laps="3"/>
|
||||
<track id="candela_city" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="75"/>
|
||||
|
||||
|
@ -1,24 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="cocoa_temple" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="5"/>
|
||||
<track id="cocoa_temple" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="timetrial"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<best>
|
||||
<karts number="8"/>
|
||||
<requirements position="1" time="125"/>
|
||||
<karts number="1"
|
||||
replay_file="challenge_cocoa_temple_supertux.replay"/>
|
||||
<requirements position="1"/>
|
||||
</best>
|
||||
<hard>
|
||||
<karts number="7"/>
|
||||
<requirements position="1" time="160"/>
|
||||
<karts number="1"
|
||||
replay_file="challenge_cocoa_temple_expert.replay"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="6"/>
|
||||
<karts number="1"
|
||||
replay_file="challenge_cocoa_temple_intermediate.replay"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="5"/>
|
||||
<karts number="1"
|
||||
replay_file="challenge_cocoa_temple_novice.replay"/>
|
||||
<karts number="1"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
|
||||
<unlock kart="suzanne"/>
|
||||
</challenge>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="cornfield_crossing" laps="3"/>
|
||||
<track id="cornfield_crossing" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="fortmagma" laps="3"/>
|
||||
<track id="fortmagma" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="190"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="gran_paradiso_island" laps="3"/>
|
||||
<track id="gran_paradiso_island" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="80"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="greenvalley" laps="3"/>
|
||||
<track id="greenvalley" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="90"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="hacienda" laps="3"/>
|
||||
<track id="hacienda" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="25"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="lighthouse" laps="4"/>
|
||||
<track id="lighthouse" laps="4" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="125"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="mansion" laps="3"/>
|
||||
<track id="mansion" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="100"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="mines" laps="3"/>
|
||||
<track id="mines" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="140"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="minigolf" laps="4"/>
|
||||
<track id="minigolf" laps="4" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="130"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="olivermath" laps="5"/>
|
||||
<track id="olivermath" laps="5" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="sandtrack" laps="3"/>
|
||||
<track id="sandtrack" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="scotland" laps="3"/>
|
||||
<track id="scotland" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="snowmountain" laps="3"/>
|
||||
<track id="snowmountain" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="115"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="snowtuxpeak" laps="3"/>
|
||||
<track id="snowtuxpeak" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="45"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="stk_enterprise" laps="3"/>
|
||||
<track id="stk_enterprise" laps="3" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="105"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="volcano_island" laps="2"/>
|
||||
<track id="volcano_island" laps="2" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="xr591" laps="2"/>
|
||||
<track id="xr591" laps="2" reverse="false"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="135"/>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="3">
|
||||
<unlock_list list="false"/>
|
||||
<track id="zengarden" laps="4"/>
|
||||
<track id="zengarden" laps="4" reverse="false"/>
|
||||
<mode major="single" minor="timetrial"/>
|
||||
<requirements trophies="35"/>
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div y="2%" width="100%" height="96%" layout="vertical-row">
|
||||
<div x="1%" y="2%" width="98%" height="96%" layout="vertical-row">
|
||||
|
||||
<div width="100%" height="40%" layout="vertical-row">
|
||||
<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">
|
||||
<box width="100%" height="75%" align="center" layout="vertical-row" padding="1">
|
||||
<list id="current_replay_info" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
</div>
|
||||
@ -18,8 +18,8 @@
|
||||
</div>
|
||||
|
||||
<div width="64%" height="100%" layout="vertical-row">
|
||||
<div width="95%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="40" layout="horizontal-row" >
|
||||
<div width="95%" align="center" layout="vertical-row" height="50%">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="record-race" I18N="Ghost replay info action" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" id="record-race-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Record the race for ghost replay"/>
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="95%" height="50%" align="center">
|
||||
<div width="95%" height="40%" align="center">
|
||||
<buttonbar id="actions" x="0" y="0" height="100%" width="100%" align="center">
|
||||
<icon-button id="start" width="128" height="128"
|
||||
icon="gui/icons/green_check.png"
|
||||
|
@ -5,12 +5,14 @@
|
||||
<model id="model" width="100%" layout="horizontal-row" height="100%">
|
||||
</model>
|
||||
</div>
|
||||
<label text="0 to use the original color, otherwise pick one from slider."
|
||||
width="100%" text_align="center" word_wrap="true"
|
||||
I18N="In the kart color slider dialog"/>
|
||||
<div width="20%" height="fit" text-align="left" layout="horizontal-row" >
|
||||
<checkbox id="toggle-slider" />
|
||||
<spacer width="40"/>
|
||||
<label id="toggle-text"/>
|
||||
</div>
|
||||
<spacer height="30" width="10"/>
|
||||
<div height="fit" width="100%" layout="horizontal-row">
|
||||
<gauge id="color-slider" min_value="0" max_value="100" proportion="1"/>
|
||||
<gauge id="color-slider" min_value="1" max_value="100" proportion="1"/>
|
||||
</div>
|
||||
<spacer height="30" width="10"/>
|
||||
<button id="close" text="Apply" align="center"/>
|
||||
|
@ -44,6 +44,8 @@ options_language.png by Alayan, based on http://www.languageicon.org/, released
|
||||
|
||||
blue_flag.png, heart.png and red_flag.png by Benau, released under CC-BY-SA 4
|
||||
|
||||
lap_flag.png, modified by Alayan, original by Alina Oleynik from The Noun Project, under CC-BY 3.0
|
||||
|
||||
====
|
||||
|
||||
Glass Skin by Auria, under CC-BY-SA 3+
|
||||
|
BIN
data/gui/icons/lap_flag.png
Normal file
BIN
data/gui/icons/lap_flag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
@ -13,50 +13,55 @@
|
||||
<list id="replay_list" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
|
||||
<tabs id="race_mode" height="6%" max_height="110" x="2%" width="98%" align="center">
|
||||
<tabs id="race_mode" height="6%" max_height="110" x="1%" width="98%" align="center">
|
||||
<icon-button id="tab_time_trial" width="128" height="128" icon="gui/icons/mode_tt.png"
|
||||
I18N="In the ghost replay selection screen" text="Time trial"/>
|
||||
<icon-button id="tab_egg_hunt" width="128" height="128" icon="gui/icons/mode_easter.png"
|
||||
I18N="In the ghost replay selection screen" text="Egg hunt"/>
|
||||
</tabs>
|
||||
|
||||
<spacer width="100%" height="1.5%" />
|
||||
<spacer width="100%" height="2%" />
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" 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" >
|
||||
<div width="40%" 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 width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="2" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_difficulty_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 replays matching the current difficulty"/>
|
||||
</div>
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_multiplayer_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Hide multiplayer replays"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_version_toggle" text_align="left"/>
|
||||
<spacer width="1%" height="fit" />
|
||||
<spacer width="2%" 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 width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_multiplayer_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Hide multiplayer replays"/>
|
||||
</div>
|
||||
<div width="40%" height="fit" layout="horizontal-row" >
|
||||
<spacer proportion="1" height="5"/>
|
||||
<button width="fit" id="record-ghost" I18N="In the ghost replay selection screen" text="Record a ghost replay"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<checkbox width="fit" id="private_server" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
I18N="In the server selection screen" text="Show only private server(s)"/>
|
||||
I18N="In the server selection screen" text="Show private server(s)"/>
|
||||
<checkbox width="fit" id="game_started" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
|
@ -30,14 +30,26 @@
|
||||
|
||||
<!-- ************ SKIN CHOICE ************ -->
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<label I18N="In the ui settings" text="Skin" align="center"/>
|
||||
<label proportion="1" I18N="In the ui settings" text="Skin" align="center"/>
|
||||
<spacer width="2%" height="20"/>
|
||||
<spinner id="skinchoice" width="30%"/>
|
||||
<div layout="horizontal-row" proportion="5" height="100%">
|
||||
<spinner id="skinchoice" width="60%"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<label proportion="1" I18N="In the ui settings" text="Minimap" align="center"/>
|
||||
<spacer width="2%" height="20"/>
|
||||
<div layout="horizontal-row" proportion="5" height="100%">
|
||||
<spinner id="minimap" width="60%"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="showfps"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Display FPS" word_wrap="true"/>
|
||||
@ -45,7 +57,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="split_screen_horizontally"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Multiplayer splits screen horizontally" word_wrap="true"/>
|
||||
@ -53,7 +65,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="perPlayerDifficulty"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Enable per-player handicaps" word_wrap="true"/>
|
||||
@ -61,7 +73,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="enable-internet"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Connect to the Internet" word_wrap="true"/>
|
||||
@ -69,7 +81,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="enable-hw-report"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" id="label-hw-report" I18N="In the ui settings"
|
||||
@ -78,7 +90,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="show-login"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Always show login screen" word_wrap="true"/>
|
||||
@ -86,7 +98,7 @@
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="6%">
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="enable-lobby-chat"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" id="label-lobby-chat" I18N="In the ui settings" text="Enable chatting in networking lobby" word_wrap="true"/>
|
||||
|
@ -7,89 +7,117 @@
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<box width="100%" height="40%" padding="10" layout="horizontal-row">
|
||||
<!-- Left pane -->
|
||||
<div proportion="1" height="100%" layout="vertical-row">
|
||||
<icon-button proportion="1" width="100%" height="100%" id="screenshot" custom_ratio="1.33333"/>
|
||||
</div>
|
||||
<!-- Right pane -->
|
||||
<div proportion="1" height="100%" layout="vertical-row">
|
||||
<label id="highscores" width="100%" text_align="center" text="= Highscores ="/>
|
||||
<div width="100%" height="73%" layout="horizontal-row">
|
||||
<!-- Left pane -->
|
||||
<div width="34%" height="100%" layout="vertical-row">
|
||||
<icon-button width="100%" height="55%" id="screenshot" custom_ratio="1.33333"/>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore1" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore1" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore2" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore2" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore3" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore3" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<label id="author" width="100%" text_align="center" word_wrap="true"/>
|
||||
|
||||
<spacer width="1" height="10%"/>
|
||||
<label id="max-arena-players" width="100%" text_align="center" word_wrap="true"/>
|
||||
<!-- Misc. info box -->
|
||||
<box width="100%" height="43%" padding="10" layout="vertical-row">
|
||||
<spacer width="1" height="20%"/>
|
||||
<label id="author" width="100%" text_align="center" word_wrap="true"/>
|
||||
<spacer width="1" height="20%"/>
|
||||
<label id="max-arena-players" width="100%" text_align="center" word_wrap="true"/>
|
||||
<spacer width="1" height="20%"/>
|
||||
</box>
|
||||
</div>
|
||||
|
||||
</box>
|
||||
<spacer width="1" height="1%"/>
|
||||
<box width="100%" height="33%" layout="vertical-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="lap-text" proportion="1" I18N="In the track info screen" text="Number of laps" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="lap-spinner" width="50%" min_value="1" max_value="20" align="center"
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="ai-text" proportion="1" I18N="In the track info screen" text="Number of AI karts" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="ai-spinner" width="50%" min_value="1" max_value="20" align="center"
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="option-text" proportion="1" I18N="In the track info screen" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="50%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="option" align="center"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
|
||||
<div width="64%" height="100%" layout="vertical-row">
|
||||
<!-- Right pane -->
|
||||
<box width="100%" height="55%" padding="10" layout="vertical-row">
|
||||
<label id="highscores" width="100%" text_align="center" text="= Highscores ="/>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore1" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore1" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="record-race-text" proportion="1" I18N="In the track info screen" text="Record the race for ghost replay" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="50%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="record" align="center"/>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore2" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore2" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore3" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore3" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore4" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore4" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<div width="95%" height="fit" layout="horizontal-row">
|
||||
<icon id="iconscore5" icon="gui/icons/random_kart.png" width="font" height="font"/>
|
||||
<spacer width="2%" height="1"/>
|
||||
<label id="highscore5" proportion="1" text="(Empty)"/>
|
||||
</div>
|
||||
</box><!-- Highscores box -->
|
||||
|
||||
<spacer width="1" height="2%"/>
|
||||
<!-- Race options box -->
|
||||
<box width="100%" height="43%" layout="vertical-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="lap-spinner" width="100%" min_value="1" max_value="20" align="center"
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
<spacer width="3%"/>
|
||||
<label id="lap-text" proportion="4" I18N="In the track info screen" text="Number of laps" text_align="left"/>
|
||||
</div>
|
||||
<spacer width="1" height="2%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="ai-spinner" width="100%" min_value="1" max_value="20" align="center"
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
<spacer width="3%"/>
|
||||
<label id="ai-text" proportion="4" I18N="In the track info screen" text="Number of AI karts" text_align="left"/>
|
||||
</div>
|
||||
<spacer width="1" height="2%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="100%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="option" align="center"/>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="3%"/>
|
||||
<label id="option-text" proportion="4" I18N="In the track info screen" text_align="left"/>
|
||||
</div>
|
||||
<spacer width="1" height="2%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="100%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="record" align="center"/>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="3%"/>
|
||||
<label id="record-race-text" proportion="4" I18N="In the track info screen" text="Record the race for ghost replay" text_align="left"/>
|
||||
</div>
|
||||
</box><!-- Race options box -->
|
||||
</div>
|
||||
</box>
|
||||
</div>
|
||||
|
||||
<spacer width="1" height="1%"/>
|
||||
|
||||
<buttonbar id="buttons" height="17%" width="100%" align="center">
|
||||
<icon-button id="start" width="64" height="64" icon="gui/icons/green_check.png"
|
||||
I18N="In the track info screen" text="Start Race"/>
|
||||
|
@ -67,7 +67,7 @@
|
||||
The actual turn radius is piece-wise linearly interpolated. This
|
||||
allows for tighter turning at lower speeds, and also avoids that
|
||||
the kart becomes too hard to control at high speed (speeds of
|
||||
higher than 23 can only be reached with powerups).
|
||||
higher than 25 can only be reached with powerups).
|
||||
time-full-steer: This is the amount of change in steering depending
|
||||
on current steering. So if the steering is between 0 and 0.5,
|
||||
the time-for-steering-change is 0.15. If the current steering is
|
||||
|
File diff suppressed because it is too large
Load Diff
1205
data/replay/challenge_cocoa_temple_expert.replay
Normal file
1205
data/replay/challenge_cocoa_temple_expert.replay
Normal file
File diff suppressed because it is too large
Load Diff
1350
data/replay/challenge_cocoa_temple_intermediate.replay
Normal file
1350
data/replay/challenge_cocoa_temple_intermediate.replay
Normal file
File diff suppressed because it is too large
Load Diff
1722
data/replay/challenge_cocoa_temple_novice.replay
Normal file
1722
data/replay/challenge_cocoa_temple_novice.replay
Normal file
File diff suppressed because it is too large
Load Diff
1131
data/replay/challenge_cocoa_temple_supertux.replay
Normal file
1131
data/replay/challenge_cocoa_temple_supertux.replay
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
||||
|
||||
<!-- Minimum and maxium server versions that be be read by this binary.
|
||||
Older versions will be ignored. -->
|
||||
<server-version min="1" max="1"/>
|
||||
<server-version min="2" max="2"/>
|
||||
|
||||
<!-- Maximum number of karts to be used at the same time. This limit
|
||||
can easily be increased, but some tracks might not have valid start
|
||||
@ -114,7 +114,7 @@
|
||||
that the bit is to be set to 0, otherwise the bit will be set.
|
||||
|
||||
This field takes two
|
||||
values: the first value is 'and'ed with bullet's default values
|
||||
values: the first value is 'and'ed with bullet's default values
|
||||
(i.e. it can be used to unset bullet defaults), the second value
|
||||
is 'or'ed (i.e. is used to set a bit). A value of -1 for 'and'
|
||||
means to keep all bits. The valid names are listed in stk_config.cpp
|
||||
@ -125,7 +125,7 @@
|
||||
smooth-angle-limit="0.65"
|
||||
fps="120"
|
||||
default-track-friction="0.5"
|
||||
default-moveable-friction="0.5"
|
||||
default-moveable-friction="0.5"
|
||||
solver-iterations="4"
|
||||
solver-split-impulse="true"
|
||||
solver-split-impulse-threshold="-0.00001"
|
||||
@ -149,14 +149,14 @@
|
||||
<replay max-frames="12000" delta-t="0.200" delta-speed="0.6"
|
||||
delta-steering="0.35" />
|
||||
|
||||
<!-- Determines the minimap related values.
|
||||
<!-- 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"/>
|
||||
|
||||
<urls donate="https://supertuxkart.net/Donate"
|
||||
<urls donate="https://supertuxkart.net/Donate"
|
||||
password-reset="http://addons.supertuxkart.net/password-reset.php" />
|
||||
|
||||
<!-- Skidmark data: maximum number of skid marks, and
|
||||
@ -201,7 +201,7 @@
|
||||
away if there is an explosion. -->
|
||||
<explosion impulse-objects="500.0" />
|
||||
|
||||
<!-- Networking
|
||||
<!-- Networking
|
||||
state-frequency: how many states the server will send per second.
|
||||
steering-reduction: Reduce a remote kart's steering by this factor
|
||||
each frame. This helps reduces oversteering by high latency
|
||||
|
@ -133,6 +133,20 @@ namespace scene
|
||||
}
|
||||
}
|
||||
|
||||
virtual void recursiveUpdateAbsolutePosition()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// update absolute position
|
||||
updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
|
||||
ISceneNodeList::Iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->recursiveUpdateAbsolutePosition();
|
||||
}
|
||||
}
|
||||
|
||||
//! Renders the node.
|
||||
virtual void render() = 0;
|
||||
|
@ -249,6 +249,10 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
|
||||
LastTimeMs = timeMs;
|
||||
|
||||
IAnimatedMeshSceneNode::OnAnimate(timeMs);
|
||||
|
||||
// For up-to-date current frame bone-child attachment
|
||||
for (u32 n=0;n<JointChildSceneNodes.size();++n)
|
||||
JointChildSceneNodes[n]->recursiveUpdateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,6 +121,9 @@ void CMountPointReader::buildDirectory()
|
||||
io::path full = list->getFullFileName(i);
|
||||
full = full.subString(Path.size(), full.size() - Path.size());
|
||||
|
||||
if (full == "")
|
||||
continue;
|
||||
|
||||
if (!list->isDirectory(i))
|
||||
{
|
||||
addItem(full, list->getFileOffset(i), list->getFileSize(i), false, RealFileNames.size());
|
||||
|
@ -39,6 +39,7 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
m_mode = CM_SINGLE_RACE;
|
||||
m_minor = RaceManager::MINOR_MODE_NORMAL_RACE;
|
||||
m_num_laps = -1;
|
||||
m_reverse = false;
|
||||
m_track_id = "";
|
||||
m_gp_id = "";
|
||||
m_version = 0;
|
||||
@ -182,6 +183,12 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
{
|
||||
error("laps");
|
||||
}
|
||||
if (!track_node->get("reverse", &m_reverse))
|
||||
{
|
||||
Log::warn("Challenge Data",
|
||||
"No reverse mode specified for challenge %s, defaulting to normal",
|
||||
filename.c_str());
|
||||
}
|
||||
}
|
||||
else if (gp_node != NULL)
|
||||
{
|
||||
@ -283,6 +290,10 @@ const irr::core::stringw ChallengeData::getChallengeDescription() const
|
||||
// Follow the leader mode:
|
||||
description = _("Follow the leader");
|
||||
}
|
||||
if (m_reverse == true)
|
||||
{
|
||||
description += _("Reverse");
|
||||
}
|
||||
}
|
||||
return description;
|
||||
} // getChallengeDescription
|
||||
@ -397,6 +408,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
|
||||
race_manager->setMinorMode(m_minor);
|
||||
race_manager->setTrack(m_track_id);
|
||||
race_manager->setNumLaps(m_num_laps);
|
||||
race_manager->setReverseTrack(m_reverse);
|
||||
race_manager->setNumKarts(m_default_num_karts[d]);
|
||||
race_manager->setNumPlayers(1);
|
||||
race_manager->setCoinTarget(m_energy[d]);
|
||||
@ -423,7 +435,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
|
||||
if (m_is_ghost_replay)
|
||||
{
|
||||
const bool result = ReplayPlay::get()->addReplayFile(file_manager
|
||||
->getAsset(FileManager::CHALLENGE, m_replay_files[d]),
|
||||
->getAsset(FileManager::REPLAY, m_replay_files[d]),
|
||||
true/*custom_replay*/);
|
||||
if (!result)
|
||||
Log::fatal("ChallengeData", "Can't open replay for challenge!");
|
||||
@ -460,7 +472,7 @@ bool ChallengeData::isChallengeFulfilled() const
|
||||
|
||||
if (kart->isEliminated() ) return false;
|
||||
if (track_name != m_track_id ) return false;
|
||||
if ((int)world->getNumKarts() < m_default_num_karts[d] ) return false;
|
||||
if ((int)world->getNumKarts() < m_default_num_karts[d] ) return false;
|
||||
if (m_energy[d] > 0 && kart->getEnergy() < m_energy[d] ) return false;
|
||||
if (m_position[d] > 0 && kart->getPosition() > m_position[d]) return false;
|
||||
|
||||
|
@ -94,6 +94,7 @@ private:
|
||||
RaceManager::MinorRaceModeType m_minor;
|
||||
|
||||
int m_num_laps;
|
||||
bool m_reverse;
|
||||
int m_position[RaceManager::DIFFICULTY_COUNT];
|
||||
int m_default_num_karts[RaceManager::DIFFICULTY_COUNT];
|
||||
std::string m_ai_kart_ident[RaceManager::DIFFICULTY_COUNT];
|
||||
@ -184,6 +185,9 @@ public:
|
||||
return m_num_laps;
|
||||
} // getNumLaps
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return reverse mode. */
|
||||
bool getReverse() const { return m_reverse; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get number of required trophies to start this challenge */
|
||||
int getNumTrophies() const { return m_num_trophies; }
|
||||
|
@ -41,6 +41,7 @@ static std::vector<UserConfigParam*> all_params;
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
@ -53,9 +54,12 @@ const int UserConfig::m_current_config_version = 8;
|
||||
// ----------------------------------------------------------------------------
|
||||
UserConfigParam::~UserConfigParam()
|
||||
{
|
||||
// Now we have server config param so we cannot do this anymore,
|
||||
// esp all params are kept until the closing of stk anyway
|
||||
//all_params.remove(this);
|
||||
if (m_can_be_deleted)
|
||||
{
|
||||
auto it = std::find(all_params.begin(), all_params.end(), this);
|
||||
if (it != all_params.end())
|
||||
all_params.erase(it);
|
||||
}
|
||||
} // ~UserConfigParam
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -66,6 +66,7 @@ class UserConfigParam
|
||||
{
|
||||
friend class GroupUserConfigParam;
|
||||
protected:
|
||||
bool m_can_be_deleted = true;
|
||||
std::string m_param_name;
|
||||
std::string m_comment;
|
||||
public:
|
||||
@ -761,7 +762,7 @@ namespace UserConfigParams
|
||||
&m_network_group, "Use random port for server connection "
|
||||
"(check stk_config.xml for default value)"));
|
||||
PARAM_PREFIX BoolUserConfigParam m_lobby_chat
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "lobby-chat",
|
||||
PARAM_DEFAULT(BoolUserConfigParam(true, "lobby-chat",
|
||||
&m_network_group, "Enable chatting in networking lobby, if off than "
|
||||
"no chat message will be displayed from any players."));
|
||||
PARAM_PREFIX IntUserConfigParam m_max_players
|
||||
@ -902,6 +903,10 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT( StringUserConfigParam("Peach.stkskin", "skin_file",
|
||||
"Name of the skin to use") );
|
||||
|
||||
PARAM_PREFIX IntUserConfigParam m_minimap_display
|
||||
PARAM_DEFAULT(IntUserConfigParam(0, "minimap_display",
|
||||
"Minimap: 0 bottom-left, 1 middle-right, 2 hidden"));
|
||||
|
||||
// ---- Handicap
|
||||
PARAM_PREFIX GroupUserConfigParam m_handicap
|
||||
PARAM_DEFAULT( GroupUserConfigParam("Handicap",
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/particle_kind_manager.hpp"
|
||||
#include "graphics/sp/sp_texture_manager.hpp"
|
||||
@ -57,9 +58,10 @@ MaterialManager::MaterialManager()
|
||||
MaterialManager::~MaterialManager()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
SP::SPTextureManager::get()->stopThreads();
|
||||
if (CVS->isGLSL())
|
||||
SP::SPTextureManager::get()->stopThreads();
|
||||
#endif
|
||||
|
||||
|
||||
for(unsigned int i=0; i<m_materials.size(); i++)
|
||||
{
|
||||
delete m_materials[i];
|
||||
|
@ -974,21 +974,39 @@ namespace GUIEngine
|
||||
if (ScreenKeyboard::isActive()) ScreenKeyboard::dismiss();
|
||||
if (ModalDialog::isADialogActive()) ModalDialog::dismiss();
|
||||
|
||||
//delete g_font;
|
||||
g_font->drop();
|
||||
g_font = NULL;
|
||||
//delete g_title_font;
|
||||
g_title_font->drop();
|
||||
g_title_font = NULL;
|
||||
//delete g_small_font;
|
||||
g_small_font->drop();
|
||||
g_small_font = NULL;
|
||||
g_large_font->drop();
|
||||
g_large_font = NULL;
|
||||
g_digit_font->drop();
|
||||
g_digit_font = NULL;
|
||||
g_outline_font->drop();
|
||||
g_outline_font = NULL;
|
||||
if (g_font)
|
||||
{
|
||||
//delete g_font;
|
||||
g_font->drop();
|
||||
g_font = NULL;
|
||||
}
|
||||
if (g_title_font)
|
||||
{
|
||||
//delete g_title_font;
|
||||
g_title_font->drop();
|
||||
g_title_font = NULL;
|
||||
}
|
||||
if (g_small_font)
|
||||
{
|
||||
//delete g_small_font;
|
||||
g_small_font->drop();
|
||||
g_small_font = NULL;
|
||||
}
|
||||
if (g_large_font)
|
||||
{
|
||||
g_large_font->drop();
|
||||
g_large_font = NULL;
|
||||
}
|
||||
if (g_digit_font)
|
||||
{
|
||||
g_digit_font->drop();
|
||||
g_digit_font = NULL;
|
||||
}
|
||||
if (g_outline_font)
|
||||
{
|
||||
g_outline_font->drop();
|
||||
g_outline_font = NULL;
|
||||
}
|
||||
|
||||
// nothing else to delete for now AFAIK, irrlicht will automatically
|
||||
// kill everything along the device
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "input/input_manager.hpp"
|
||||
#include "modes/demo_world.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/debug.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
@ -186,21 +184,6 @@ bool EventHandler::OnEvent (const SEvent &event)
|
||||
SFXManager::get()->resumeAll();
|
||||
}
|
||||
}
|
||||
else if (cmd == APP_CMD_TERM_WINDOW)
|
||||
{
|
||||
if (STKHost::existHost() && NetworkConfig::get()->isWAN())
|
||||
{
|
||||
STKHost::get()->requestShutdownDelayed(10000);
|
||||
}
|
||||
}
|
||||
else if (cmd == APP_CMD_INIT_WINDOW)
|
||||
{
|
||||
if (STKHost::existHost() && NetworkConfig::get()->isWAN() &&
|
||||
!STKHost::get()->requestedShutdown())
|
||||
{
|
||||
STKHost::get()->cancelShutdown();
|
||||
}
|
||||
}
|
||||
else if (cmd == APP_CMD_LOW_MEMORY)
|
||||
{
|
||||
Log::warn("EventHandler", "Low memory event received");
|
||||
|
@ -272,7 +272,9 @@ PlayerKartWidget::~PlayerKartWidget()
|
||||
|
||||
if (m_kart_name->getIrrlichtElement() != NULL)
|
||||
m_kart_name->getIrrlichtElement()->remove();
|
||||
getCurrentScreen()->manualRemoveWidget(this);
|
||||
|
||||
if (getCurrentScreen() != NULL)
|
||||
getCurrentScreen()->manualRemoveWidget(this);
|
||||
|
||||
#ifdef DEBUG
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
|
@ -388,25 +388,26 @@ void MultitouchDevice::updateAxisY(float value)
|
||||
*/
|
||||
void MultitouchDevice::handleControls(MultitouchButton* button)
|
||||
{
|
||||
if (m_controller == NULL)
|
||||
if (!isGameRunning())
|
||||
return;
|
||||
|
||||
if (button->type == MultitouchButtonType::BUTTON_STEERING)
|
||||
{
|
||||
updateAxisX(button->axis_x);
|
||||
updateAxisY(button->axis_y);
|
||||
}
|
||||
else if (button->type == MultitouchButtonType::BUTTON_UP_DOWN)
|
||||
{
|
||||
updateAxisY(button->axis_y);
|
||||
}
|
||||
else if (button->type == MultitouchButtonType::BUTTON_ESCAPE)
|
||||
|
||||
if (button->type == MultitouchButtonType::BUTTON_ESCAPE)
|
||||
{
|
||||
StateManager::get()->escapePressed();
|
||||
}
|
||||
else
|
||||
|
||||
if (m_controller != NULL && !race_manager->isWatchingReplay())
|
||||
{
|
||||
if (button->action != PA_BEFORE_FIRST)
|
||||
if (button->type == MultitouchButtonType::BUTTON_STEERING)
|
||||
{
|
||||
updateAxisX(button->axis_x);
|
||||
updateAxisY(button->axis_y);
|
||||
}
|
||||
else if (button->type == MultitouchButtonType::BUTTON_UP_DOWN)
|
||||
{
|
||||
updateAxisY(button->axis_y);
|
||||
}
|
||||
else if (button->action != PA_BEFORE_FIRST)
|
||||
{
|
||||
int value = button->pressed ? Input::MAX_VALUE : 0;
|
||||
m_controller->action(button->action, value);
|
||||
@ -416,6 +417,15 @@ void MultitouchDevice::handleControls(MultitouchButton* button)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool MultitouchDevice::isGameRunning()
|
||||
{
|
||||
return StateManager::get()->getGameState() == GUIEngine::GAME &&
|
||||
!GUIEngine::ModalDialog::isADialogActive() &&
|
||||
!GUIEngine::ScreenKeyboard::isActive();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void MultitouchDevice::updateController()
|
||||
{
|
||||
if (m_player == NULL)
|
||||
@ -427,10 +437,7 @@ void MultitouchDevice::updateController()
|
||||
// Handle multitouch events only when race is running. It avoids to process
|
||||
// it when pause dialog is active during the race. And there is no reason
|
||||
// to use it for GUI navigation.
|
||||
if (StateManager::get()->getGameState() != GUIEngine::GAME ||
|
||||
GUIEngine::ModalDialog::isADialogActive() ||
|
||||
GUIEngine::ScreenKeyboard::isActive() ||
|
||||
race_manager->isWatchingReplay())
|
||||
if (!isGameRunning())
|
||||
{
|
||||
m_controller = NULL;
|
||||
return;
|
||||
|
@ -94,6 +94,7 @@ private:
|
||||
|
||||
float getSteeringFactor(float value);
|
||||
void handleControls(MultitouchButton* button);
|
||||
bool isGameRunning();
|
||||
|
||||
public:
|
||||
/** The array that contains data for all multitouch input events */
|
||||
|
@ -631,3 +631,26 @@ std::string AssetsAndroid::getDataPath()
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Get a path for internal lib directory
|
||||
* \return Path for internal lib directory or empty string when failed
|
||||
*/
|
||||
std::string AssetsAndroid::getLibPath()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
AndroidApplicationInfo application_info =
|
||||
CIrrDeviceAndroid::getApplicationInfo(global_android_app->activity);
|
||||
|
||||
std::string lib_path = application_info.native_lib_dir;
|
||||
|
||||
if (access(lib_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
lib_path = "";
|
||||
}
|
||||
|
||||
return lib_path;
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
void init();
|
||||
static std::string getDataPath();
|
||||
static std::string getLibPath();
|
||||
};
|
||||
|
||||
|
||||
|
@ -110,7 +110,8 @@ Attachment::~Attachment()
|
||||
*/
|
||||
void Attachment::set(AttachmentType type, int ticks,
|
||||
AbstractKart *current_kart,
|
||||
bool disable_swatter_animation)
|
||||
bool disable_swatter_animation,
|
||||
bool set_by_rewind_parachute)
|
||||
{
|
||||
// Don't override currently player swatter removing bomb animation
|
||||
Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||
@ -179,7 +180,8 @@ void Attachment::set(AttachmentType type, int ticks,
|
||||
// A parachute can be attached as result of the usage of an item. In this
|
||||
// case we have to save the current kart speed so that it can be detached
|
||||
// by slowing down.
|
||||
if(m_type==ATTACH_PARACHUTE)
|
||||
// if set by rewind the parachute ticks is already correct
|
||||
if (m_type == ATTACH_PARACHUTE && !set_by_rewind_parachute)
|
||||
{
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
float speed_mult;
|
||||
@ -306,19 +308,16 @@ void Attachment::rewindTo(BareNetworkString *buffer)
|
||||
|
||||
// Attaching an object can be expensive (loading new models, ...)
|
||||
// so avoid doing this if there is no change in attachment type
|
||||
// Don't use set to reset a model on local player if it's already cleared
|
||||
// (or m_initial_speed is redone / model is re-shown again when rewinding)
|
||||
if (m_type == new_type || m_type == ATTACH_NOTHING)
|
||||
if (m_type == new_type)
|
||||
{
|
||||
setTicksLeft(ticks_left);
|
||||
if (m_type != new_type && new_type != ATTACH_SWATTER)
|
||||
m_type = new_type;
|
||||
return;
|
||||
}
|
||||
|
||||
set(new_type, ticks_left, m_previous_owner,
|
||||
new_type == ATTACH_SWATTER && !is_removing_bomb
|
||||
/*disable_swatter_animation*/);
|
||||
/*disable_swatter_animation*/,
|
||||
new_type == ATTACH_PARACHUTE);
|
||||
} // rewindTo
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -353,6 +352,12 @@ void Attachment::hitBanana(ItemState *item_state)
|
||||
return;
|
||||
}
|
||||
|
||||
// Make it consistent with attachment rewind when eating banana with bomb
|
||||
// see if (m_type == ATTACH_BOMB && m_kart->getKartAnimation() != NULL)
|
||||
// in 515
|
||||
if (m_kart->getKartAnimation())
|
||||
return;
|
||||
|
||||
AttachmentType new_attachment = ATTACH_NOTHING;
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
// Use this as a basic random number to make sync with server easier.
|
||||
@ -529,13 +534,19 @@ void Attachment::update(int ticks)
|
||||
m_node->setVisible((division & 0x1) == 0);
|
||||
}
|
||||
|
||||
if(m_plugin)
|
||||
if (m_plugin)
|
||||
{
|
||||
bool discard = m_plugin->updateAndTestFinished(ticks);
|
||||
if(discard)
|
||||
int discard_ticks = m_plugin->updateAndTestFinished(ticks);
|
||||
if (discard_ticks != -1)
|
||||
{
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
// Save it for rewinding
|
||||
m_ticks_left =
|
||||
discard_ticks - World::getWorld()->getTicksSinceStart();
|
||||
if (m_ticks_left <= 0)
|
||||
{
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,8 @@ public:
|
||||
void handleCollisionWithKart(AbstractKart *other);
|
||||
void set (AttachmentType type, int ticks,
|
||||
AbstractKart *previous_kart=NULL,
|
||||
bool disable_swatter_animation = false);
|
||||
bool disable_swatter_animation = false,
|
||||
bool set_by_rewind_parachute = false);
|
||||
void rewindTo(BareNetworkString *buffer);
|
||||
void saveState(BareNetworkString *buffer) const;
|
||||
|
||||
|
@ -53,8 +53,9 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Updates a plugin. This is called once each time frame. If the
|
||||
* function returns true, the attachment is discarded. */
|
||||
virtual bool updateAndTestFinished(int ticks) = 0;
|
||||
* function returns a non-negative number, the attachment is discarded
|
||||
* when world ticks >= that number. */
|
||||
virtual int updateAndTestFinished(int ticks) = 0;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when the animation of the Attachment's node is done. */
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "items/item.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -138,6 +138,10 @@ public:
|
||||
virtual void collectedItem (ItemState *item, AbstractKart *kart);
|
||||
virtual void switchItems ();
|
||||
bool randomItemsForArena(const AlignedArray<btTransform>& pos);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the items are switched atm. */
|
||||
bool areItemsSwitched() { return (m_switch_ticks > 0); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Only used in the NetworkItemManager. */
|
||||
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
|
||||
|
@ -256,7 +256,7 @@ BareNetworkString* Plunger::saveState(std::vector<std::string>* ru)
|
||||
BareNetworkString* buffer = Flyable::saveState(ru);
|
||||
buffer->addUInt16(m_keep_alive).addUInt8(m_moved_to_infinity ? 1 : 0);
|
||||
if (m_rubber_band)
|
||||
buffer->addUInt8(m_rubber_band->getRubberBandTo());
|
||||
buffer->addUInt8(m_rubber_band->get8BitState());
|
||||
else
|
||||
buffer->addUInt8(255);
|
||||
return buffer;
|
||||
@ -268,7 +268,20 @@ void Plunger::restoreState(BareNetworkString *buffer, int count)
|
||||
Flyable::restoreState(buffer, count);
|
||||
m_keep_alive = buffer->getUInt16();
|
||||
m_moved_to_infinity = buffer->getUInt8() == 1;
|
||||
int8_t rbt = buffer->getUInt8();
|
||||
if (rbt != -1 && m_rubber_band)
|
||||
m_rubber_band->setRubberBandTo((RubberBand::RubberBandTo)rbt);
|
||||
uint8_t bit_state = buffer->getUInt8();
|
||||
if (bit_state == 255 && m_rubber_band)
|
||||
{
|
||||
delete m_rubber_band;
|
||||
m_rubber_band = NULL;
|
||||
if (!m_reverse_mode)
|
||||
m_reverse_mode = true;
|
||||
}
|
||||
else if (bit_state != 255 && !m_rubber_band)
|
||||
{
|
||||
m_rubber_band = new RubberBand(this, m_owner);
|
||||
if (m_reverse_mode)
|
||||
m_reverse_mode = false;
|
||||
}
|
||||
if (bit_state != 255)
|
||||
m_rubber_band->set8BitState(bit_state);
|
||||
} // restoreState
|
||||
|
@ -561,6 +561,11 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n,
|
||||
random_number);
|
||||
// FIXME Disable switch and bubblegum for now in network
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
(new_powerup == PowerupManager::POWERUP_BUBBLEGUM ||
|
||||
new_powerup == PowerupManager::POWERUP_SWITCH))
|
||||
new_powerup = PowerupManager::POWERUP_BOWLING;
|
||||
|
||||
// Always add a new powerup in ITEM_MODE_NEW (or if the kart
|
||||
// doesn't have a powerup atm).
|
||||
|
@ -45,6 +45,7 @@
|
||||
RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
|
||||
: m_plunger(plunger), m_owner(kart)
|
||||
{
|
||||
m_hit_kart = NULL;
|
||||
m_attached_state = RB_TO_PLUNGER;
|
||||
updatePosition();
|
||||
|
||||
@ -276,6 +277,7 @@ void RubberBand::hit(AbstractKart *kart_hit, const Vec3 *track_xyz)
|
||||
// =================
|
||||
m_hit_position = *track_xyz;
|
||||
m_attached_state = RB_TO_TRACK;
|
||||
m_hit_kart = NULL;
|
||||
} // hit
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -289,3 +291,24 @@ void RubberBand::remove()
|
||||
}
|
||||
#endif
|
||||
} // remove
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
uint8_t RubberBand::get8BitState() const
|
||||
{
|
||||
uint8_t state = (uint8_t)(m_attached_state & 3);
|
||||
state |= m_attached_state == RB_TO_KART && m_hit_kart ?
|
||||
(m_hit_kart->getWorldKartId() << 3) : 0;
|
||||
return state;
|
||||
} // get8BitState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RubberBand::set8BitState(uint8_t bit_state)
|
||||
{
|
||||
m_hit_kart = NULL;
|
||||
m_attached_state = (RubberBandTo)(bit_state & 3);
|
||||
if (m_attached_state == RB_TO_KART)
|
||||
{
|
||||
unsigned kart = bit_state >> 3;
|
||||
m_hit_kart = World::getWorld()->getKart(kart);
|
||||
}
|
||||
} // set8BitState
|
||||
|
@ -73,8 +73,8 @@ public:
|
||||
void updateGraphics(float dt);
|
||||
void update(int ticks);
|
||||
void hit(AbstractKart *kart_hit, const Vec3 *track_xyz=NULL);
|
||||
RubberBandTo getRubberBandTo() const { return m_attached_state; }
|
||||
void setRubberBandTo(RubberBandTo rbt) { m_attached_state = rbt; }
|
||||
uint8_t get8BitState() const;
|
||||
void set8BitState(uint8_t bit_state);
|
||||
void remove();
|
||||
}; // RubberBand
|
||||
#endif
|
||||
|
@ -161,20 +161,20 @@ void Swatter::updateGrahpics(float dt)
|
||||
/** Updates an armed swatter: it checks for any karts that are close enough
|
||||
* and not invulnerable, it swats the kart.
|
||||
* \param dt Time step size.
|
||||
* \return True if the attachment should be discarded.
|
||||
* \return World ticks to discard the swatter.
|
||||
*/
|
||||
bool Swatter::updateAndTestFinished(int ticks)
|
||||
int Swatter::updateAndTestFinished(int ticks)
|
||||
{
|
||||
const int ticks_start = World::getWorld()->getTicksSinceStart();
|
||||
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||
{
|
||||
if (ticks_start >= m_removed_bomb_ticks)
|
||||
return true;
|
||||
return false;
|
||||
return m_removed_bomb_ticks;
|
||||
return -1;
|
||||
} // if removing bomb
|
||||
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
if (!m_discard_now)
|
||||
{
|
||||
@ -186,7 +186,7 @@ bool Swatter::updateAndTestFinished(int ticks)
|
||||
// to make sure all clients know the existence of swatter each other
|
||||
if (ticks_start - m_swatter_start_ticks < 60 ||
|
||||
m_swatter_end_ticks - ticks_start < 60)
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
chooseTarget();
|
||||
pointToTarget();
|
||||
@ -258,15 +258,15 @@ bool Swatter::updateAndTestFinished(int ticks)
|
||||
|
||||
if (m_discard_now)
|
||||
{
|
||||
return ticks_start > m_end_swat_ticks;
|
||||
return m_end_swat_ticks;
|
||||
}
|
||||
else if (ticks_start > m_end_swat_ticks)
|
||||
{
|
||||
m_animation_phase = SWATTER_AIMING;
|
||||
m_end_swat_ticks = std::numeric_limits<int>::max();
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
return false;
|
||||
return -1;
|
||||
} // updateAndTestFinished
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
scene::ISceneNode* bomb_scene_node, int ticks);
|
||||
virtual ~Swatter();
|
||||
void updateGrahpics(float dt) OVERRIDE;
|
||||
bool updateAndTestFinished(int ticks) OVERRIDE;
|
||||
int updateAndTestFinished(int ticks) OVERRIDE;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the swatter is currently aiming, i.e. can be used to
|
||||
|
@ -261,6 +261,8 @@ public:
|
||||
/** Returns true if the kart has a plunger attached to its face. */
|
||||
virtual int getBlockedByPlungerTicks() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getGraphicalViewBlockedByPlunger() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime. */
|
||||
virtual void blockViewWithPlunger() = 0;
|
||||
@ -274,6 +276,9 @@ public:
|
||||
* \param slowdown Reduction of max speed. */
|
||||
virtual void setSquash(float time, float slowdown) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Makes the kart unsquashed again. */
|
||||
virtual void unsetSquash() = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the speed of the kart in meters/second. This is not declared
|
||||
* pure abstract, since this function is not needed for certain classes,
|
||||
* like Ghost. */
|
||||
|
@ -143,9 +143,19 @@ void AbstractKartAnimation::addNetworkAnimationChecker(bool reset_powerup)
|
||||
{
|
||||
// Prevent access to deleted kart animation object
|
||||
std::weak_ptr<int> cct = m_check_created_ticks;
|
||||
Vec3 original_position;
|
||||
AbstractKart* k = m_kart;
|
||||
if (k)
|
||||
original_position = k->getXYZ();
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(m_created_ticks,
|
||||
[](){},
|
||||
/*undo_function*/[cct, k, original_position]()
|
||||
{
|
||||
auto cct_sp = cct.lock();
|
||||
if (!cct_sp || !k)
|
||||
return;
|
||||
k->setXYZ(original_position);
|
||||
},
|
||||
/*replay_function*/[p]()
|
||||
{
|
||||
if (p)
|
||||
|
@ -30,6 +30,14 @@
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
enum KartAnimationType : uint8_t
|
||||
{
|
||||
KAT_RESCUE = 0,
|
||||
KAT_EXPLOSION_DIRECT_HIT = 1,
|
||||
KAT_EXPLOSION = 2,
|
||||
KAT_CANNON = 3
|
||||
};
|
||||
|
||||
/** The base class for all kart animation, like rescue, explosion, or cannon.
|
||||
* Kart animations are done by removing the physics body from the physics
|
||||
* world, and instead modifying the rotation and position of the kart
|
||||
@ -94,10 +102,12 @@ public:
|
||||
m_end_transform = t;
|
||||
m_end_ticks = ticks;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void checkNetworkAnimationCreationSucceed(const btTransform& fallback_trans);
|
||||
// ----------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
void checkNetworkAnimationCreationSucceed(const btTransform& fb_trans);
|
||||
// ------------------------------------------------------------------------
|
||||
int getEndTicks() const { return m_end_ticks; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const = 0;
|
||||
}; // AbstractKartAnimation
|
||||
|
||||
#endif
|
||||
|
@ -81,6 +81,8 @@ public:
|
||||
virtual ~CannonAnimation();
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool usePredefinedEndTransform() const { return false; }
|
||||
virtual bool usePredefinedEndTransform() const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const { return KAT_CANNON; }
|
||||
}; // CannonAnimation
|
||||
#endif
|
||||
|
@ -101,6 +101,8 @@ void NetworkAIController::convertAIToPlayerActions()
|
||||
0 : 32768);
|
||||
all_actions.emplace_back(PA_RESCUE,
|
||||
m_ai_controls->getRescue() ? 32768 : 0);
|
||||
all_actions.emplace_back(PA_LOOK_BACK,
|
||||
m_ai_controls->getLookBack() ? 32768 : 0);
|
||||
|
||||
for (const auto& a : all_actions)
|
||||
{
|
||||
|
@ -316,6 +316,9 @@ void SkiddingAI::update(int ticks)
|
||||
|
||||
int num_ai = m_world->getNumKarts() - race_manager->getNumPlayers();
|
||||
int position_among_ai = m_kart->getPosition() - m_num_players_ahead;
|
||||
// Karts with boosted AI get a better speed cap value
|
||||
if (m_kart->getBoostAI())
|
||||
position_among_ai = 1;
|
||||
|
||||
float speed_cap = m_ai_properties->getSpeedCap(m_distance_to_player,
|
||||
position_among_ai,
|
||||
@ -1063,7 +1066,6 @@ void SkiddingAI::evaluateItems(const ItemState *item, Vec3 kart_aim_direction,
|
||||
* Level 2 to 5 AI : strategy detailed before each item
|
||||
* Each successive level is overall stronger (5 the strongest, 2 the weakest of
|
||||
* non-random strategies), but two levels may share a strategy for a given item.
|
||||
* (level 5 is not yet used ; meant for SuperTux GP preferred karts or boss races)
|
||||
* \param dt Time step size.
|
||||
* STATE: shield on -> avoid usage of offensive items (with certain tolerance)
|
||||
* STATE: swatter on -> avoid usage of shield
|
||||
@ -1361,7 +1363,7 @@ void SkiddingAI::handleBubblegum(int item_skill,
|
||||
//if it is a bomb, wait : we may pass it to another kart before the timer runs out
|
||||
if (item_skill == 5 && type == Attachment::ATTACH_BOMB)
|
||||
{
|
||||
if (m_kart->getAttachment()->getTicksLeft() > stk_config->time2Ticks(3))
|
||||
if (m_kart->getAttachment()->getTicksLeft() < stk_config->time2Ticks(2))
|
||||
{
|
||||
m_controls->setFire(true);
|
||||
m_controls->setLookBack(false);
|
||||
@ -1425,7 +1427,8 @@ void SkiddingAI::handleBubblegum(int item_skill,
|
||||
if (abs_angle < 0.2f) straight_behind = true;
|
||||
}
|
||||
|
||||
if(m_distance_behind < 8.0f && straight_behind )
|
||||
if(m_distance_behind < 8.0f && straight_behind &&
|
||||
(!ItemManager::get()->areItemsSwitched() || item_skill < 4))
|
||||
{
|
||||
m_controls->setFire(true);
|
||||
m_controls->setLookBack(true);
|
||||
|
@ -72,7 +72,7 @@ ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart)
|
||||
// ----------------------------------------------------------------------------
|
||||
ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
const Vec3 &explosion_position,
|
||||
bool direct_hit)
|
||||
bool direct_hit, bool from_state)
|
||||
: AbstractKartAnimation(kart, "ExplosionAnimation")
|
||||
{
|
||||
m_direct_hit = direct_hit;
|
||||
@ -148,7 +148,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
|
||||
m_kart->getAttachment()->clear();
|
||||
// Clear powerups when direct hit in CTF
|
||||
addNetworkAnimationChecker(m_reset_ticks != -1);
|
||||
if (!from_state)
|
||||
addNetworkAnimationChecker(m_reset_ticks != -1);
|
||||
} // ExplosionAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -74,9 +74,9 @@ protected:
|
||||
Vec3 m_reset_xyz, m_reset_normal;
|
||||
|
||||
ExplosionAnimation(AbstractKart *kart);
|
||||
ExplosionAnimation(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit);
|
||||
public:
|
||||
ExplosionAnimation(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit, bool from_state = false);
|
||||
static ExplosionAnimation *create(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit);
|
||||
static ExplosionAnimation *create(AbstractKart *kart);
|
||||
@ -85,5 +85,8 @@ public:
|
||||
virtual void update(int ticks);
|
||||
bool hasResetAlready() const
|
||||
{ return m_reset_ticks != -1 && m_timer < m_reset_ticks; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const
|
||||
{ return m_direct_hit ? KAT_EXPLOSION_DIRECT_HIT : KAT_EXPLOSION; }
|
||||
}; // ExplosionAnimation
|
||||
#endif
|
||||
|
@ -118,18 +118,9 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_max_speed = new MaxSpeed(this);
|
||||
m_terrain_info = new TerrainInfo();
|
||||
m_powerup = new Powerup(this);
|
||||
m_last_used_powerup = PowerupManager::POWERUP_NOTHING;
|
||||
m_vehicle = NULL;
|
||||
m_initial_position = position;
|
||||
m_race_position = position;
|
||||
m_collected_energy = 0;
|
||||
m_finished_race = false;
|
||||
m_race_result = false;
|
||||
m_finish_time = 0.0f;
|
||||
m_bubblegum_ticks = 0;
|
||||
m_bubblegum_torque = 0.0f;
|
||||
m_invulnerable_ticks = 0;
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
|
||||
m_shadow = NULL;
|
||||
m_wheel_box = NULL;
|
||||
@ -138,16 +129,13 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_skidmarks = NULL;
|
||||
m_controller = NULL;
|
||||
m_saved_controller = NULL;
|
||||
m_flying = false;
|
||||
m_stars_effect = NULL;
|
||||
m_is_jumping = false;
|
||||
m_min_nitro_ticks = 0;
|
||||
m_energy_to_min_ratio = 0;
|
||||
m_consumption_per_tick = stk_config->ticks2Time(1) *
|
||||
m_kart_properties->getNitroConsumption();
|
||||
m_fire_clicked = 0;
|
||||
m_boosted_ai = false;
|
||||
m_type = RaceManager::KT_AI;
|
||||
m_flying = false;
|
||||
|
||||
m_xyz_history_size = stk_config->time2Ticks(XYZ_HISTORY_TIME);
|
||||
|
||||
@ -157,17 +145,12 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_previous_xyz.push_back(initial_position);
|
||||
m_previous_xyz_times.push_back(0.0f);
|
||||
}
|
||||
m_time_previous_counter = 0.0f;
|
||||
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_has_caught_nolok_bubblegum = false;
|
||||
|
||||
// Initialize custom sound vector (TODO: add back when properly done)
|
||||
// m_custom_sounds.resize(SFXManager::NUM_CUSTOMS);
|
||||
|
||||
// Set position and heading:
|
||||
m_reset_transform = init_transform;
|
||||
m_speed = 0.0f;
|
||||
m_last_factor_engine_sound = 0.0f;
|
||||
|
||||
m_kart_model->setKart(this);
|
||||
@ -202,7 +185,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_terrain_sound = NULL;
|
||||
m_last_sound_material = NULL;
|
||||
m_previous_terrain_sound = NULL;
|
||||
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
} // Kart
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -316,7 +299,7 @@ Kart::~Kart()
|
||||
*/
|
||||
void Kart::reset()
|
||||
{
|
||||
if (m_flying)
|
||||
if (m_flying && !isGhostKart())
|
||||
{
|
||||
m_flying = false;
|
||||
stopFlying();
|
||||
@ -366,6 +349,9 @@ void Kart::reset()
|
||||
m_collision_particles->setCreationRateAbsolute(0.0f);
|
||||
#endif
|
||||
|
||||
unsetSquash();
|
||||
|
||||
m_last_used_powerup = PowerupManager::POWERUP_NOTHING;
|
||||
m_race_position = m_initial_position;
|
||||
m_finished_race = false;
|
||||
m_eliminated = false;
|
||||
@ -373,8 +359,9 @@ void Kart::reset()
|
||||
m_bubblegum_ticks = 0;
|
||||
m_bubblegum_torque = 0.0f;
|
||||
m_invulnerable_ticks = 0;
|
||||
m_min_nitro_ticks = 0;
|
||||
m_energy_to_min_ratio = 0;
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
m_collected_energy = 0;
|
||||
m_bounce_back_ticks = 0;
|
||||
m_brake_ticks = 0;
|
||||
@ -383,9 +370,14 @@ void Kart::reset()
|
||||
m_current_lean = 0.0f;
|
||||
m_falling_time = 0.0f;
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
m_has_caught_nolok_bubblegum = false;
|
||||
m_is_jumping = false;
|
||||
m_flying = false;
|
||||
m_startup_boost = 0.0f;
|
||||
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
for (int i=0;i<m_xyz_history_size;i++)
|
||||
{
|
||||
m_previous_xyz[i] = getXYZ();
|
||||
@ -599,8 +591,15 @@ void Kart::blockViewWithPlunger()
|
||||
{
|
||||
// Avoid that a plunger extends the plunger time
|
||||
if(m_view_blocked_by_plunger<=0 && !isShielded())
|
||||
{
|
||||
m_view_blocked_by_plunger =
|
||||
stk_config->time2Ticks(m_kart_properties->getPlungerInFaceTime());
|
||||
if (m_graphical_view_blocked_by_plunger == 0.0f)
|
||||
{
|
||||
m_graphical_view_blocked_by_plunger =
|
||||
m_kart_properties->getPlungerInFaceTime();
|
||||
}
|
||||
}
|
||||
if(isShielded())
|
||||
{
|
||||
decreaseShieldTime();
|
||||
@ -884,22 +883,27 @@ float Kart::getSpeedForTurnRadius(float radius) const
|
||||
InterpolationArray turn_angle_at_speed = m_kart_properties->getTurnRadius();
|
||||
// Convert the turn radius into turn angle
|
||||
for(int i = 0; i < (int)turn_angle_at_speed.size(); i++)
|
||||
turn_angle_at_speed.setY(i, sin(m_kart_properties->getWheelBase() /
|
||||
turn_angle_at_speed.getY(i)));
|
||||
turn_angle_at_speed.setY(i, sin( 1.0 / turn_angle_at_speed.getY(i)));
|
||||
|
||||
float angle = sin(m_kart_properties->getWheelBase() / radius);
|
||||
float angle = sin(1.0 / radius);
|
||||
return turn_angle_at_speed.getReverse(angle);
|
||||
} // getSpeedForTurnRadius
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum steering angle (depending on speed). */
|
||||
/** Returns the maximum steering angle (depending on speed).
|
||||
This is proportional to kart length because physics reverse this effect,
|
||||
the results of this function should not be used to determine the
|
||||
real raw steer angle. */
|
||||
float Kart::getMaxSteerAngle(float speed) const
|
||||
{
|
||||
InterpolationArray turn_angle_at_speed = m_kart_properties->getTurnRadius();
|
||||
// Convert the turn radius into turn angle
|
||||
// We multiply by wheel base to keep turn radius identical
|
||||
// across karts of different lengths sharing the same
|
||||
// turn radius properties
|
||||
for(int i = 0; i < (int)turn_angle_at_speed.size(); i++)
|
||||
turn_angle_at_speed.setY(i, sin(m_kart_properties->getWheelBase() /
|
||||
turn_angle_at_speed.getY(i)));
|
||||
turn_angle_at_speed.setY(i, sin( 1.0 / turn_angle_at_speed.getY(i))
|
||||
* m_kart_properties->getWheelBase());
|
||||
|
||||
return turn_angle_at_speed.get(speed);
|
||||
} // getMaxSteerAngle
|
||||
@ -955,10 +959,16 @@ void Kart::finishedRace(float time, bool from_server)
|
||||
World::getWorld()->getTicksSinceStart(),
|
||||
/*undo_function*/[old_controller, this]()
|
||||
{
|
||||
if (m_network_finish_check_ticks == -1)
|
||||
return;
|
||||
|
||||
m_controller = old_controller;
|
||||
},
|
||||
/*replay_function*/[ec, old_controller, this]()
|
||||
{
|
||||
if (m_network_finish_check_ticks == -1)
|
||||
return;
|
||||
|
||||
m_saved_controller = old_controller;
|
||||
ec->reset();
|
||||
m_controller = ec;
|
||||
@ -1068,9 +1078,8 @@ void Kart::setRaceResult()
|
||||
}
|
||||
else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_FREE_FOR_ALL)
|
||||
{
|
||||
// the top kart wins
|
||||
FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
|
||||
m_race_result = ffa->getKartAtPosition(1) == this;
|
||||
m_race_result = ffa->getKartFFAResult(getWorldKartId());
|
||||
}
|
||||
else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG)
|
||||
{
|
||||
@ -1323,13 +1332,13 @@ void Kart::eliminate()
|
||||
*/
|
||||
void Kart::update(int ticks)
|
||||
{
|
||||
if (m_network_finish_check_ticks != 0 &&
|
||||
if (m_network_finish_check_ticks > 0 &&
|
||||
World::getWorld()->getTicksSinceStart() >
|
||||
m_network_finish_check_ticks &&
|
||||
!m_finished_race && m_saved_controller != NULL)
|
||||
{
|
||||
Log::warn("Kart", "Missing finish race from server.");
|
||||
m_network_finish_check_ticks = 0;
|
||||
m_network_finish_check_ticks = -1;
|
||||
delete m_controller;
|
||||
m_controller = m_saved_controller;
|
||||
m_saved_controller = NULL;
|
||||
@ -1432,7 +1441,10 @@ void Kart::update(int ticks)
|
||||
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= ticks;
|
||||
//unblock the view if kart just became shielded
|
||||
if(isShielded())
|
||||
{
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
}
|
||||
// Decrease remaining invulnerability time
|
||||
if(m_invulnerable_ticks>0)
|
||||
{
|
||||
@ -1672,6 +1684,7 @@ void Kart::update(int ticks)
|
||||
if (emergency)
|
||||
{
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
if (m_flying)
|
||||
{
|
||||
stopFlying();
|
||||
@ -1831,6 +1844,31 @@ void Kart::setSquash(float time, float slowdown)
|
||||
#endif
|
||||
} // setSquash
|
||||
|
||||
void Kart::unsetSquash()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (isGhostKart()) return;
|
||||
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
if (m_vehicle && m_vehicle->getNumWheels() > 0)
|
||||
{
|
||||
scene::ISceneNode** wheels = m_kart_model->getWheelNodes();
|
||||
scene::ISceneNode* node = m_kart_model->getAnimatedNode() ?
|
||||
m_kart_model->getAnimatedNode() : m_node;
|
||||
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); i++)
|
||||
{
|
||||
if (wheels[i])
|
||||
{
|
||||
wheels[i]->setParent(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns if the kart is currently being squashed
|
||||
*/
|
||||
@ -3020,22 +3058,13 @@ void Kart::updateGraphics(float dt)
|
||||
// If squasing time ends, reset the model
|
||||
if (m_squash_time <= 0.0f || !isSquashed())
|
||||
{
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
scene::ISceneNode* node =
|
||||
m_kart_model->getAnimatedNode() ?
|
||||
m_kart_model->getAnimatedNode() : m_node;
|
||||
if (m_vehicle->getNumWheels() > 0)
|
||||
{
|
||||
scene::ISceneNode **wheels = m_kart_model->getWheelNodes();
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); ++i)
|
||||
{
|
||||
if (wheels[i])
|
||||
wheels[i]->setParent(node);
|
||||
}
|
||||
}
|
||||
unsetSquash();
|
||||
}
|
||||
} // if squashed
|
||||
if (m_graphical_view_blocked_by_plunger > 0.0f)
|
||||
m_graphical_view_blocked_by_plunger -= dt;
|
||||
if (m_graphical_view_blocked_by_plunger < 0.0f)
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < EMITTER_COUNT; i++)
|
||||
|
@ -223,6 +223,9 @@ protected:
|
||||
/** When a kart has its view blocked by the plunger, this variable will be
|
||||
* > 0 the number it contains is the time left before removing plunger. */
|
||||
int16_t m_view_blocked_by_plunger;
|
||||
|
||||
float m_graphical_view_blocked_by_plunger;
|
||||
|
||||
/** The current speed (i.e. length of velocity vector) of this kart. */
|
||||
float m_speed;
|
||||
|
||||
@ -313,6 +316,7 @@ public:
|
||||
virtual void handleZipper (const Material *m=NULL,
|
||||
bool play_sound=false) OVERRIDE;
|
||||
virtual void setSquash (float time, float slowdown) OVERRIDE;
|
||||
virtual void unsetSquash () OVERRIDE;
|
||||
|
||||
virtual void crashed (AbstractKart *k, bool update_attachments) OVERRIDE;
|
||||
virtual void crashed (const Material *m, const Vec3 &normal) OVERRIDE;
|
||||
@ -393,6 +397,9 @@ public:
|
||||
virtual int getBlockedByPlungerTicks() const OVERRIDE
|
||||
{ return m_view_blocked_by_plunger; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getGraphicalViewBlockedByPlunger() const OVERRIDE
|
||||
{ return m_graphical_view_blocked_by_plunger; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime. */
|
||||
virtual void blockViewWithPlunger() OVERRIDE;
|
||||
|
@ -303,17 +303,12 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
m_gravity_center_shift.setZ(0);
|
||||
}
|
||||
|
||||
// In older STK versions the physical wheels where moved 'wheel_radius'
|
||||
// into the physical body (i.e. 'hypothetical' wheel shape would not
|
||||
// poke out of the physical shape). In order to make the karts a bit more
|
||||
// stable, the physical wheel position (i.e. location of raycast) were
|
||||
// moved to be on the corner of the shape. In order to retain the same
|
||||
// steering behaviour, the wheel base (which in turn determines the
|
||||
// turn angle at certain speeds) is shortened by 2*wheel_radius
|
||||
// Wheel radius was always 0.25, and is now not used anymore, but in order
|
||||
// to keep existing steering behaviour, the same formula is still
|
||||
// used.
|
||||
m_wheel_base = fabsf(m_kart_model->getLength() - 2*0.25f);
|
||||
// The longer the kart,the bigger its turn radius if using an identical
|
||||
// wheel base, exactly proportionally to its length.
|
||||
// The wheel base is used to compensate this
|
||||
// We divide by 1.425 to have a default turn radius which conforms
|
||||
// closely (+-0,1%) with the specifications in kart_characteristics.xml
|
||||
m_wheel_base = fabsf(m_kart_model->getLength()/1.425f);
|
||||
|
||||
m_shadow_material = material_manager->getMaterialSPM(m_shadow_file, "",
|
||||
"alphablend");
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/abstract_kart_animation.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/rescue_animation.hpp"
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/max_speed.hpp"
|
||||
@ -52,6 +53,7 @@ KartRewinder::KartRewinder(const std::string& ident,
|
||||
*/
|
||||
void KartRewinder::reset()
|
||||
{
|
||||
m_last_animation_end_ticks = -1;
|
||||
m_transfrom_from_network =
|
||||
btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
Kart::reset();
|
||||
@ -138,7 +140,9 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
buffer->add(trans.getOrigin());
|
||||
btQuaternion quat = trans.getRotation();
|
||||
buffer->add(quat);
|
||||
buffer->addUInt32(ka->getEndTicks());
|
||||
unsigned et = ka->getEndTicks() & 134217727;
|
||||
et |= ka->getAnimationType() << 27;
|
||||
buffer->addUInt32(et);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -207,10 +211,38 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
|
||||
if (has_animation)
|
||||
{
|
||||
int end_ticks = buffer->getUInt32();
|
||||
AbstractKartAnimation* ka = getKartAnimation();
|
||||
if (ka)
|
||||
ka->setEndTransformTicks(m_transfrom_from_network, end_ticks);
|
||||
unsigned et = buffer->getUInt32();
|
||||
int end_ticks = et & 134217727;
|
||||
KartAnimationType kat = (KartAnimationType)(et >> 27);
|
||||
if (!getKartAnimation() && end_ticks != m_last_animation_end_ticks)
|
||||
{
|
||||
Log::info("KartRewinder", "Creating animation %d from state", kat);
|
||||
switch (kat)
|
||||
{
|
||||
case KAT_RESCUE:
|
||||
new RescueAnimation(this, false/*is_auto_rescue*/,
|
||||
true/*from_state*/);
|
||||
break;
|
||||
case KAT_EXPLOSION_DIRECT_HIT:
|
||||
new ExplosionAnimation(this, getSmoothedXYZ(),
|
||||
true/*direct_hit*/, true/*from_state*/);
|
||||
break;
|
||||
case KAT_EXPLOSION:
|
||||
new ExplosionAnimation(this, getSmoothedXYZ(),
|
||||
false/*direct_hit*/, true/*from_state*/);
|
||||
break;
|
||||
default:
|
||||
Log::warn("KartRewinder", "Unknown animation %d from state",
|
||||
kat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (getKartAnimation())
|
||||
{
|
||||
getKartAnimation()->setEndTransformTicks(m_transfrom_from_network,
|
||||
end_ticks);
|
||||
}
|
||||
m_last_animation_end_ticks = end_ticks;
|
||||
}
|
||||
|
||||
Vec3 lv = buffer->getVec3();
|
||||
|
@ -33,6 +33,7 @@ private:
|
||||
btTransform m_transfrom_from_network;
|
||||
float m_prev_steering, m_steering_smoothing_dt, m_steering_smoothing_time;
|
||||
|
||||
int m_last_animation_end_ticks;
|
||||
public:
|
||||
KartRewinder(const std::string& ident, unsigned int world_kart_id,
|
||||
int position, const btTransform& init_transform,
|
||||
|
@ -40,7 +40,8 @@
|
||||
* and initialised the timer.
|
||||
* \param kart Pointer to the kart which is animated.
|
||||
*/
|
||||
RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
|
||||
RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue,
|
||||
bool from_state)
|
||||
: AbstractKartAnimation(kart, "RescueAnimation")
|
||||
{
|
||||
btTransform prev_trans = kart->getTrans();
|
||||
@ -89,8 +90,11 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
|
||||
}
|
||||
|
||||
// Clear powerups when rescue in CTF
|
||||
addNetworkAnimationChecker(race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG);
|
||||
if (!from_state)
|
||||
{
|
||||
addNetworkAnimationChecker(race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG);
|
||||
}
|
||||
} // RescueAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -49,9 +49,13 @@ protected:
|
||||
Referee *m_referee;
|
||||
|
||||
public:
|
||||
RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false);
|
||||
RescueAnimation(AbstractKart *kart,
|
||||
bool is_auto_rescue = false,
|
||||
bool from_state = false);
|
||||
float maximumHeight();
|
||||
virtual ~RescueAnimation();
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const { return KAT_RESCUE; }
|
||||
}; // RescueAnimation
|
||||
#endif
|
||||
|
@ -421,6 +421,7 @@ void Skidding::update(int ticks, bool is_on_ground,
|
||||
m_predicted_curve->setHeading(m_kart->getHeading());
|
||||
float angle = m_kart->getMaxSteerAngle(SPEED)
|
||||
* fabsf(getSteeringFraction());
|
||||
//FIXME : what is this for ?
|
||||
float r = kp->getWheelBase()
|
||||
/ asin(angle)*1.0f;
|
||||
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -1841,7 +1841,7 @@ void main_abort()
|
||||
{
|
||||
if (main_loop)
|
||||
{
|
||||
main_loop->abort();
|
||||
main_loop->requestAbort();
|
||||
}
|
||||
}
|
||||
#ifdef ANDROID
|
||||
@ -1936,8 +1936,11 @@ int main(int argc, char *argv[] )
|
||||
}
|
||||
else if (CommandLine::has("--lan-server", &s))
|
||||
{
|
||||
ProfileWorld::disableGraphics();
|
||||
UserConfigParams::m_enable_sound = false;
|
||||
if (no_graphics)
|
||||
{
|
||||
ProfileWorld::disableGraphics();
|
||||
UserConfigParams::m_enable_sound = false;
|
||||
}
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
ServerConfig::m_server_name = s;
|
||||
ServerConfig::m_wan_server = false;
|
||||
@ -2279,8 +2282,10 @@ int main(int argc, char *argv[] )
|
||||
{
|
||||
Log::closeOutputFiles();
|
||||
#endif
|
||||
#ifndef ANDROID
|
||||
fclose(stderr);
|
||||
fclose(stdout);
|
||||
#endif
|
||||
#ifndef WIN32
|
||||
}
|
||||
#endif
|
||||
@ -2336,6 +2341,9 @@ static void cleanSuperTuxKart()
|
||||
if(unlock_manager) delete unlock_manager;
|
||||
Online::ProfileManager::destroy();
|
||||
GUIEngine::DialogQueue::deallocate();
|
||||
GUIEngine::clear();
|
||||
GUIEngine::cleanUp();
|
||||
GUIEngine::clearScreenCache();
|
||||
if(font_manager) delete font_manager;
|
||||
|
||||
// Now finish shutting down objects which a separate thread. The
|
||||
@ -2349,7 +2357,8 @@ static void cleanSuperTuxKart()
|
||||
#ifndef SERVER_ONLY
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
if(!NewsManager::get()->waitForReadyToDeleted(2.0f))
|
||||
if (UserConfigParams::m_internet_status == Online::RequestManager::
|
||||
IPERM_ALLOWED && !NewsManager::get()->waitForReadyToDeleted(2.0f))
|
||||
{
|
||||
Log::info("Thread", "News manager not stopping, exiting anyway.");
|
||||
}
|
||||
|
@ -65,7 +65,8 @@ LRESULT CALLBACK separateProcessProc(_In_ HWND hwnd, _In_ UINT uMsg,
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
MainLoop::MainLoop(unsigned parent_pid)
|
||||
: m_abort(false), m_ticks_adjustment(0), m_parent_pid(parent_pid)
|
||||
: m_abort(false), m_request_abort(false), m_ticks_adjustment(0),
|
||||
m_parent_pid(parent_pid)
|
||||
{
|
||||
m_curr_time = 0;
|
||||
m_prev_time = 0;
|
||||
@ -307,16 +308,22 @@ void MainLoop::run()
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
if (msg.message == WM_QUIT)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
// If parent is killed, abort the child main loop too
|
||||
if (WaitForSingleObject(parent, 0) != WAIT_TIMEOUT)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// POSIX equivalent
|
||||
if (m_parent_pid != 0 && getppid() != (int)m_parent_pid)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
#endif
|
||||
PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);
|
||||
|
||||
@ -327,17 +334,28 @@ void MainLoop::run()
|
||||
|
||||
// Shutdown next frame if shutdown request is sent while loading the
|
||||
// world
|
||||
if (STKHost::existHost() && STKHost::get()->requestedShutdown())
|
||||
if ((STKHost::existHost() && STKHost::get()->requestedShutdown()) ||
|
||||
m_request_abort)
|
||||
{
|
||||
SFXManager::get()->quickSound("anvil");
|
||||
bool exist_host = STKHost::existHost();
|
||||
core::stringw msg = _("Server connection timed out.");
|
||||
if (!STKHost::get()->getErrorMessage().empty())
|
||||
|
||||
if (!m_request_abort)
|
||||
{
|
||||
msg = STKHost::get()->getErrorMessage();
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
SFXManager::get()->quickSound("anvil");
|
||||
if (!STKHost::get()->getErrorMessage().empty())
|
||||
{
|
||||
msg = STKHost::get()->getErrorMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exist_host == true)
|
||||
{
|
||||
STKHost::get()->shutdown();
|
||||
}
|
||||
STKHost::get()->shutdown();
|
||||
// In case the user opened a race pause dialog
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (CVS->isGLSL())
|
||||
@ -350,19 +368,32 @@ void MainLoop::run()
|
||||
irr_driver->getActualScreenSize().Height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// In case the user opened a race pause dialog
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
if (World::getWorld())
|
||||
{
|
||||
race_manager->clearNetworkGrandPrixResult();
|
||||
race_manager->exitRace();
|
||||
}
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
|
||||
if (exist_host == true)
|
||||
{
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
}
|
||||
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
}
|
||||
|
||||
if (m_request_abort)
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
}
|
||||
|
||||
if (!m_abort)
|
||||
@ -392,84 +423,96 @@ void MainLoop::run()
|
||||
PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
|
||||
Online::RequestManager::get()->update(frame_duration);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
m_ticks_adjustment.lock();
|
||||
if (m_ticks_adjustment.getData() != 0)
|
||||
{
|
||||
if (m_ticks_adjustment.getData() > 0)
|
||||
m_ticks_adjustment.lock();
|
||||
if (m_ticks_adjustment.getData() != 0)
|
||||
{
|
||||
num_steps += m_ticks_adjustment.getData();
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
else if (m_ticks_adjustment.getData() < 0)
|
||||
{
|
||||
int new_steps = num_steps + m_ticks_adjustment.getData();
|
||||
if (new_steps < 0)
|
||||
if (m_ticks_adjustment.getData() > 0)
|
||||
{
|
||||
num_steps = 0;
|
||||
m_ticks_adjustment.getData() = new_steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_steps = new_steps;
|
||||
num_steps += m_ticks_adjustment.getData();
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ticks_adjustment.unlock();
|
||||
|
||||
for(int i=0; i<num_steps; i++)
|
||||
{
|
||||
if (World::getWorld() && history->replayHistory())
|
||||
history->updateReplay(World::getWorld()->getTicksSinceStart());
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update",
|
||||
0x7F, 0x00, 0x7F);
|
||||
if (auto pm = ProtocolManager::lock())
|
||||
{
|
||||
pm->update(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
|
||||
if (World::getWorld()) updateRace(1);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// We need to check again because update_race may have requested
|
||||
// the main loop to abort; and it's not a good idea to continue
|
||||
// since the GUI engine is no more to be called then.
|
||||
if (m_abort) break;
|
||||
|
||||
if (m_frame_before_loading_world)
|
||||
{
|
||||
m_frame_before_loading_world = false;
|
||||
break;
|
||||
}
|
||||
if (World::getWorld())
|
||||
{
|
||||
if (World::getWorld()->getPhase() == WorldStatus::SETUP_PHASE)
|
||||
else if (m_ticks_adjustment.getData() < 0)
|
||||
{
|
||||
// Skip the large num steps contributed by loading time
|
||||
World::getWorld()->updateTime(1);
|
||||
int new_steps = num_steps + m_ticks_adjustment.getData();
|
||||
if (new_steps < 0)
|
||||
{
|
||||
num_steps = 0;
|
||||
m_ticks_adjustment.getData() = new_steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_steps = new_steps;
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ticks_adjustment.unlock();
|
||||
|
||||
for (int i = 0; i < num_steps; i++)
|
||||
{
|
||||
if (World::getWorld() && history->replayHistory())
|
||||
{
|
||||
history->updateReplay(
|
||||
World::getWorld()->getTicksSinceStart());
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update",
|
||||
0x7F, 0x00, 0x7F);
|
||||
if (auto pm = ProtocolManager::lock())
|
||||
{
|
||||
pm->update(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
|
||||
if (World::getWorld())
|
||||
{
|
||||
updateRace(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// We need to check again because update_race may have requested
|
||||
// the main loop to abort; and it's not a good idea to continue
|
||||
// since the GUI engine is no more to be called then.
|
||||
if (m_abort || m_request_abort)
|
||||
break;
|
||||
|
||||
if (m_frame_before_loading_world)
|
||||
{
|
||||
m_frame_before_loading_world = false;
|
||||
break;
|
||||
}
|
||||
World::getWorld()->updateTime(1);
|
||||
}
|
||||
} // for i < num_steps
|
||||
|
||||
if (World::getWorld())
|
||||
{
|
||||
if (World::getWorld()->getPhase()==WorldStatus::SETUP_PHASE)
|
||||
{
|
||||
// Skip the large num steps contributed by loading time
|
||||
World::getWorld()->updateTime(1);
|
||||
break;
|
||||
}
|
||||
World::getWorld()->updateTime(1);
|
||||
}
|
||||
} // for i < num_steps
|
||||
|
||||
// Handle controller the last to avoid slow PC sending actions too late
|
||||
if (!m_abort)
|
||||
{
|
||||
// Handle controller the last to avoid slow PC sending actions too
|
||||
// late
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
// User aborted (e.g. closed window)
|
||||
bool abort = !irr_driver->getDevice()->run();
|
||||
|
||||
if (abort)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto gp = GameProtocol::lock())
|
||||
{
|
||||
gp->sendActions();
|
||||
}
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER(); // MainLoop pop
|
||||
PROFILER_SYNC_FRAME();
|
||||
@ -482,12 +525,4 @@ void MainLoop::run()
|
||||
|
||||
} // run
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Set the abort flag, causing the mainloop to be left.
|
||||
*/
|
||||
void MainLoop::abort()
|
||||
{
|
||||
m_abort = true;
|
||||
} // abort
|
||||
|
||||
/* EOF */
|
||||
|
@ -31,6 +31,8 @@ class MainLoop
|
||||
private:
|
||||
/** True if the main loop should exit. */
|
||||
std::atomic_bool m_abort;
|
||||
|
||||
std::atomic_bool m_request_abort;
|
||||
|
||||
/** True if the frame rate should be throttled. */
|
||||
bool m_throttle_fps;
|
||||
@ -48,7 +50,9 @@ public:
|
||||
MainLoop(unsigned parent_pid);
|
||||
~MainLoop();
|
||||
void run();
|
||||
void abort();
|
||||
/** Set the abort flag, causing the mainloop to be left. */
|
||||
void abort() { m_abort = true; }
|
||||
void requestAbort() { m_request_abort = true; }
|
||||
void setThrottleFPS(bool throttle) { m_throttle_fps = throttle; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if STK is to be stoppe. */
|
||||
|
@ -196,3 +196,14 @@ video::SColor FreeForAll::getColor(unsigned int kart_id) const
|
||||
{
|
||||
return GUIEngine::getSkin()->getColor("font::normal");
|
||||
} // getColor
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool FreeForAll::getKartFFAResult(int kart_id) const
|
||||
{
|
||||
// the kart(s) which has the top score wins
|
||||
AbstractKart* k = getKartAtPosition(1);
|
||||
if (!k)
|
||||
return false;
|
||||
int top_score = getKartScore(k->getWorldKartId());
|
||||
return getKartScore(kart_id) == top_score;
|
||||
} // getKartFFAResult
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
void setKartScoreFromServer(NetworkString& ns);
|
||||
// ------------------------------------------------------------------------
|
||||
int getKartScore(int kart_id) const { return m_scores.at(kart_id); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool getKartFFAResult(int kart_id) const;
|
||||
}; // FreeForAll
|
||||
|
||||
|
||||
|
@ -598,7 +598,8 @@ void LinearWorld::getKartsDisplayInfo(
|
||||
|
||||
// Don't compare times when crossing the start line first
|
||||
if(laps_of_leader>0 &&
|
||||
(getTimeTicks() - getTicksAtLapForKart(kart->getWorldKartId())<5||
|
||||
(getTimeTicks() - getTicksAtLapForKart(kart->getWorldKartId()) <
|
||||
stk_config->time2Ticks(8) ||
|
||||
rank_info.lap != laps_of_leader) &&
|
||||
raceHasLaps())
|
||||
{ // Display for 5 seconds
|
||||
|
@ -229,8 +229,8 @@ void World::init()
|
||||
global_player_id, race_manager->getKartType(i),
|
||||
race_manager->getPlayerDifficulty(i));
|
||||
}
|
||||
new_kart->setBoostAI(race_manager->hasBoostedAI(i));
|
||||
m_karts.push_back(new_kart);
|
||||
|
||||
} // for i
|
||||
|
||||
// Load other custom models if needed
|
||||
@ -587,6 +587,9 @@ void World::onGo()
|
||||
*/
|
||||
void World::terminateRace()
|
||||
{
|
||||
// In case the user opened paused dialog in network
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
m_schedule_pause = false;
|
||||
m_schedule_unpause = false;
|
||||
|
||||
|
@ -93,6 +93,7 @@
|
||||
*/
|
||||
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||
{
|
||||
m_last_success_poll_time.store(StkTime::getRealTimeMs() + 30000);
|
||||
m_waiting_players_counts.store(0);
|
||||
m_server_owner_id.store(-1);
|
||||
m_registered_for_once_only = false;
|
||||
@ -110,7 +111,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||
m_result_ns = getNetworkString();
|
||||
m_result_ns->setSynchronous(true);
|
||||
m_waiting_for_reset = false;
|
||||
m_server_id_online = 0;
|
||||
m_server_id_online.store(0);
|
||||
} // ServerLobby
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -356,7 +357,7 @@ void ServerLobby::createServerIdFile()
|
||||
if (!sid.empty() && !m_has_created_server_id_file)
|
||||
{
|
||||
std::fstream fs;
|
||||
sid += StringUtils::toString(m_server_id_online) + "_" +
|
||||
sid += StringUtils::toString(m_server_id_online.load()) + "_" +
|
||||
StringUtils::toString(STKHost::get()->getPrivatePort());
|
||||
fs.open(sid, std::ios::out);
|
||||
fs.close();
|
||||
@ -384,6 +385,14 @@ void ServerLobby::asynchronousUpdate()
|
||||
handlePendingConnection();
|
||||
}
|
||||
|
||||
if (NetworkConfig::get()->isWAN() &&
|
||||
allowJoinedPlayersWaiting() && m_server_recovering.expired() &&
|
||||
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000)
|
||||
{
|
||||
Log::warn("ServerLobby", "Trying auto server recovery.");
|
||||
registerServer(false/*now*/);
|
||||
}
|
||||
|
||||
switch (m_state.load())
|
||||
{
|
||||
case SET_PUBLIC_ADDRESS:
|
||||
@ -420,7 +429,7 @@ void ServerLobby::asynchronousUpdate()
|
||||
// Register this server with the STK server. This will block
|
||||
// this thread, because there is no need for the protocol manager
|
||||
// to react to any requests before the server is registered.
|
||||
if (registerServer())
|
||||
if (registerServer(true/*now*/))
|
||||
{
|
||||
if (allowJoinedPlayersWaiting())
|
||||
m_registered_for_once_only = true;
|
||||
@ -690,12 +699,56 @@ void ServerLobby::update(int ticks)
|
||||
* ProtocolManager thread). The information about this client is added
|
||||
* to the table 'server'.
|
||||
*/
|
||||
bool ServerLobby::registerServer()
|
||||
bool ServerLobby::registerServer(bool now)
|
||||
{
|
||||
while (!m_server_unregistered.expired())
|
||||
while (now && !m_server_unregistered.expired())
|
||||
StkTime::sleep(1);
|
||||
|
||||
Online::XMLRequest *request = new Online::XMLRequest();
|
||||
// ========================================================================
|
||||
class RegisterServerRequest : public Online::XMLRequest
|
||||
{
|
||||
private:
|
||||
std::weak_ptr<ServerLobby> m_server_lobby;
|
||||
protected:
|
||||
virtual void afterOperation()
|
||||
{
|
||||
Online::XMLRequest::afterOperation();
|
||||
const XMLNode* result = getXMLData();
|
||||
std::string rec_success;
|
||||
auto sl = m_server_lobby.lock();
|
||||
if (!sl)
|
||||
return;
|
||||
|
||||
if (result->get("success", &rec_success) &&
|
||||
rec_success == "yes")
|
||||
{
|
||||
const XMLNode* server = result->getNode("server");
|
||||
assert(server);
|
||||
const XMLNode* server_info = server->getNode("server-info");
|
||||
assert(server_info);
|
||||
unsigned server_id_online = 0;
|
||||
server_info->get("id", &server_id_online);
|
||||
assert(server_id_online != 0);
|
||||
Log::info("ServerLobby",
|
||||
"Server %d is now online.", server_id_online);
|
||||
sl->m_server_id_online.store(server_id_online);
|
||||
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
|
||||
return;
|
||||
}
|
||||
Log::error("ServerLobby", "%s",
|
||||
StringUtils::wideToUtf8(getInfo()).c_str());
|
||||
// For auto server recovery wait 3 seconds for next try
|
||||
// This sleep only the request manager thread
|
||||
if (manageMemory())
|
||||
StkTime::sleep(3000);
|
||||
}
|
||||
public:
|
||||
RegisterServerRequest(bool now, std::shared_ptr<ServerLobby> sl)
|
||||
: XMLRequest(!now/*manage memory*/), m_server_lobby(sl) {}
|
||||
}; // RegisterServerRequest
|
||||
|
||||
RegisterServerRequest *request = new RegisterServerRequest(now,
|
||||
std::dynamic_pointer_cast<ServerLobby>(shared_from_this()));
|
||||
NetworkConfig::get()->setServerDetails(request, "create");
|
||||
request->addParameter("address", m_server_address.getIP() );
|
||||
request->addParameter("port", m_server_address.getPort() );
|
||||
@ -715,29 +768,19 @@ bool ServerLobby::registerServer()
|
||||
Log::info("ServerLobby", "Public server address %s",
|
||||
m_server_address.toString().c_str());
|
||||
|
||||
request->executeNow();
|
||||
|
||||
const XMLNode* result = request->getXMLData();
|
||||
std::string rec_success;
|
||||
|
||||
if (result->get("success", &rec_success) && rec_success == "yes")
|
||||
if (now)
|
||||
{
|
||||
const XMLNode* server = result->getNode("server");
|
||||
assert(server);
|
||||
const XMLNode* server_info = server->getNode("server-info");
|
||||
assert(server_info);
|
||||
server_info->get("id", &m_server_id_online);
|
||||
assert(m_server_id_online != 0);
|
||||
Log::info("ServerLobby",
|
||||
"Server %d is now online.", m_server_id_online);
|
||||
request->executeNow();
|
||||
delete request;
|
||||
return true;
|
||||
if (m_server_id_online.load() == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
irr::core::stringc error(request->getInfo().c_str());
|
||||
Log::error("ServerLobby", "%s", error.c_str());
|
||||
delete request;
|
||||
return false;
|
||||
else
|
||||
{
|
||||
request->queue();
|
||||
m_server_recovering = request->observeExistence();
|
||||
}
|
||||
return true;
|
||||
} // registerServer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -811,7 +854,7 @@ void ServerLobby::startSelection(const Event *event)
|
||||
if (!allowJoinedPlayersWaiting())
|
||||
{
|
||||
ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION);
|
||||
if (NetworkConfig::get()->isWAN() )
|
||||
if (NetworkConfig::get()->isWAN())
|
||||
{
|
||||
unregisterServer(false/*now*/);
|
||||
}
|
||||
@ -903,7 +946,9 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
// First poll every 5 seconds. Return if no polling needs to be done.
|
||||
const uint64_t POLL_INTERVAL = 5000;
|
||||
static uint64_t last_poll_time = 0;
|
||||
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL)
|
||||
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL ||
|
||||
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000 ||
|
||||
m_server_id_online.load() == 0)
|
||||
return;
|
||||
|
||||
// Keep the port open, it can be sent to anywhere as we will send to the
|
||||
@ -927,12 +972,13 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
virtual void afterOperation()
|
||||
{
|
||||
Online::XMLRequest::afterOperation();
|
||||
const XMLNode *result = getXMLData();
|
||||
const XMLNode* result = getXMLData();
|
||||
std::string success;
|
||||
|
||||
if (!result->get("success", &success) || success != "yes")
|
||||
{
|
||||
Log::error("ServerLobby", "Cannot retrieve the list.");
|
||||
Log::error("ServerLobby", "Poll server request failed: %s",
|
||||
StringUtils::wideToUtf8(getInfo()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -942,6 +988,7 @@ void ServerLobby::checkIncomingConnectionRequests()
|
||||
auto sl = m_server_lobby.lock();
|
||||
if (!sl)
|
||||
return;
|
||||
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
|
||||
if (sl->m_state.load() != WAITING_FOR_START_GAME &&
|
||||
!sl->allowJoinedPlayersWaiting())
|
||||
{
|
||||
|
@ -95,6 +95,8 @@ private:
|
||||
/** It indicates if this server is unregistered with the stk server. */
|
||||
std::weak_ptr<bool> m_server_unregistered;
|
||||
|
||||
std::weak_ptr<bool> m_server_recovering;
|
||||
|
||||
/** Timeout counter for various state. */
|
||||
std::atomic<int64_t> m_timeout;
|
||||
|
||||
@ -148,9 +150,11 @@ private:
|
||||
|
||||
std::atomic<uint32_t> m_waiting_players_counts;
|
||||
|
||||
std::atomic<uint64_t> m_last_success_poll_time;
|
||||
|
||||
uint64_t m_server_started_at, m_server_delay;
|
||||
|
||||
unsigned m_server_id_online;
|
||||
std::atomic<uint32_t> m_server_id_online;
|
||||
|
||||
bool m_registered_for_once_only;
|
||||
|
||||
@ -164,7 +168,7 @@ private:
|
||||
// Track(s) votes
|
||||
void playerVote(Event *event);
|
||||
void playerFinishedResult(Event *event);
|
||||
bool registerServer();
|
||||
bool registerServer(bool now);
|
||||
void finishedLoadingWorldClient(Event *event);
|
||||
void kickHost(Event* event);
|
||||
void changeTeam(Event* event);
|
||||
|
@ -51,6 +51,7 @@ FloatServerConfigParam::FloatServerConfigParam(float default_value,
|
||||
const char* comment)
|
||||
: FloatUserConfigParam(param_name, comment)
|
||||
{
|
||||
m_can_be_deleted = false;
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
g_server_params.push_back(this);
|
||||
@ -62,6 +63,7 @@ IntServerConfigParam::IntServerConfigParam(int default_value,
|
||||
const char* comment)
|
||||
: IntUserConfigParam(param_name, comment)
|
||||
{
|
||||
m_can_be_deleted = false;
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
g_server_params.push_back(this);
|
||||
@ -73,6 +75,7 @@ BoolServerConfigParam::BoolServerConfigParam(bool default_value,
|
||||
const char* comment)
|
||||
: BoolUserConfigParam(param_name, comment)
|
||||
{
|
||||
m_can_be_deleted = false;
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
g_server_params.push_back(this);
|
||||
@ -84,6 +87,7 @@ StringServerConfigParam::StringServerConfigParam(std::string default_value,
|
||||
const char* comment)
|
||||
: StringUserConfigParam(param_name, comment)
|
||||
{
|
||||
m_can_be_deleted = false;
|
||||
m_value = default_value;
|
||||
m_default_value = default_value;
|
||||
g_server_params.push_back(this);
|
||||
@ -132,7 +136,7 @@ void loadServerConfigXML(const XMLNode* root)
|
||||
return;
|
||||
}
|
||||
|
||||
int config_file_version = -1;
|
||||
/*int config_file_version = -1;
|
||||
if (root->get("version", &config_file_version) < 1 ||
|
||||
config_file_version < stk_config->m_min_server_version ||
|
||||
config_file_version > stk_config->m_max_server_version)
|
||||
@ -142,7 +146,7 @@ void loadServerConfigXML(const XMLNode* root)
|
||||
delete root;
|
||||
writeServerConfigToDisk();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
for (unsigned i = 0; i < g_server_params.size(); i++)
|
||||
g_server_params[i]->findYourDataInAChildOf(root);
|
||||
|
@ -269,7 +269,7 @@ namespace ServerConfig
|
||||
|
||||
// ========================================================================
|
||||
/** Server version, will be advanced if there are protocol changes. */
|
||||
static const uint32_t m_server_version = 1;
|
||||
static const uint32_t m_server_version = 2;
|
||||
// ========================================================================
|
||||
void loadServerConfig(const std::string& path = "");
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -308,7 +308,6 @@ void STKHost::init()
|
||||
{
|
||||
m_network_timer.store(StkTime::getRealTimeMs());
|
||||
m_shutdown = false;
|
||||
m_shutdown_delay = 0;
|
||||
m_authorised = false;
|
||||
m_network = NULL;
|
||||
m_exit_timeout.store(std::numeric_limits<uint64_t>::max());
|
||||
@ -635,8 +634,7 @@ void STKHost::setErrorMessage(const irr::core::stringw &message)
|
||||
{
|
||||
if (!message.empty())
|
||||
{
|
||||
irr::core::stringc s(message.c_str());
|
||||
Log::error("STKHost", "%s", s.c_str());
|
||||
Log::error("STKHost", "%s", StringUtils::wideToUtf8(message).c_str());
|
||||
}
|
||||
m_error_message = message;
|
||||
} // setErrorMessage
|
||||
|
@ -117,9 +117,6 @@ private:
|
||||
* triggers a shutdown of the STKHost (and the Protocolmanager). */
|
||||
std::atomic_bool m_shutdown;
|
||||
|
||||
/** Used as a timeout for shedule shutdown. */
|
||||
std::atomic<uint64_t> m_shutdown_delay;
|
||||
|
||||
/** True if this local host is authorised to control a server. */
|
||||
std::atomic_bool m_authorised;
|
||||
|
||||
@ -211,21 +208,8 @@ public:
|
||||
void requestShutdown()
|
||||
{
|
||||
m_shutdown.store(true);
|
||||
m_shutdown_delay.store(0);
|
||||
} // requestExit
|
||||
//-------------------------------------------------------------------------
|
||||
void requestShutdownDelayed(int delay)
|
||||
{
|
||||
m_shutdown.store(true);
|
||||
m_shutdown_delay.store(StkTime::getRealTimeMs() + delay);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void cancelShutdown()
|
||||
{
|
||||
m_shutdown.store(false);
|
||||
m_shutdown_delay.store(0);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void shutdown();
|
||||
//-------------------------------------------------------------------------
|
||||
void sendPacketToAllPeersInServer(NetworkString *data,
|
||||
@ -282,11 +266,7 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if a shutdown of the network infrastructure was
|
||||
* requested. */
|
||||
bool requestedShutdown() const
|
||||
{
|
||||
return m_shutdown.load() &&
|
||||
m_shutdown_delay.load() < StkTime::getRealTimeMs();
|
||||
}
|
||||
bool requestedShutdown() const { return m_shutdown.load(); }
|
||||
// ------------------------------------------------------------------------
|
||||
int receiveRawPacket(char *buffer, int buffer_len,
|
||||
TransportAddress* sender, int max_tries = -1)
|
||||
|
@ -326,7 +326,11 @@ namespace Online
|
||||
setProgress(-1.0f);
|
||||
|
||||
Request::afterOperation();
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
if (m_curl_session)
|
||||
{
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
m_curl_session = NULL;
|
||||
}
|
||||
} // afterOperation
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -63,7 +63,7 @@ namespace Online
|
||||
std::string m_filename;
|
||||
|
||||
/** Pointer to the curl data structure for this request. */
|
||||
CURL *m_curl_session;
|
||||
CURL *m_curl_session = NULL;
|
||||
|
||||
/** curl return code. */
|
||||
CURLcode m_curl_code;
|
||||
@ -93,7 +93,14 @@ namespace Online
|
||||
int priority = 1);
|
||||
HTTPRequest(const char * const filename, bool manage_memory = false,
|
||||
int priority = 1);
|
||||
virtual ~HTTPRequest() {}
|
||||
virtual ~HTTPRequest()
|
||||
{
|
||||
if (m_curl_session)
|
||||
{
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
m_curl_session = NULL;
|
||||
}
|
||||
}
|
||||
virtual bool isAllowedToAdd() const OVERRIDE;
|
||||
void setApiURL(const std::string& url, const std::string &action);
|
||||
void setAddonsURL(const std::string& path);
|
||||
|
@ -213,7 +213,13 @@ namespace Online
|
||||
me->m_current_request->execute();
|
||||
// This test is necessary in case that execute() was aborted
|
||||
// (otherwise the assert in addResult will be triggered).
|
||||
if (!me->getAbort()) me->addResult(me->m_current_request);
|
||||
if (!me->getAbort())
|
||||
me->addResult(me->m_current_request);
|
||||
else if (me->m_current_request->manageMemory())
|
||||
{
|
||||
delete me->m_current_request;
|
||||
me->m_current_request = NULL;
|
||||
}
|
||||
me->m_request_queue.lock();
|
||||
} // while handle all requests
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "LinearMath/btIDebugDraw.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
#include "karts/kart_model.hpp"
|
||||
@ -51,12 +50,6 @@ btKart::btKart(btRigidBody* chassis, btVehicleRaycaster* raycaster,
|
||||
Kart *kart)
|
||||
: m_vehicleRaycaster(raycaster)
|
||||
{
|
||||
btScalar height = 0;
|
||||
for (int i=0;i<stk_config->time2Ticks(HISTORY_TIME);i++)
|
||||
{
|
||||
m_ground_height.push_back(height);
|
||||
}
|
||||
|
||||
m_chassisBody = chassis;
|
||||
m_indexRightAxis = 0;
|
||||
m_indexUpAxis = 1;
|
||||
@ -127,10 +120,6 @@ void btKart::reset()
|
||||
wheel.m_raycastInfo.m_suspensionLength = 0;
|
||||
updateWheelTransform(i, true);
|
||||
}
|
||||
for (int i=0;i<stk_config->time2Ticks(HISTORY_TIME);i++)
|
||||
{
|
||||
m_ground_height[i] = 0;
|
||||
}
|
||||
m_visual_wheels_touch_ground = false;
|
||||
m_allow_sliding = false;
|
||||
m_num_wheels_on_ground = 0;
|
||||
@ -141,7 +130,6 @@ void btKart::reset()
|
||||
m_max_speed = -1.0f;
|
||||
m_min_speed = 0.0f;
|
||||
m_cushioning_disable_time = 0;
|
||||
m_new_ground_height = 999.9f;
|
||||
|
||||
// Set the brakes so that karts don't slide downhill
|
||||
setAllBrakes(5.0f);
|
||||
@ -289,10 +277,10 @@ btScalar btKart::rayCast(unsigned int index, float fraction)
|
||||
btScalar max_susp_len = wheel.getSuspensionRestLength()
|
||||
+ wheel.m_maxSuspensionTravel;
|
||||
|
||||
// Do a longer raycast to see if the kart might soon hit the
|
||||
// Do a slightly longer raycast to see if the kart might soon hit the
|
||||
// ground and some 'cushioning' is needed to avoid that the chassis
|
||||
// hits the ground.
|
||||
btScalar raylen = max_susp_len*10 + 0.5f;
|
||||
btScalar raylen = max_susp_len + 0.5f;
|
||||
|
||||
btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
|
||||
const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
|
||||
@ -308,9 +296,6 @@ btScalar btKart::rayCast(unsigned int index, float fraction)
|
||||
wheel.m_raycastInfo.m_groundObject = 0;
|
||||
|
||||
btScalar depth = raylen * rayResults.m_distFraction;
|
||||
|
||||
if (depth < m_new_ground_height)
|
||||
m_new_ground_height = depth;
|
||||
if (object && depth < max_susp_len)
|
||||
{
|
||||
wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
|
||||
@ -532,7 +517,6 @@ void btKart::updateVehicle( btScalar step )
|
||||
if(m_cushioning_disable_time>0) m_cushioning_disable_time --;
|
||||
|
||||
bool needed_cushioning = false;
|
||||
|
||||
btVector3 v =
|
||||
m_chassisBody->getVelocityInLocalPoint(m_wheelInfo[wheel_index]
|
||||
.m_chassisConnectionPointCS);
|
||||
@ -543,7 +527,7 @@ void btKart::updateVehicle( btScalar step )
|
||||
|
||||
#ifdef DEBUG_CUSHIONING
|
||||
Log::verbose("physics",
|
||||
"World %d wheel %d lsuspl %f vdown %f overall speed %f length %f",
|
||||
"World %d wheel %d lsuspl %f vdown %f overall speed %f lenght %f",
|
||||
World::getWorld()->getTimeTicks(),
|
||||
wheel_index,
|
||||
m_wheelInfo[wheel_index].m_raycastInfo.m_suspensionLength,
|
||||
@ -551,14 +535,6 @@ void btKart::updateVehicle( btScalar step )
|
||||
-v_down.getY() + 9.8*step,
|
||||
step * (-v_down.getY() + 9.8*step)+offset);
|
||||
#endif
|
||||
// Update the ground height history
|
||||
for (int i=stk_config->time2Ticks(HISTORY_TIME)-1;i>0;i--)
|
||||
{
|
||||
m_ground_height[i] = m_ground_height[i-1];
|
||||
}
|
||||
m_ground_height[0] = m_new_ground_height;
|
||||
m_new_ground_height = 999.9f;
|
||||
|
||||
// If the kart is falling, estimate the distance the kart will fall
|
||||
// in the next time step: the speed gets increased by the gravity*dt.
|
||||
// This approximation is still not good enough (either because of
|
||||
@ -567,25 +543,19 @@ void btKart::updateVehicle( btScalar step )
|
||||
// predict the upcoming collision correcty - so we add an offset
|
||||
// to the predicted kart movement, which was found experimentally:
|
||||
btScalar gravity = m_chassisBody->getGravity().length();
|
||||
|
||||
btScalar predicted_fall = -v_down.getY() + gravity*step +
|
||||
(m_ground_height[stk_config->time2Ticks(HISTORY_TIME)-1]
|
||||
-m_ground_height[0])/stk_config->time2Ticks(HISTORY_TIME);
|
||||
|
||||
if (v_down.getY()<0 && m_cushioning_disable_time==0 &&
|
||||
m_ground_height[0] < step*predicted_fall + offset &&
|
||||
m_ground_height[0] > 0 &&
|
||||
m_ground_height[stk_config->time2Ticks(HISTORY_TIME)-1] > 0.4)
|
||||
m_wheelInfo[wheel_index].m_raycastInfo.m_suspensionLength
|
||||
< step * (-v_down.getY()+gravity*step)+offset)
|
||||
{
|
||||
// Disable more cushioning for 1 second. This avoids the problem
|
||||
// of hovering: a kart gets cushioned on a down-sloping area, still
|
||||
// moves forwards, gets cushioned again etc. --> kart is hovering
|
||||
// and not controllable.
|
||||
m_cushioning_disable_time = stk_config->time2Ticks(1);
|
||||
m_cushioning_disable_time = 120;
|
||||
|
||||
needed_cushioning = true;
|
||||
btVector3 impulse = down * predicted_fall
|
||||
/ m_chassisBody->getInvMass();
|
||||
btVector3 impulse = down * (-v_down.getY() + gravity*step)
|
||||
/ m_chassisBody->getInvMass();
|
||||
#ifdef DEBUG_CUSHIONING
|
||||
float v_old = m_chassisBody->getLinearVelocity().getY();
|
||||
#endif
|
||||
@ -593,13 +563,12 @@ void btKart::updateVehicle( btScalar step )
|
||||
#ifdef DEBUG_CUSHIONING
|
||||
Log::verbose("physics",
|
||||
"World %d Cushioning imp %f vdown %f from %f m/s to %f m/s "
|
||||
"height %f contact %f kart %f susp %f relspeed %f",
|
||||
"contact %f kart %f susp %f relspeed %f",
|
||||
World::getWorld()->getTimeTicks(),
|
||||
impulse.getY(),
|
||||
-v_down.getY(),
|
||||
v_old,
|
||||
m_chassisBody->getLinearVelocity().getY(),
|
||||
m_ground_height[0],
|
||||
m_wheelInfo[wheel_index].m_raycastInfo.m_isInContact ?
|
||||
m_wheelInfo[wheel_index].m_raycastInfo.m_contactPointWS.getY()
|
||||
: -100,
|
||||
|
@ -11,8 +11,6 @@
|
||||
#ifndef BT_KART_HPP
|
||||
#define BT_KART_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||
#include "physics/btKartRaycast.hpp"
|
||||
@ -119,13 +117,6 @@ private:
|
||||
* physics steps, so need to be set again by the application. */
|
||||
btScalar m_max_speed;
|
||||
|
||||
/** Smallest wheel height to the ground, with a few frames of history */
|
||||
std::vector<btScalar> m_ground_height;
|
||||
const float HISTORY_TIME = 0.05f;
|
||||
|
||||
/** Used to get the smallest weel height in the current frame */
|
||||
btScalar m_new_ground_height;
|
||||
|
||||
/** True if the visual wheels touch the ground. */
|
||||
bool m_visual_wheels_touch_ground;
|
||||
|
||||
@ -301,3 +292,4 @@ public:
|
||||
}; // class btKart
|
||||
|
||||
#endif //BT_KART_HPP
|
||||
|
||||
|
@ -354,13 +354,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
|
||||
case MP_EXACT:
|
||||
{
|
||||
extend.setY(0);
|
||||
|
||||
// In case of readonly materials we have to get the material from
|
||||
// the mesh, otherwise from the node. This is esp. important for
|
||||
// water nodes, which only have the material defined in the node,
|
||||
// but not in the mesh at all!
|
||||
bool is_readonly_material = false;
|
||||
|
||||
scene::IMesh* mesh = NULL;
|
||||
switch (presentation->getNode()->getType())
|
||||
{
|
||||
@ -371,7 +364,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
|
||||
scene::IMeshSceneNode *node =
|
||||
(scene::IMeshSceneNode*)presentation->getNode();
|
||||
mesh = node->getMesh();
|
||||
is_readonly_material = node->isReadOnlyMaterials();
|
||||
break;
|
||||
}
|
||||
case scene::ESNT_ANIMATED_MESH :
|
||||
@ -380,7 +372,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
|
||||
scene::IAnimatedMeshSceneNode *node =
|
||||
(scene::IAnimatedMeshSceneNode*)presentation->getNode();
|
||||
mesh = node->getMesh()->getMesh(0);
|
||||
is_readonly_material = node->isReadOnlyMaterials();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -436,27 +427,27 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
|
||||
mb->getVertexType());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle readonly materials correctly: mb->getMaterial can return
|
||||
// NULL if the node is not using readonly materials. E.g. in case
|
||||
// of a water scene node, the mesh (which is the animated copy of
|
||||
// the original mesh) does not contain any material information,
|
||||
// the material is only available in the node.
|
||||
const video::SMaterial &irrMaterial =
|
||||
is_readonly_material ? mb->getMaterial()
|
||||
: presentation->getNode()->getMaterial(i);
|
||||
video::ITexture* t=irrMaterial.getTexture(0);
|
||||
|
||||
const Material* material=0;
|
||||
if(t)
|
||||
const video::SMaterial& irrMaterial = mb->getMaterial();
|
||||
std::string t1_full_path, t2_full_path;
|
||||
video::ITexture* t1 = irrMaterial.getTexture(0);
|
||||
if (t1)
|
||||
{
|
||||
std::string image =
|
||||
std::string(core::stringc(t->getName()).c_str());
|
||||
material = material_manager
|
||||
->getMaterial(StringUtils::getBasename(image));
|
||||
if(material->isIgnore())
|
||||
continue;
|
||||
t1_full_path = t1->getName().getPtr();
|
||||
t1_full_path = file_manager->getFileSystem()->getAbsolutePath(
|
||||
t1_full_path.c_str()).c_str();
|
||||
}
|
||||
video::ITexture* t2 = irrMaterial.getTexture(1);
|
||||
if (t2)
|
||||
{
|
||||
t2_full_path = t2->getName().getPtr();
|
||||
t2_full_path = file_manager->getFileSystem()->getAbsolutePath(
|
||||
t2_full_path.c_str()).c_str();
|
||||
}
|
||||
const Material* material = material_manager->getMaterialSPM(
|
||||
t1_full_path, t2_full_path);
|
||||
if (material->isIgnore())
|
||||
continue;
|
||||
|
||||
if (mb->getVertexType() == video::EVT_STANDARD)
|
||||
{
|
||||
irr::video::S3DVertex* mbVertices =
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
HighscoreManager* highscore_manager=0;
|
||||
const unsigned int HighscoreManager::CURRENT_HSCORE_FILE_VERSION = 3;
|
||||
const unsigned int HighscoreManager::CURRENT_HSCORE_FILE_VERSION = 4;
|
||||
|
||||
HighscoreManager::HighscoreManager()
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
typedef std::string HighscoreType;
|
||||
|
||||
private:
|
||||
enum {HIGHSCORE_LEN = 3}; // It's a top 3 list
|
||||
enum {HIGHSCORE_LEN = 5}; // It's a top 5 list
|
||||
std::string m_track;
|
||||
HighscoreType m_highscore_type;
|
||||
int m_number_of_karts;
|
||||
|
@ -327,6 +327,7 @@ void RaceManager::startNew(bool from_overworld)
|
||||
m_num_ghost_karts = ReplayPlay::get()->getNumGhostKart();
|
||||
|
||||
m_started_from_overworld = from_overworld;
|
||||
if (m_started_from_overworld) m_continue_saved_gp = false;
|
||||
m_saved_gp = NULL; // There will be checks for this being NULL done later
|
||||
|
||||
if (m_major_mode==MAJOR_MODE_GRAND_PRIX)
|
||||
@ -510,6 +511,31 @@ void RaceManager::startNextRace()
|
||||
}
|
||||
} // not first race
|
||||
|
||||
// set boosted AI status for AI karts
|
||||
int boosted_ai_count = std::min<int>(m_ai_kart_list.size(),
|
||||
(m_kart_status.size()-2)/4 + 1);
|
||||
if (boosted_ai_count > 4) boosted_ai_count = 4;
|
||||
int ai_count = m_ai_kart_list.size();
|
||||
|
||||
for (unsigned int i=0;i<m_kart_status.size();i++)
|
||||
{
|
||||
if (m_kart_status[i].m_kart_type == KT_AI)
|
||||
{
|
||||
if (boosted_ai_count > 0 &&
|
||||
(UserConfigParams::m_gp_most_points_first ||
|
||||
ai_count == boosted_ai_count))
|
||||
{
|
||||
m_kart_status[i].m_boosted_ai = true;
|
||||
boosted_ai_count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kart_status[i].m_boosted_ai = false;
|
||||
}
|
||||
ai_count--;
|
||||
}
|
||||
}
|
||||
|
||||
// the constructor assigns this object to the global
|
||||
// variable world. Admittedly a bit ugly, but simplifies
|
||||
// handling of objects which get created in the constructor
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user