Merge branch 'game_protocol'

This commit is contained in:
Benau 2018-04-20 10:34:19 +08:00
commit c2b5e566c0
316 changed files with 10319 additions and 8367 deletions

View File

@ -36,6 +36,8 @@ mass.png by Auria, released under CC-0
power.png by Auria, based on https://openclipart.org/detail/193925/check-engine and https://openclipart.org/detail/144799/power-icon, released under CC-0
crown.png by glitch, from https://openclipart.org/detail/210257/misc-game-crown, released under public domain
====
Glass Skin by Auria, under CC-BY-SA 3+

BIN
data/gui/crown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="1%" y="1%" width="98%" height="99%" layout="vertical-row" >
<header width="80%"
I18N="In the kart selection (player setup) screen"
text="Choose a Kart"
align="center" text_align="center" />
<placeholder id="playerskarts" width="100%" align="center" proportion="4">
<!-- Contents is added programatically -->
</placeholder>
<spacer height="15" width="25"/>
<box proportion="2" width="100%" layout="vertical-row" padding="2">
<ribbon_grid id="karts" proportion="1" square_items="true" width="100%" align="center"
child_width="90" child_height="90" max_rows="3"/>
</box>
<!-- Groups will be added dynamically at runtime -->
<tabs width="98%" x="1%" height="5%" id="kartgroups">
</tabs>
<spacer width="100%" height="2%"/>
</div>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
</stkgui>

View File

@ -2,69 +2,70 @@
<stkgui>
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
<header id="title" text_align="center" width="80%" align="center" I18N="In the server creation screen" text="Server Creation"/>
<spacer height="15" width="10"/>
<box proportion="4" width="90%" layout="vertical-row" align="center">
<div width="90%" align="center" layout="vertical-row" y="2%" height="96%">
<div width="100%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Name of the server"/>
<textbox proportion="1" id="name" I18N="In the server creation screen"/>
</div>
<box proportion="1" width="90%" layout="vertical-row" align="center">
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Max. number of players"/>
<gauge id="max_players" proportion="1" min_value="2" max_value="12"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Password (optional)"/>
<textbox proportion="1" id="password" I18N="In the server creation screen"/>
</div>
<spacer height="20" width="20"/>
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Difficulty"/>
<!--<gauge id="difficulty" proportion="1" min_value="1" max_value="4"/>-->
<ribbon id="difficulty" height="135" width="90%" align="center">
<icon-button id="novice" width="128" height="128" icon="gui/difficulty_easy.png"
I18N="Difficulty" text="Novice"/>
<icon-button id="intermediate" width="128" height="128" icon="gui/difficulty_medium.png"
I18N="Difficulty" text="Intermediate"/>
<icon-button id="expert" width="128" height="128" icon="gui/difficulty_hard.png"
I18N="Difficulty" text="Expert"/>
<icon-button id="best" width="128" height="128" icon="gui/difficulty_best.png"
I18N="Difficulty" text="SuperTux"/>
</ribbon>
<spacer height="20" width="20"/>
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Game mode"/>
<ribbon id="gamemode" height="135" width="50%" align="center">
<icon-button id="normal" width="128" height="128" icon="gui/mode_normal.png"
I18N="Multiplayer game mode" text="Normal Race"/>
<icon-button id="timetrial" width="128" height="128" icon="gui/mode_tt.png"
I18N="Multiplayer game mode" text="Time Trial"/>
</ribbon>
<!--
<scrollable_toolbar id="gamemode" height="135" width="90%" label_location="bottom" align="center"
child_width="135" child_height="135" />
-->
</div>
<label id="info" proportion="1" width="100%" align="center" text_align="center" word_wrap="true" text=""/>
<buttonbar id="options" x="0" y="0" width="25%" height="12%" align="center">
<icon-button id="create" width="64" height="64" icon="gui/green_check.png"
I18N="In the server creation screen" text="Create" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="In the server creation screen" text="Cancel" label_location="bottom"/>
</buttonbar>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Name of the server"/>
<textbox proportion="1" id="name" I18N="In the server creation screen"/>
</div>
<spacer height="10" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Max. number of players"/>
<gauge id="max_players" proportion="1" min_value="2"/>
</div>
<spacer height="10" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Password (optional)"/>
<textbox proportion="1" id="password" I18N="In the server creation screen"/>
</div>
<spacer height="5" width="20"/>
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Difficulty"/>
<ribbon id="difficulty" height="15%" width="90%" align="center">
<icon-button id="novice" width="128" height="128" icon="gui/difficulty_easy.png"
I18N="Difficulty" text="Novice"/>
<icon-button id="intermediate" width="128" height="128" icon="gui/difficulty_medium.png"
I18N="Difficulty" text="Intermediate"/>
<icon-button id="expert" width="128" height="128" icon="gui/difficulty_hard.png"
I18N="Difficulty" text="Expert"/>
<icon-button id="best" width="128" height="128" icon="gui/difficulty_best.png"
I18N="Difficulty" text="SuperTux"/>
</ribbon>
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Game mode"/>
<ribbon id="gamemode" height="15%" width="90%" align="center">
<icon-button id="normal" width="128" height="128" icon="gui/mode_normal.png"
I18N="Multiplayer game mode" text="Normal Race"/>
<icon-button id="timetrial" width="128" height="128" icon="gui/mode_tt.png"
I18N="Multiplayer game mode" text="Time Trial"/>
<icon-button id="3strikes" width="128" height="128" icon="gui/mode_3strikes.png"
I18N="Multiplayer game mode" text="3 Strikes Battle"/>
<icon-button id="soccer" width="128" height="128" icon="gui/mode_soccer.png"
I18N="Multiplayer game mode" text="Soccer"/>
</ribbon>
<spacer height="10" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="more-options" proportion="1" text_align="left"/>
<spinner id="more-options-spinner" proportion="1" wrap_around="true"/>
</div>
<label id="info" proportion="1" width="100%" align="center" text_align="center" word_wrap="true" text=""/>
<buttonbar id="options" x="0" y="0" width="25%" height="12%" align="center">
<icon-button id="create" width="64" height="64" icon="gui/green_check.png"
I18N="In the server creation screen" text="Create" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="In the server creation screen" text="Cancel" label_location="bottom"/>
</buttonbar>
<spacer width="10" height="20"/>
</box>
<spacer height="15" width="10"/>
<spacer width="10" height="10"/>
</div>
</stkgui>

View File

@ -1,60 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
<header text_align="center" width="80%" align="center" I18N="In networking lobby" text="Lobby"/>
<header id="lobby-text" text_align="center" width="80%" align="center" I18N="In networking lobby" text="Lobby"/>
<spacer height="15" width="10"/>
<div proportion="1" x="2%" width="96%" layout="vertical-row">
<div proportion="4" x="2%" width="96%" layout="vertical-row">
<div width="100%" proportion="2" layout="horizontal-row">
<box id="info" proportion="2" height="100%" layout="vertical-row">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name:"/>
<label proportion="2" text_align="left" id="server_name" text=""/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Difficulty:"/>
<label proportion="2" text_align="left" id="server_difficulty" text=""/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Game mode:"/>
<label proportion="2" text_align="left" id="server_game_mode" text=""/>
</div>
<label word_wrap="true" id="text" proportion="3" width="100%" height="100%" text_valign="top"/>
</box>
<spacer width="20" height="20"/>
<box proportion="1" height="100%" layout="vertical-row">
<list id="players" width="100%" height="100%"/>
</box>
</div>
<spacer width="20" height="20"/>
<div width="100%" proportion="1" layout="horizontal-row">
<box proportion="2" height="100%" layout="vertical-row">
<list id="chat" width="100%" height="100%"/>
</box>
<spacer width="20" height="20"/>
<box id="actions" proportion="1" height="100%" layout="vertical-row">
<!-- <label I18N="In networking lobby" word_wrap="true" text="actions" align="center" text-align="center"/>
-->
<icon-button id="start" width="64" height="64" icon="gui/green_check.png" align="center"
I18N="In the network lobby" text="Start Race"/>
</box>
</div>
</div>
<spacer width="10" height="7%"/>
<bottombar x="2%" width="96%" height="10%" layout="horizontal-row">
<label text_align="left" align="center" height="100%" id="online_status" proportion="1" text=""/>
<spacer width="10" height="10" />
<buttonbar id="menu_bottomrow" x="0" y="0" width="20%" height="100%" align="center">
<icon-button id="exit" width="64" height="64" icon="gui/main_quit.png" extend_label="50"
I18N="In the networking lobby" text="Exit" label_location="hover"/>
<spacer height="10"/>
<div width="100%" proportion="1" layout="horizontal-row">
<spacer width="20" height="20"/>
<box proportion="2" height="100%" layout="vertical-row">
<textbox id="chat" width="100%" height="30%"/>
<spacer height="20"/>
<button id="send" height="30%" width="fit" I18N="In the network lobby" text="Send" />
</box>
<spacer width="40"/>
<buttonbar id="actions" proportion="1" width="75%" height="75%">
<icon-button id="start" width="64" height="64" icon="gui/green_check.png" align="center"
I18N="In the network lobby" text="Start race"/>
<icon-button id="exit" width="64" height="64" icon="gui/main_quit.png" align="center"
I18N="In the network lobby" text="Exit"/>
</buttonbar>
</bottombar>
</div>
<spacer height="10"/>
</div>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
</stkgui>

View File

@ -4,9 +4,20 @@
<header text_align="center" width="80%" align="center" text="Online"/>
<spacer height="15" width="10"/>
<button id="user-id" width="20%" height="fit" align="center"/>
<spacer height="20"/>
<box width="50%" height="10%" layout="horizontal-row" align="center" valign="center">
<spacer proportion="1"/>
<label I18N="In the networking menu" align="center"
text="Enable splitscreen or player handicaps" text_align="right"/>
<spacer width="25"/>
<checkbox id="enable-splitscreen" align="center" />
<spacer proportion="1"/>
</box>
<spacer height="15" width="10"/>
<icon id="logo" align="center" proportion="4" width="100%" icon="gui/logo.png"/>
<spacer height="15" width="10"/>
<buttonbar id="menu_toprow" proportion="3" width="90%" align="center">

View File

@ -26,6 +26,10 @@
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Game mode:"/>
<label proportion="2" text_align="left" id="server_game_mode" text=""/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_password" text_align="left" proportion="1" text="Password"/>
<textbox id="password" proportion="2" height="fit"/>
</div>
</div>
<spacer height="20" width="50"/>

View File

@ -11,5 +11,13 @@
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
<list id="server_list" x="0" y="0" width="100%" height="100%"/>
</box>
<div width="99%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<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)"/>
</div>
</div>
</div>
</stkgui>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="5%" width="96%" height="85%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="Splitscreen player in network" text="Add player"/>
<spacer height="20" width="50"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label id="name-text" proportion="1" text_align="left" I18N="Splitscreen player in network" text="Name"/>
<spinner id="name-spinner" width="50%" align="center" wrap_around="true" />
</div>
</div>
<spacer height="20" width="50"/>
<div id="handicap-row" width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label id="handicap-text" proportion="1" text_align="left" I18N="Splitscreen player in network" text="Handicap"/>
<checkbox id="handicap" align="center" />
</div>
</div>
<spacer height="20" width="50"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label id="message-label" proportion="1" text_align="left" I18N="Splitscreen player in network"
text="Press the 'All players ready' button after the player list is ready."/>
</div>
</div>
<spacer height="20" width="50"/>
<buttonbar id="options" width="90%" height="20%" align="center">
<icon-button id="add" width="64" height="64" icon="gui/blue_plus.png"
I18N="Splitscreen player in network" text="Add player" label_location="bottom"/>
<icon-button id="connect" width="64" height="64" icon="gui/green_check.png"
I18N="Splitscreen player in network" text="All players ready" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Splitscreen player in network" text="Cancel" label_location="bottom"/>
<icon-button id="reset" width="64" height="64" icon="gui/remove.png"
I18N="Splitscreen player in network" text="Clear added player" label_location="bottom"/>
</buttonbar>
</div>
</stkgui>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" I18N="Networking screen" text="Waiting for the others..."/>
<spacer height="40" width="50"/>
<label proportion="1" width="100%" text_align="left" id="lblDetails"/>
</div>
</stkgui>

View File

@ -80,6 +80,16 @@
</div>
</div>
<spacer height="4" width="10" />
<div layout="horizontal-row" width="100%" height="fit">
<div proportion="1" height="fit" layout="horizontal-row" >
<checkbox id="enable-lobby-chat"/>
<spacer width="20" height="100%" />
<label height="100%" id="label-lobby-chat" I18N="In the ui settings" text="Enable chatting in networking lobby"/>
</div>
</div>
<spacer height="18" width="4"/>
<!-- ************ LANGUAGE CHOICE ************ -->

View File

@ -2,7 +2,7 @@
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="1%" y="1%" width="98%" height="96%" layout="vertical-row" >
<div id="all-track" x="1%" y="1%" width="60%" height="96%" layout="vertical-row" >
<header width="80%" I18N="In the track selection screen" text="All Tracks"
align="center" text_align="center" />
@ -17,5 +17,32 @@
<tabs width="100%" height="5%" id="trackgroups"> </tabs>
<spacer width="100%" height="2%" />
<box id="rect-box" width="100%" height="20%" padding="15" layout="vertical-row">
<div width="100%" height="fit" layout="horizontal-row" >
<label id="lap-text" proportion="1" I18N="In the track screen" 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 height="10"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="reverse-text" proportion="1" I18N="In the track 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="reverse" align="center"/>
</div>
</div>
</div>
</box>
</div>
<div id="vote" x="63%" y="1%" width="37%" height="96%" layout="vertical-row">
<div width="95%" proportion="2" layout="horizontal-row">
<box proportion="2" height="100%" layout="vertical-row">
<label id="vote-text" word_wrap="true" id="text" proportion="3" width="100%" height="100%" text_valign="top"/>
</box>
</div>
</div>
</stkgui>

View File

@ -1,8 +1,7 @@
<spshader>
<shader-info name="roadBlending" fallback-shader="solid" use-tangents="Y"/>
<first-pass vertex-shader="sp_pass.vert"
fragment-shader="sp_road_blending.frag"
skinned-mesh-shader="sp_skinning.vert">
fragment-shader="sp_road_blending.frag">
</first-pass>
<!--
<shadow-pass vertex-shader="sp_shadow.vert"

View File

@ -160,9 +160,16 @@
away if there is an explosion. -->
<explosion impulse-objects="500.0" />
<!-- Networking - the current networking code is outdated and will not
work anymore - so for now don't enable this. -->
<networking enable="false"/>
<!-- Networking
state-frequency: how many states the server will send per second.
positional-smoothing: smoothing factor used in exponential smoothing
depending on error.
rotational-smoothing: slerp factor used in exponential smoothing
of rotations depending on error.
-->
<networking state-frequency="10"
positional-smoothing="0.25:0.95 1.0:0.85"
rotational-smoothing="0.25:0.95 1.0:0.85" />
<!-- The field od views for 1-4 player split screen. fov-3 is
actually not used (since 3 player split screen uses the
@ -482,4 +489,11 @@
-->
<texture-compression quality="64"/>
<!-- List of default ports used, by default STK use random ports
for client and server, disable it in user config to allow
port forward. The server discovery port has to be the same
across all clients and servers.
-->
<network server-discovery-port="2757" client-port="2758" server-port="2759"/>
</config>

42
doc/physics_order Normal file
View File

@ -0,0 +1,42 @@
This shows in which order input handling, physics computations and
other kart related items are updated in each frame.
main_loop:
getDT() : Determine nexts DT --> simulation
is [T, T+DT] with T=now.
RewindManager::addNextTimeStep() : Adds a default TimeStepInfo entry to the
RewindQueue which will store events for the
current time step (e.g. key presses, and
network data).
irr_driver::update() : Rendering and input handling.
Controller::action() : Store user action in m_controls of
kart. Clients send event to server.
RaceEventManager::update() : A thin wrapper around world used in networked
races.
RewindManager::playEventsTill() : Plays all events in [T, T+DT]: copies unhandled
network events that must be handled at the
current time to the current TimeStepInfo. Can do
complete rewind and replay till T is reached again!
World::updateWorld()
RewindManager::update() : Store current state on server if necessary and
broadcast it to clients.
Karts::update()
Moveable::update() : Copy physics data from bullet to STK.
updateSpeed() : Get physics speed and set it in kart.
Controller::update() : Set kart steering based on user/AI input.
Slipstream::update() : call Kart::handleZipper if required.
updatePhysics()
HandleStartBoost : Trigger boost if required.
updateEnginePower...() : Sets engine power/brakes for bullet vehicle.
Skidding::update() : Update skidding values (which will
affect steering).
setSteering : Sets the bullet steering based on
kart's current steering.
updateSliding() : Test for sliding which can reduce the wheels
friction/grip, causing the physics to slide.
MaxSpeed::update() : Cap speed of kart if kart is too fast.
!physicsafter : !Print debug values
Physics::update() : Time step bullet as often as necessary. This is
using the steering etc information set above.
ProtocolManager::update() : Synchronous protocol updates.
World::updateTime() : Increase time from T to T+DT.

View File

@ -48,9 +48,9 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
}
else
FileSystem = io::createFileSystem();
core::stringc s = "Irrlicht Engine version ";
s.append(getVersion());
os::Printer::log(s.c_str(), ELL_INFORMATION);
//core::stringc s = "Irrlicht Engine version ";
//s.append(getVersion());
//os::Printer::log(s.c_str(), ELL_INFORMATION);
checkVersion(params.SDK_version_do_not_use);
}

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -129,10 +129,10 @@ void PlayerManager::onSTKQuit()
* RequestManager.
*/
Online::XMLRequest *PlayerManager::requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password)
void PlayerManager::requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password)
{
return getCurrentPlayer()->requestSignIn(username, password);
getCurrentPlayer()->requestSignIn(username, password);
} // requestSignIn
// ----------------------------------------------------------------------------

View File

@ -111,8 +111,8 @@ public:
static void resumeSavedSession();
static void onSTKQuit();
static void requestSignOut();
static Online::XMLRequest *requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password);
static void requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password);
// ------------------------------------------------------------------------
/** Returns the current player. */

View File

@ -138,8 +138,8 @@ public:
virtual Online::OnlineProfile* getProfile() const = 0;
virtual void requestPoll() const = 0;
virtual void requestSavedSession() = 0;
virtual Online::XMLRequest* requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password) = 0;
virtual void requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password) = 0;
virtual void signIn(bool success, const XMLNode * input) = 0;
virtual void signOut(bool success, const XMLNode * input,
const irr::core::stringw &info) = 0;

View File

@ -117,8 +117,23 @@ void STKConfig::load(const std::string &filename)
Log::fatal("StkConfig", "Wrong number of item switches defined in stk_config");
}
if (m_positional_smoothing.size() == 0)
{
Log::fatal("StkConfig", "No positional smoothing defined in stk_config.");
}
if (m_rotational_smoothing.size() == 0)
{
Log::fatal("StkConfig", "No rotationalsmoothing defined in stk_config.");
}
if (m_client_port == 0 || m_server_port == 0 || m_server_discovery_port == 0 ||
m_client_port == m_server_port || m_client_port == m_server_discovery_port ||
m_server_port == m_server_discovery_port)
{
Log::fatal("StkConfig", "Invalid default port values.");
}
CHECK_NEG(m_max_karts, "<karts max=..." );
CHECK_NEG(m_item_switch_time, "item-switch-time" );
CHECK_NEG(m_item_switch_ticks, "item switch-time" );
CHECK_NEG(m_bubblegum_counter, "bubblegum disappear counter");
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
CHECK_NEG(m_max_skidmarks, "max-skidmarks" );
@ -131,7 +146,7 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_delay_finish_time, "delay-finish-time" );
CHECK_NEG(m_music_credit_time, "music-credit-time" );
CHECK_NEG(m_leader_time_per_kart, "leader time-per-kart" );
CHECK_NEG(m_penalty_time, "penalty-time" );
CHECK_NEG(m_penalty_ticks, "penalty-time" );
CHECK_NEG(m_max_display_news, "max-display-news" );
CHECK_NEG(m_replay_max_time, "replay max-time" );
CHECK_NEG(m_replay_delta_angle, "replay delta-angle" );
@ -140,6 +155,7 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_smooth_angle_limit, "physics smooth-angle-limit" );
CHECK_NEG(m_default_track_friction, "physics default-track-friction");
CHECK_NEG(m_physics_fps, "physics fps" );
CHECK_NEG(m_network_state_frequeny, "network state-frequency" );
CHECK_NEG(m_default_moveable_friction, "physics default-moveable-friction");
// Square distance to make distance checks cheaper (no sqrt)
@ -157,10 +173,11 @@ void STKConfig::init_defaults()
m_bomb_time = m_bomb_time_increase =
m_explosion_impulse_objects = m_music_credit_time =
m_delay_finish_time = m_skid_fadeout_time =
m_near_ground = m_item_switch_time =
m_smooth_angle_limit = m_penalty_time =
m_default_track_friction = m_default_moveable_friction =
UNDEFINED;
m_near_ground =
m_smooth_angle_limit = m_default_track_friction =
m_default_moveable_friction = UNDEFINED;
m_item_switch_ticks = -100;
m_penalty_ticks = -100;
m_physics_fps = -100;
m_bubblegum_counter = -100;
m_shield_restrict_weapons = false;
@ -175,8 +192,8 @@ void STKConfig::init_defaults()
m_replay_delta_angle = -100;
m_replay_delta_pos2 = -100;
m_replay_dt = -100;
m_network_state_frequeny = -100;
m_title_music = NULL;
m_enable_networking = true;
m_smooth_normals = false;
m_same_powerup_mode = POWERUP_MODE_ONLY_IF_SAME;
m_ai_acceleration = 1.0f;
@ -185,6 +202,9 @@ void STKConfig::init_defaults()
m_cutscene_fov = 0.61f;
m_max_skinning_bones = 1024;
m_tc_quality = 16;
m_server_discovery_port = 2757;
m_client_port = 2758;
m_server_port = 2759;
m_score_increase.clear();
m_leader_intervals.clear();
@ -256,7 +276,9 @@ void STKConfig::getAllData(const XMLNode * root)
if (const XMLNode *startup_node= root->getNode("startup"))
{
startup_node->get("penalty", &m_penalty_time );
float f;
startup_node->get("penalty", &f);
m_penalty_ticks = time2Ticks(f);
}
if (const XMLNode *news_node= root->getNode("news"))
@ -337,7 +359,9 @@ void STKConfig::getAllData(const XMLNode * root)
if(const XMLNode *switch_node= root->getNode("switch"))
{
switch_node->get("items", &m_switch_items );
switch_node->get("time", &m_item_switch_time);
float f;
if( switch_node->get("time", &f) )
m_item_switch_ticks = stk_config->time2Ticks(f);
}
if(const XMLNode *bubblegum_node= root->getNode("bubblegum"))
@ -356,8 +380,12 @@ void STKConfig::getAllData(const XMLNode * root)
ai_node->get("acceleration", &m_ai_acceleration);
}
if(const XMLNode *networking_node= root->getNode("networking"))
networking_node->get("enable", &m_enable_networking);
if (const XMLNode *networking_node = root->getNode("networking"))
{
networking_node->get("state-frequency", &m_network_state_frequeny);
networking_node->get("positional-smoothing", &m_positional_smoothing );
networking_node->get("rotational-smoothing", &m_rotational_smoothing );
}
if(const XMLNode *replay_node = root->getNode("replay"))
{
@ -384,6 +412,19 @@ void STKConfig::getAllData(const XMLNode * root)
tc->get("quality", &m_tc_quality);
}
if (const XMLNode *tc = root->getNode("network"))
{
unsigned server_discovery_port = 0;
unsigned client_port = 0;
unsigned server_port = 0;
tc->get("server-discovery-port", &server_discovery_port);
tc->get("client-port", &client_port);
tc->get("server-port", &server_port);
m_server_discovery_port = (uint16_t)server_discovery_port;
m_client_port = (uint16_t)client_port;
m_server_port = (uint16_t)server_port;
}
// Get the default KartProperties
// ------------------------------
const XMLNode *node = root -> getNode("general-kart-defaults");

View File

@ -27,6 +27,7 @@
*/
#include "network/remote_kart_info.hpp"
#include "utils/interpolation_array.hpp"
#include "utils/no_copy.hpp"
#include "utils/constants.hpp"
@ -69,13 +70,13 @@ public:
float m_bomb_time; /**<Time before a bomb explodes. */
float m_bomb_time_increase; /**<Time added to bomb timer when it's
passed on. */
float m_item_switch_time; /**< Time items will be switched. */
int m_item_switch_ticks; /**< Time items will be switched. */
int m_bubblegum_counter; /**< How many times bubble gums must be
driven over before they disappear. */
bool m_shield_restrict_weapons; /**<Wether weapon usage is punished. */
float m_explosion_impulse_objects; /**<Impulse of explosion on moving
objects, e.g. road cones, ... */
float m_penalty_time; /**< Penalty time when starting too
int m_penalty_ticks; /**< Penalty time when starting too
early. */
float m_delay_finish_time; /**<Delay after a race finished before
the results are displayed. */
@ -84,9 +85,20 @@ public:
int m_max_karts; /**<Maximum number of karts. */
bool m_smooth_normals; /**< If normals for raycasts for wheels
should be interpolated. */
/** If the angle between a normal on a vertex and the normal of the
* triangle are more than this value, the physics will use the normal
* of the triangle in smoothing normal. */
/** How many state updates per second the server will send. */
int m_network_state_frequeny;
/** Smoothing of prediction errors for position, defined as an
* InterpolationArray. */
InterpolationArray m_positional_smoothing;
/** Smoothing of prediction errors for rotations, defined as an
* InterpolationArray. */
InterpolationArray m_rotational_smoothing;
/** If the angle between a normal on a vertex and the normal of the
* triangle are more than this value, the physics will use the normal
* of the triangle in smoothing normal. */
float m_smooth_angle_limit;
/** Default friction for the track and any track/library object. */
@ -107,7 +119,6 @@ public:
m_max_track_version; /**<version supported by this binary. */
int m_max_display_news; /**<How often a news message is displayed
before it is ignored. */
bool m_enable_networking;
/** Disable steering if skidding is stopped. This can help in making
* skidding more controllable (since otherwise when trying to steer while
@ -159,6 +170,11 @@ public:
unsigned m_tc_quality;
/** Client and server port use random ports if enabled in user config. */
uint16_t m_server_discovery_port;
uint16_t m_client_port;
uint16_t m_server_port;
/** Lists of TTF files used in STK. */
std::vector<std::string> m_normal_ttf;
std::vector<std::string> m_digit_ttf;

View File

@ -181,146 +181,6 @@ void GroupUserConfigParam::addChild(UserConfigParam* child)
m_attributes.push_back(child);
} // addChild
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
const char* comment)
{
m_param_name = param_name;
all_params.push_back(this);
if(comment != NULL) m_comment = comment;
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T,U>::ListUserConfigParam(const char* param_name,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
all_params.push_back(this);
if(comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start ( arguments, nb_elements );
for ( int i = 0; i < nb_elements; i++ )
m_elements.push_back(T(va_arg ( arguments, U )));
va_end ( arguments ); // Cleans up the list
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment)
{
m_param_name = param_name;
group->addChild(this);
if(comment != NULL) m_comment = comment;
} // ListUserConfigParam
// ============================================================================
template<typename T, typename U>
ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
group->addChild(this);
if(comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start ( arguments, nb_elements );
for ( int i = 0; i < nb_elements; i++ )
m_elements.push_back(va_arg ( arguments, T ));
va_end ( arguments ); // Cleans up the list
} // ListUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::write(std::ofstream& stream) const
{
const int elts_amount = (int)m_elements.size();
// comment
if(m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
stream << " -->\n <" << m_param_name.c_str() << "\n";
stream << " Size=\"" << elts_amount << "\"\n";
// actual elements
for (int n=0; n<elts_amount; n++)
{
stream << " " << n << "=\"" << m_elements[n].c_str() << "\"\n";
}
stream << " >\n";
stream << " </" << m_param_name.c_str() << ">\n\n";
} // write
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
{
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
//Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
int attr_count = 0;
child->get( "Size", &attr_count);
for (int n=0; n<attr_count; n++)
{
T elt;
std::string str;
child->get( StringUtils::toString(n), &str);
StringUtils::fromString<T>(str, elt);
// check if the element is already there :
bool there = false;
for (unsigned int i = 0; i < m_elements.size(); i++)
{
if (elt == m_elements[i])
{
there = true;
break;
}
}
if (!there)
{
m_elements.push_back(elt);
}
}
} // findYourDataInAChildOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T, U>::findYourDataInAnAttributeOf(const XMLNode* node)
{
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void ListUserConfigParam<T,U>::addElement(T element)
{
m_elements.push_back(element);
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
core::stringc ListUserConfigParam<T, U>::toString() const
{
return "";
} // toString
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
@ -334,26 +194,12 @@ MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
const char* comment,
int nb_elements,
...)
const char* comment, std::map<T, U> default_value)
{
m_param_name = param_name;
all_params.push_back(this);
if (comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start(arguments, nb_elements);
struct pair_type { T key; U value; };
for (int i = 0; i < nb_elements; i++)
{
pair_type key_value_pair = va_arg(arguments, pair_type);
m_elements.insert(std::pair<T, U>(key_value_pair.key, key_value_pair.value));
}
va_end(arguments); // Cleans up the list
m_elements = default_value;
} // MapUserConfigParam
// ----------------------------------------------------------------------------
@ -370,27 +216,14 @@ MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elements,
...)
GroupUserConfigParam* group, const char* comment,
std::map<T, U> default_value)
{
m_param_name = param_name;
group->addChild(this);
if (comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start(arguments, nb_elements);
struct pair_type { T key; U value; };
for (int i = 0; i < nb_elements; i++)
{
pair_type key_value_pair = va_arg(arguments, pair_type);
m_elements.insert(std::pair<T, U>(key_value_pair.key, key_value_pair.value));
}
va_end(arguments); // Cleans up the list
m_elements = default_value;
} // MapUserConfigParam
// ----------------------------------------------------------------------------
@ -401,7 +234,7 @@ void MapUserConfigParam<T, U>::write(std::ofstream& stream) const
if (m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
stream << " -->\n <" << m_param_name.c_str() << "\n";
for (const auto& kv : m_elements)
for (const auto& kv : m_elements)
{
stream << " " << kv.first << "=\"" << kv.second << "\"\n";
}
@ -410,7 +243,6 @@ void MapUserConfigParam<T, U>::write(std::ofstream& stream) const
} // write
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
{

View File

@ -37,6 +37,7 @@
cause an undefined game action now
6: Added stick configurations.
*/
#include <iterator>
#include <string>
#include <map>
#include <vector>
@ -98,44 +99,6 @@ public:
}; // GroupUserConfigParam
// ============================================================================
template<typename T, typename U>
class ListUserConfigParam : public UserConfigParam
{
std::vector<T> m_elements;
public:
ListUserConfigParam(const char* param_name,
const char* comment = NULL);
ListUserConfigParam(const char* param_name,
const char* comment,
int nb_elts,
...);
ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment = NULL);
ListUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elts,
...);
void write(std::ofstream& stream) const;
void findYourDataInAChildOf(const XMLNode* node);
void findYourDataInAnAttributeOf(const XMLNode* node);
void addElement(T element);
irr::core::stringc toString() const;
operator std::vector<T>() const
{ return m_elements; }
float& operator=(const std::vector<T>& v)
{ m_elements = std::vector<T>(v); return m_elements; }
float& operator=(const ListUserConfigParam& v)
{ m_elements = std::vector<T>(v); return m_elements; }
}; // ListUserConfigParam
typedef ListUserConfigParam<std::string, const char*> StringListUserConfigParam;
template<typename T, typename U>
class MapUserConfigParam : public UserConfigParam
{
@ -146,16 +109,14 @@ public:
const char* comment = NULL);
MapUserConfigParam(const char* param_name,
const char* comment,
int nb_elts,
...);
std::map<T, U> default_value);
MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment = NULL);
MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elts,
...);
std::map<T, U> default_value);
void write(std::ofstream& stream) const;
void findYourDataInAChildOf(const XMLNode* node);
@ -165,10 +126,18 @@ public:
irr::core::stringc toString() const;
operator std::map<T,U>() const
operator std::map<T, U>() const
{
return m_elements;
}
typename std::map<T, U>::iterator begin()
{
return m_elements.begin();
}
typename std::map<T, U>::iterator end()
{
return m_elements.end();
}
std::map<T, U>& operator=(const std::map<T,U>& v)
{
m_elements = std::map<T, U>(v);
@ -183,8 +152,9 @@ public:
{
return m_elements[key];
}
}; // ListUserConfigParam
typedef MapUserConfigParam<int, int> IntToIntUserConfigParam;
}; // MapUserConfigParam
typedef MapUserConfigParam<uint32_t, uint32_t> UIntToUIntUserConfigParam;
typedef MapUserConfigParam<std::string, uint32_t> StringToUIntUserConfigParam;
// ============================================================================
class IntUserConfigParam : public UserConfigParam
{
@ -205,7 +175,7 @@ public:
irr::core::stringc toString() const;
void revertToDefaults() { m_value = m_default_value; }
int getDefaultValue() { return m_default_value; }
operator int() const { return m_value; }
int& operator++(int dummy) { m_value++; return m_value; }
int& operator=(const int& v) { m_value = v; return m_value; }
@ -713,72 +683,70 @@ namespace UserConfigParams
* can store. */
PARAM_PREFIX float m_profiler_buffer_duration PARAM_DEFAULT(20.0f);
// not saved to file
// ---- Networking
PARAM_PREFIX IntUserConfigParam m_server_max_players
PARAM_DEFAULT( IntUserConfigParam(16, "server_max_players",
"Maximum number of players on the server.") );
PARAM_PREFIX StringListUserConfigParam m_stun_servers
PARAM_DEFAULT( StringListUserConfigParam("Stun_servers", "The stun servers"
" that will be used to know the public address.",
24,
"provserver.televolution.net",
"sip1.lakedestiny.cordiaip.com",
"stun1.voiceeclipse.net",
"stun01.sipphone.com",
"stun.callwithus.com",
"stun.counterpath.net",
"stun.endigovoip.com",
"stun.ekiga.net",
"stun.ideasip.com",
"stun.internetcalls.com",
"stun.ipns.com",
"stun.noc.ams-ix.net",
"stun.phonepower.com",
"stun.phoneserve.com",
"stun.rnktel.com",
"stun.softjoys.com",
"stunserver.org",
"stun.sipgate.net",
"stun.stunprotocol.org",
"stun.voip.aebc.com",
"stun.voipbuster.com",
"stun.voxalot.com",
"stun.voxgratia.org",
"stun.xten.com") );
// ---- Gamemode setup
PARAM_PREFIX IntToIntUserConfigParam m_num_karts_per_gamemode
PARAM_DEFAULT(IntToIntUserConfigParam("num_karts_per_gamemode",
"The Number of karts per gamemode.",
1,
std::make_pair(1100, 4)
PARAM_PREFIX StringToUIntUserConfigParam m_stun_list
PARAM_DEFAULT(StringToUIntUserConfigParam("stun_list",
"The stun servers that will be used to know the public address,"
" LHS: server address, RHS: ping time.",
{
{ "numb.viagenie.ca", 0u },
{ "stun.12connect.com", 0u },
{ "stun.callwithus.com", 0u },
{ "stun.cope.es", 0u },
{ "stun.counterpath.net", 0u },
{ "stun.ekiga.net", 0u },
{ "stun.ivao.aero", 0u },
{ "stun.schlund.de", 0u },
{ "stun.stunprotocol.org", 0u },
{ "stun.voip.aebc.com", 0u }
}
));
PARAM_PREFIX GroupUserConfigParam m_network_group
PARAM_DEFAULT(GroupUserConfigParam("Network", "Network Settings"));
PARAM_PREFIX BoolUserConfigParam m_log_packets
PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets",
"If all network packets should be logged") );
PARAM_DEFAULT(BoolUserConfigParam(false, "log-network-packets",
&m_network_group, "If all network packets should be logged"));
PARAM_PREFIX BoolUserConfigParam m_random_ports
PARAM_DEFAULT(BoolUserConfigParam(true, "randrom-ports",
&m_network_group, "Use random ports for client and server connection"));
PARAM_PREFIX BoolUserConfigParam m_lobby_chat
PARAM_DEFAULT(BoolUserConfigParam(false, "lobby-chat",
&m_network_group, "Enable chatting in networking lobby, if off than "
"no chat message will be displayed from any players."));
PARAM_PREFIX FloatUserConfigParam m_voting_timeout
PARAM_DEFAULT(FloatUserConfigParam(10.0f, "voting-timeout",
&m_network_group, "Timeout in seconds for voting tracks in server."));
PARAM_PREFIX IntUserConfigParam m_server_max_players
PARAM_DEFAULT(IntUserConfigParam(12, "server_max_players",
&m_network_group, "Maximum number of players on the server."));
PARAM_PREFIX StringToUIntUserConfigParam m_server_ban_list
PARAM_DEFAULT(StringToUIntUserConfigParam("server_ban_list",
"LHS: IP in x.x.x.x format, RHS: online id, if 0 than all players "
"from this IP will be banned.",
{ { "0.0.0.0", 0u } }
));
// ---- Gamemode setup
PARAM_PREFIX UIntToUIntUserConfigParam m_num_karts_per_gamemode
PARAM_DEFAULT(UIntToUIntUserConfigParam("num_karts_per_gamemode",
"The Number of karts per gamemode.",
{
{ 0u, 4u },
{ 1002u, 5u },
{ 1100u, 4u },
{ 1101u, 4u },
{ 2000u, 4u },
{ 2001u, 4u }
}
));
// ---- Graphic Quality
PARAM_PREFIX GroupUserConfigParam m_graphics_quality
PARAM_DEFAULT( GroupUserConfigParam("GFX",
"Graphics Quality Settings") );
// On OSX 10.4 and before there may be driver issues with FBOs, so to be
// safe disable them by default
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define FBO_DEFAULT false
#else
#define FBO_DEFAULT true
#endif
#else
#define FBO_DEFAULT true
#endif
PARAM_PREFIX IntUserConfigParam m_particles_effects
PARAM_DEFAULT( IntUserConfigParam(2, "particles-effecs",
&m_graphics_quality, "Particles effects: 0 disabled, 1 only important, 2 enabled") );
@ -842,17 +810,6 @@ namespace UserConfigParams
PARAM_PREFIX BoolUserConfigParam m_crashed
PARAM_DEFAULT( BoolUserConfigParam(false, "crashed") );
#if defined(WIN32) && !defined(__CYGWIN__)
// No console on windows
# define CONSOLE_DEFAULT false
#else
# define CONSOLE_DEFAULT true
#endif
// No console on windows
PARAM_PREFIX BoolUserConfigParam m_log_errors_to_console
PARAM_DEFAULT( BoolUserConfigParam(
CONSOLE_DEFAULT, "log_errors", "Enable logging to console.") );
// ---- Camera
PARAM_PREFIX GroupUserConfigParam m_camera
PARAM_DEFAULT( GroupUserConfigParam("camera",

View File

@ -29,6 +29,7 @@
#include "graphics/stk_tex_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/skin.hpp"
#include "modes/profile_world.hpp"
#include "utils/string_utils.hpp"
#include <array>
@ -209,7 +210,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
if (bits->buffer != NULL)
if (bits->buffer != NULL && !ProfileWorld::isNoGraphics())
{
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
@ -335,7 +336,7 @@ void FontWithFace::setDPI()
if (UserConfigParams::m_hidpi_enabled)
{
float scale = screen_height / 480.0f;
m_face_dpi = getScalingFactorTwo() * getScalingFactorOne() * scale;
m_face_dpi = int(getScalingFactorTwo() * getScalingFactorOne() * scale);
}
else
{

View File

@ -20,6 +20,7 @@
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
@ -31,14 +32,15 @@
#include "race/race_manager.hpp"
#include "utils/vec3.hpp"
const float burst_time = 0.1f;
/** Creates an explosion effect. */
Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char * particle_file)
: HitSFX(coord, explosion_sound)
{
// short emision time, explosion, not constant flame
m_remaining_time = burst_time;
m_explosion_ticks = stk_config->time2Ticks(2.0f);
m_remaining_ticks = stk_config->time2Ticks(0.1f);
m_emission_frames = 0;
#ifndef SERVER_ONLY
@ -84,22 +86,22 @@ Explosion::~Explosion()
* \param dt Time step size.
* \return true If the explosion is finished.
*/
bool Explosion::updateAndDelete(float dt)
bool Explosion::updateAndDelete(int ticks)
{
// The explosion sfx is shorter than the particle effect,
// so no need to save the result of the update call.
HitSFX::updateAndDelete(dt);
HitSFX::updateAndDelete(ticks);
m_emission_frames++;
m_remaining_time -= dt;
m_remaining_ticks -= ticks;
// Do nothing more if the animation is still playing
if (m_remaining_time>0) return false;
if (m_remaining_ticks>0) return false;
// Otherwise check that the sfx has finished, otherwise the
// sfx will get aborted 'in the middle' when this explosion
// object is removed.
if (m_remaining_time > -explosion_time)
if (m_remaining_ticks > -m_explosion_ticks)
{
#ifndef SERVER_ONLY
// if framerate is very low, emit for at least a few frames, in case
@ -122,3 +124,4 @@ bool Explosion::updateAndDelete(float dt)
return false; // not finished
} // updateAndDelete

View File

@ -21,6 +21,7 @@
#define HEADER_EXPLOSION_HPP
#include "graphics/hit_sfx.hpp"
#include "utils/cpp2011.hpp"
#include "utils/no_copy.hpp"
namespace irr
@ -33,23 +34,26 @@ class Vec3;
class SFXBase;
class ParticleEmitter;
const float explosion_time = 2.0f;
/**
* \ingroup graphics
*/
class Explosion : public HitSFX
{
private:
float m_remaining_time;
int m_remaining_ticks;
int m_emission_frames;
ParticleEmitter* m_emitter;
int m_explosion_ticks;
public:
Explosion(const Vec3& coord, const char* explosion_sound, const char * particle_file );
~Explosion();
bool updateAndDelete(float delta_t);
bool hasEnded () { return m_remaining_time <= -explosion_time; }
bool updateAndDelete(int ticks) OVERRIDE;
bool hasEnded ()
{
return m_remaining_ticks <= -m_explosion_ticks;
}
} ;

View File

@ -43,7 +43,7 @@ public:
/** Updates a hit effect. Called once per frame.
* \param dt Time step size.
* \return True if the hit effect is finished and can be removed. */
virtual bool updateAndDelete(float dt) = 0;
virtual bool updateAndDelete(int ticks) = 0;
// ------------------------------------------------------------------------
/** Sets that this SFX affects a player kart, which can be used to

View File

@ -61,7 +61,7 @@ void HitSFX::setLocalPlayerKartHit()
* \param dt Time step size.
* \return true If the explosion is finished.
*/
bool HitSFX::updateAndDelete(float dt)
bool HitSFX::updateAndDelete(int ticks)
{
SFXBase::SFXStatus status = m_sfx->getStatus();
return status!= SFXBase::SFX_PLAYING;

View File

@ -36,7 +36,7 @@ private:
public:
HitSFX(const Vec3& coord, const char* explosion_sound);
~HitSFX();
virtual bool updateAndDelete(float dt) OVERRIDE;
virtual bool updateAndDelete(int ticks) OVERRIDE;
virtual void setLocalPlayerKartHit() OVERRIDE;
}; // HitSFX

View File

@ -303,7 +303,6 @@ core::recti IrrDriver::getSplitscreenWindow(int WindowNum)
const int x_grid_Position = WindowNum % cols;
const int y_grid_Position = int(floor((WindowNum) / cols));
int wid = (int)irr_driver->getActualScreenSize().Width;
//To prevent the viewport going over the right side, we use std::min to ensure the right corners are never larger than the total width
return core::recti(
@ -715,8 +714,8 @@ void IrrDriver::initDevice()
// set cursor visible by default (what's the default is not too clearly documented,
// so let's decide ourselves...)
m_device->getCursorControl()->setVisible(true);
m_pointer_shown = true;
#endif
m_pointer_shown = true;
} // initDevice
// ----------------------------------------------------------------------------
@ -786,16 +785,19 @@ void IrrDriver::getOpenGLData(std::string *vendor, std::string *renderer,
//-----------------------------------------------------------------------------
void IrrDriver::showPointer()
{
#ifndef SERVER_ONLY
if (!m_pointer_shown)
{
m_pointer_shown = true;
this->getDevice()->getCursorControl()->setVisible(true);
}
#endif
} // showPointer
//-----------------------------------------------------------------------------
void IrrDriver::hidePointer()
{
#ifndef SERVER_ONLY
// always visible in artist debug mode, to be able to use the context menu
if (UserConfigParams::m_artist_debug_mode)
{
@ -808,6 +810,7 @@ void IrrDriver::hidePointer()
m_pointer_shown = false;
this->getDevice()->getCursorControl()->setVisible(false);
}
#endif
} // hidePointer
//-----------------------------------------------------------------------------

View File

@ -152,7 +152,9 @@ Material::Material(const XMLNode *node, bool deprecated)
node->get("ignore", &m_ignore );
node->get("max-speed", &m_max_speed_fraction );
node->get("slowdown-time", &m_slowdown_time );
float f = stk_config->ticks2Time(m_slowdown_ticks);
node->get("slowdown-time", &f );
m_slowdown_ticks = stk_config->time2Ticks(f);
node->get("colorizable", &m_colorizable );
node->get("colorization-factor", &m_colorization_factor);
node->get("hue-settings", &m_hue_settings );
@ -484,7 +486,7 @@ void Material::init()
m_colorization_factor = 0.0f;
m_colorization_mask = "";
m_max_speed_fraction = 1.0f;
m_slowdown_time = 1.0f;
m_slowdown_ticks = stk_config->time2Ticks(1.0f);
m_sfx_name = "";
m_sfx_min_speed = 0.0f;
m_sfx_max_speed = 30;

View File

@ -155,7 +155,7 @@ private:
RandomGenerator m_random_hue;
/** How much the top speed is reduced per second. */
float m_slowdown_time;
int m_slowdown_ticks;
/** Maximum speed at which no more slow down occurs. */
float m_max_speed_fraction;
@ -287,7 +287,7 @@ public:
/** Returns how long it will take for a slowdown to take effect.
* It is the time it takes till the full slowdown applies to
* karts. So a short time will slowdown a kart much faster. */
float getSlowDownTime() const { return m_slowdown_time; }
int getSlowDownTicks() const { return m_slowdown_ticks; }
// ------------------------------------------------------------------------
/** Returns true if this material is under some other mesh and therefore
* requires another raycast to find the surface it is under (used for

View File

@ -42,11 +42,13 @@
*/
SlipStream::SlipStream(AbstractKart* kart)
{
m_node = NULL;
m_kart = kart;
m_moving = NULL;
m_moving_fast = NULL;
m_moving_bonus = NULL;
m_node = NULL;
m_node_fast = NULL;
m_bonus_node = NULL;
#ifndef SERVER_ONLY
if (CVS->isGLSL())
@ -210,7 +212,7 @@ void SlipStream::reset()
{
m_slipstream_mode = SS_NONE;
m_slipstream_time = 0;
m_bonus_time = 0;
m_bonus_time = 0;
// Reset a potential max speed increase
m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM, 0, 0, 0, 0);
@ -612,7 +614,7 @@ void SlipStream::updateQuad()
/** Update, called once per timestep.
* \param dt Time step size.
*/
void SlipStream::update(float dt)
void SlipStream::update(int ticks)
{
const KartProperties *kp = m_kart->getKartProperties();
@ -628,6 +630,7 @@ void SlipStream::update(float dt)
updateQuad();
}
float dt = stk_config->ticks2Time(ticks);
#ifndef SERVER_ONLY
if (CVS->isGLSL())
{
@ -731,7 +734,7 @@ void SlipStream::update(float dt)
// (additional target_kart_length because that kart's center
// is not the center of rotation of the slipstreaming quad)
Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
float l = kp_target->getSlipstreamLength()*1.1;//Outer quad margin
float l = kp_target->getSlipstreamLength()*1.1f;//Outer quad margin
float speed_factor = m_target_kart->getSpeed()
/kp_target->getSlipstreamBaseSpeed();
l = l*speed_factor + m_target_kart->getKartLength()
@ -821,12 +824,13 @@ void SlipStream::update(float dt)
m_slipstream_time = 0.0f;
m_bonus_active = true;
int fade_out = kp->getSlipstreamFadeOutTicks();
m_kart->instantSpeedIncrease(MaxSpeed::MS_INCREASE_SLIPSTREAM,
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamAddPower(),
m_bonus_time,
kp->getSlipstreamFadeOutTime());
stk_config->ticks2Time(fade_out) );
}
if(!is_sstreaming)

View File

@ -123,7 +123,7 @@ public:
SlipStream (AbstractKart* kart);
virtual ~SlipStream ();
void reset();
virtual void update(float dt);
virtual void update(int ticks);
bool isSlipstreamReady() const;
// ------------------------------------------------------------------------

View File

@ -56,9 +56,9 @@ SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
glBufferData(GL_ARRAY_BUFFER, 4 * 48, NULL, GL_DYNAMIC_DRAW);
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ARRAY_BUFFER, 32, NULL, GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, 44, NULL, GL_DYNAMIC_DRAW);
SPInstancedData id = SPInstancedData(m_trans, 0.0f, 0.0f, 0.0f, 0);
glBufferSubData(GL_ARRAY_BUFFER, 0, 32, &id);
glBufferSubData(GL_ARRAY_BUFFER, 0, 44, &id);
SPTextureManager::get()->increaseGLCommandFunctionCount(1);
SPTextureManager::get()->addGLCommandFunction
(std::bind(&SPDynamicDrawCall::initTextureDyDc, this));
@ -120,26 +120,23 @@ SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
glBindBuffer(GL_ARRAY_BUFFER, m_ibo);
// Origin
glEnableVertexAttribArray(8);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 32, (void*)0);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 44, (void*)0);
glVertexAttribDivisorARB(8, 1);
// Rotation (quaternion .xyz)
// Rotation (quaternion in 4 32bit floats)
glEnableVertexAttribArray(9);
glVertexAttribPointer(9, 4, GL_INT_2_10_10_10_REV,
GraphicsRestrictions::isDisabled
(GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION) ?
GL_FALSE : GL_TRUE, 32, (void*)12);
glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, 44, (void*)12);
glVertexAttribDivisorARB(9, 1);
// Scale (3 half floats and .w for quaternion .w)
// Scale (3 half floats and .w unused)
glEnableVertexAttribArray(10);
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 32, (void*)16);
glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 44, (void*)28);
glVertexAttribDivisorARB(10, 1);
// Texture translation
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 32, (void*)24);
glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 44, (void*)36);
glVertexAttribDivisorARB(11, 1);
// Misc data (skinning offset and hue change)
glEnableVertexAttribArray(12);
glVertexAttribIPointer(12, 2, GL_SHORT, 32, (void*)28);
glVertexAttribIPointer(12, 2, GL_SHORT, 44, (void*)40);
glVertexAttribDivisorARB(12, 1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -164,4 +161,4 @@ bool SPDynamicDrawCall::initTextureDyDc()
return true;
} // initTextureDyDc
}
}

View File

@ -208,7 +208,7 @@ void SPShader::bindTextures(const std::array<GLuint, 6>& tex,
void SPShader::addAllUniforms(RenderPass rp)
{
#ifndef SERVER_ONLY
GLint total_uniforms;
GLint total_uniforms = 0;
glGetProgramiv(m_program[rp], GL_ACTIVE_UNIFORMS, &total_uniforms);
static const std::map<GLenum, std::type_index> supported_types =
{

View File

@ -79,7 +79,7 @@ STKTexture::STKTexture(video::IImage* img, const std::string& name)
STKTexture::~STKTexture()
{
#ifndef SERVER_ONLY
if (m_texture_name != 0)
if (m_texture_name != 0 && !ProfileWorld::isNoGraphics())
{
glDeleteTextures(1, &m_texture_name);
}

View File

@ -309,11 +309,12 @@ namespace GUIEngine
For icon buttons. A different icon to show when the item is focused.
\n
\subsection prop4 PROP_TEXT_ALIGN
<em> Name in XML files: </em> \c "text_align"
\subsection prop4 PROP_TEXT_ALIGN, PROP_TEXT_VALIGN
<em> Name in XML files: </em> \c "text_align", "text_valign"
used exclusively by label components. Value can be "right" or "center" (left
used if not specified).
used if not specified) for "text_align", or "top"/"center"/"bottom" for
valign.
\n
\subsection prop5 PROP_WORD_WRAP

View File

@ -375,7 +375,10 @@ void EventHandler::processGUIAction(const PlayerAction action,
case PA_RESCUE:
case PA_MENU_CANCEL:
if (pressedDown) GUIEngine::getStateManager()->escapePressed();
if (pressedDown&& !isWithinATextBox())
{
GUIEngine::getStateManager()->escapePressed();
}
break;
case PA_FIRE:
@ -813,7 +816,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
const int playerID = input_manager->getPlayerKeyboardID();
if (input_manager->masterPlayerOnly() && playerID != PLAYER_ID_GAME_MASTER) break;
if (!w->isFocusedForPlayer(playerID)) w->setFocusForPlayer(playerID);
if (playerID != -1 && !w->isFocusedForPlayer(playerID)) w->setFocusForPlayer(playerID);
break;
}

View File

@ -48,14 +48,9 @@ using namespace irr;
*/
namespace GUIEngine
{
#define DEFINE_SCREEN_SINGLETON( ClassName ) \
template<> ClassName* GUIEngine::ScreenSingleton< ClassName >::singleton = NULL
/**
* \brief Declares a class to be a singleton.
* Normally, all screens will be singletons.
* Note that you need to use the 'DEFINE_SCREEN_SINGLETON' macro in a .
* cpp file to actually define the instance (as this can't be done in a .h)
* \ingroup guiengine
*/
template<typename SCREEN>
@ -83,6 +78,8 @@ namespace GUIEngine
}
};
template <typename SCREEN> SCREEN*
ScreenSingleton<SCREEN>::singleton = nullptr;
/**
* \brief Represents a single GUI screen.

View File

@ -210,6 +210,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
READ_PROPERTY(icon, PROP_ICON);
READ_PROPERTY(focus_icon, PROP_FOCUS_ICON);
READ_PROPERTY(text_align, PROP_TEXT_ALIGN);
READ_PROPERTY(text_valign, PROP_TEXT_VALIGN);
READ_PROPERTY(min_value, PROP_MIN_VALUE);
READ_PROPERTY(max_value, PROP_MAX_VALUE);
READ_PROPERTY(square_items, PROP_SQUARE);

View File

@ -1675,7 +1675,7 @@ void Skin::renderSections(PtrVector<Widget>* within_vector)
if (widget.m_type == WTYPE_DIV)
{
if (widget.m_show_bounding_box)
if (widget.m_show_bounding_box && widget.isVisible())
{
if (widget.m_is_bounding_box_round)
{

View File

@ -309,7 +309,9 @@ bool Widget::isVisible() const
{
if (m_element != NULL)
{
assert(m_element->isVisible() == m_is_visible);
// repair mismatch
if (m_element->isVisible() != m_is_visible)
m_element->setVisible(m_is_visible);
}
return m_is_visible;
}

View File

@ -98,6 +98,7 @@ namespace GUIEngine
PROP_ICON,
PROP_FOCUS_ICON,
PROP_TEXT_ALIGN,
PROP_TEXT_VALIGN,
PROP_MIN_VALUE,
PROP_MAX_VALUE,
PROP_MAX_WIDTH,
@ -325,7 +326,7 @@ namespace GUIEngine
* it visible implicitely calls setActive(true). If you mix visiblity and (de)activated calls,
* undefined behavior may ensue (like invisible but clickable buttons).
*/
void setVisible(bool visible);
virtual void setVisible(bool visible);
/** Returns if the element is visible. */
bool isVisible() const;
@ -658,6 +659,7 @@ namespace GUIEngine
/** Gets called when the widget is active and got clicked. (Only works for button widgets for now.) */
virtual void onClick() { }
virtual irr::core::dimension2di getDimension() const { return irr::core::dimension2di(m_w, m_h); }
};

View File

@ -823,6 +823,9 @@ bool CGUIEditBox::processKey(const SEvent& event)
calculateScrollPos();
if (CursorPos > (s32)Text.size())
CursorPos = Text.size();
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
switch(event.KeyInput.Key)
{

View File

@ -76,7 +76,9 @@ void BubbleWidget::replaceText()
else if (m_properties[PROP_TEXT_ALIGN] == "right") align = EGUIA_LOWERRIGHT;
else if (translations->isRTLText(message)) align = EGUIA_LOWERRIGHT;
EGUI_ALIGNMENT valign = EGUIA_CENTER ; //TODO: make label v-align configurable through XML file?
EGUI_ALIGNMENT valign = EGUIA_CENTER;
if (m_properties[PROP_TEXT_VALIGN] == "top") valign = EGUIA_UPPERLEFT;
if (m_properties[PROP_TEXT_VALIGN] == "bottom") valign = EGUIA_LOWERRIGHT;
// find expanded bubble size
int text_height = irrwidget->getTextHeight();

View File

@ -44,6 +44,9 @@ void CheckBoxWidget::add()
m_id = m_element->getID();
m_element->setTabOrder(m_id);
m_element->setTabGroup(false);
if (!m_is_visible)
m_element->setVisible(false);
}
// -----------------------------------------------------------------------------
EventPropagation CheckBoxWidget::transmitEvent(Widget* w,

View File

@ -155,7 +155,7 @@ void DynamicRibbonWidget::add()
if (UserConfigParams::m_hidpi_enabled)
{
m_arrows_w *= 1.5f;
m_arrows_w = int(m_arrows_w*1.5f);
}
const int button_h = m_arrows_w;

View File

@ -416,3 +416,13 @@ void IconButtonWidget::setLabelFont()
}
}
}
// -----------------------------------------------------------------------------
void IconButtonWidget::setVisible(bool visible)
{
Widget::setVisible(visible);
if (m_label != NULL)
m_label->setVisible(visible);
}

View File

@ -33,6 +33,7 @@ namespace irr
#include "guiengine/widget.hpp"
#include "utils/leak_check.hpp"
#include "utils/cpp2011.hpp"
namespace GUIEngine
{
@ -161,6 +162,14 @@ namespace GUIEngine
// --------------------------------------------------------------------
/** Returns the texture of this button. */
const video::ITexture* getTexture();
// --------------------------------------------------------------------
virtual void setVisible(bool visible) OVERRIDE;
// --------------------------------------------------------------------
virtual void elementRemoved() OVERRIDE
{
Widget::elementRemoved();
m_label = NULL;
}
};
}

View File

@ -66,7 +66,10 @@ void LabelWidget::add()
EGUI_ALIGNMENT align = EGUIA_UPPERLEFT;
if (m_properties[PROP_TEXT_ALIGN] == "center") align = EGUIA_CENTER;
else if (m_properties[PROP_TEXT_ALIGN] == "right") align = EGUIA_LOWERRIGHT;
EGUI_ALIGNMENT valign = EGUIA_CENTER ; //TODO: make label v-align configurable through XML file?
EGUI_ALIGNMENT valign = EGUIA_CENTER ;
if (m_properties[PROP_TEXT_VALIGN] == "top") valign = EGUIA_UPPERLEFT;
if (m_properties[PROP_TEXT_VALIGN] == "bottom") valign = EGUIA_LOWERRIGHT;
IGUIStaticText* irrwidget;
if (m_scroll_speed != 0)
@ -107,6 +110,9 @@ void LabelWidget::add()
if (m_scroll_speed <= 0)
m_element->setNotClipped(true);
if (!m_is_visible)
m_element->setVisible(false);
} // add
// ----------------------------------------------------------------------------

View File

@ -108,7 +108,9 @@ namespace GUIEngine
// ------------------------------------------------------------------------
/** Called when players are renumbered (changes the player ID) */
void setPlayerID(const int newPlayerID);
// ------------------------------------------------------------------------
PlayerNameSpinner* getPlayerNameSpinner() const
{ return m_player_ident_spinner; }
// ------------------------------------------------------------------------
/** Returns the ID of this player */
int getPlayerID() const;

View File

@ -63,7 +63,17 @@ public:
m_listeners[n].onTextUpdated();
}
}
if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == IRR_KEY_RETURN)
{
for (unsigned int n=0; n<m_listeners.size(); n++)
{
if (m_listeners[n].onEnterPressed(Text))
{
Text = L"";
CursorPos = 0;
}
}
}
return out;
}

View File

@ -33,6 +33,7 @@ namespace GUIEngine
public:
virtual ~ITextBoxWidgetListener() {}
virtual void onTextUpdated() = 0;
virtual bool onEnterPressed(const irr::core::stringw& text) { return false; }
};
/** \brief A text field widget.

View File

@ -28,18 +28,21 @@
#include "guiengine/screen_keyboard.hpp"
#include "input/device_manager.hpp"
#include "input/gamepad_device.hpp"
#include "input/input.hpp"
#include "input/keyboard_device.hpp"
#include "input/multitouch_device.hpp"
#include "input/input.hpp"
#include "input/wiimote_manager.hpp"
#include "karts/controller/controller.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/demo_world.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "physics/physics.hpp"
#include "race/history.hpp"
#include "replay/replay_recorder.hpp"
#include "states_screens/dialogs/splitscreen_player_dialog.hpp"
#include "states_screens/kart_selection.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/options_screen_device.hpp"
@ -84,6 +87,10 @@ InputManager::InputManager() : m_mode(BOOTSTRAP),
// -----------------------------------------------------------------------------
void InputManager::update(float dt)
{
#ifdef ENABLE_WIIUSE
wiimote_manager->update();
#endif
if(m_timer_in_use)
{
m_timer -= dt;
@ -290,14 +297,14 @@ void InputManager::handleStaticAction(int key, int value)
case IRR_KEY_F11:
if(value && shift_is_pressed && world && RewindManager::isEnabled())
{
printf("Enter rewind to time:");
printf("Enter rewind to time in ticks:");
char s[256];
fgets(s, 256, stdin);
float t;
int t;
StringUtils::fromString(s,t);
RewindManager::get()->rewindTo(t);
Log::info("Rewind", "Rewinding from %f to %f",
world->getTime(), t);
RewindManager::get()->rewindTo(t, world->getTimeTicks());
Log::info("Rewind", "Rewinding from %d to %d",
world->getTimeTicks(), t);
}
break;
@ -705,6 +712,31 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
// when a device presses fire or rescue
if (m_device_manager->getAssignMode() == DETECT_NEW)
{
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isAddingNetworkPlayers())
{
// Ignore release event
if (value == 0)
return;
InputDevice *device = NULL;
if (type == Input::IT_KEYBOARD)
{
//Log::info("InputManager", "New Player Joining with Key %d", button);
device = m_device_manager->getKeyboardFromBtnID(button);
}
else if (type == Input::IT_STICKBUTTON ||
type == Input::IT_STICKMOTION )
{
device = m_device_manager->getGamePadFromIrrID(deviceID);
}
if (device && (action == PA_FIRE || action == PA_MENU_SELECT))
{
if (!GUIEngine::ModalDialog::isADialogActive())
new SplitscreenPlayerDialog(device);
return;
}
}
// Player is unjoining
if ((player != NULL) && (action == PA_RESCUE ||
action == PA_MENU_CANCEL ) )
@ -744,7 +776,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
if (device != NULL)
{
KartSelectionScreen::getRunningInstance()->joinPlayer(device);
KartSelectionScreen::getRunningInstance()->joinPlayer(device, NULL/*player profile*/);
}
}
return; // we're done here, ignore devices that aren't
@ -1195,7 +1227,7 @@ EventPropagation InputManager::input(const SEvent& event)
float factor = UserConfigParams::m_multitouch_tilt_factor;
factor = std::max(factor, 0.1f);
device->updateAxisX(event.AccelerometerEvent.Y / factor);
device->updateAxisX(float(event.AccelerometerEvent.Y) / factor);
}
}

View File

@ -204,7 +204,7 @@ void Attachment::set(AttachmentType type, int ticks,
{
BareNetworkString *buffer = new BareNetworkString(2);
saveState(buffer);
rwm->addEvent(this, buffer);
rwm->addEvent(this, buffer, /*confirmed*/true);
}
#endif
} // set
@ -269,7 +269,13 @@ void Attachment::saveState(BareNetworkString *buffer) const
void Attachment::rewindTo(BareNetworkString *buffer)
{
uint8_t type = buffer->getUInt8();
AttachmentType new_type = AttachmentType(type & 0x7f); // mask out bit 7
// FIXME Sometimes type == 255 is returned, reason unknown
if (new_type > ATTACH_NOTHING)
{
return;
}
// If there is no attachment, clear the attachment if necessary and exit
if(new_type==ATTACH_NOTHING)
@ -360,8 +366,9 @@ void Attachment::hitBanana(Item *item, int new_attachment)
// default time. This is necessary to avoid that a kart lands on the
// same banana again once the explosion animation is finished, giving
// the kart the same penalty twice.
float f = std::max(item->getDisableTime(), kp->getExplosionDuration() + 2.0f);
item->setDisableTime(f);
int ticks = std::max(item->getDisableTicks(),
stk_config->time2Ticks(kp->getExplosionDuration() + 2.0f));
item->setDisableTicks(ticks);
break;
}
case ATTACH_ANVIL:
@ -484,7 +491,7 @@ void Attachment::handleCollisionWithKart(AbstractKart *other)
} // handleCollisionWithKart
//-----------------------------------------------------------------------------
void Attachment::update(float dt)
void Attachment::update(int ticks)
{
if(m_type==ATTACH_NOTHING) return;
@ -493,7 +500,7 @@ void Attachment::update(float dt)
if (m_type == ATTACH_BOMB && m_kart->getKartAnimation() != NULL)
return;
m_ticks_left--; // dt always physics time step
m_ticks_left -= ticks;
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
@ -516,6 +523,7 @@ void Attachment::update(float dt)
m_node->setVisible((division & 0x1) == 0);
}
float dt = stk_config->ticks2Time(ticks);
if (m_node_scale < m_wanted_node_scale)
{
m_node_scale += dt*1.5f;
@ -527,7 +535,7 @@ void Attachment::update(float dt)
if(m_plugin)
{
bool discard = m_plugin->updateAndTestFinished(dt);
bool discard = m_plugin->updateAndTestFinished(ticks);
if(discard)
{
clear(); // also removes the plugin

View File

@ -112,7 +112,7 @@ public:
~Attachment();
void clear ();
void hitBanana(Item *item, int new_attachment=-1);
void update (float dt);
void update(int ticks);
void handleCollisionWithKart(AbstractKart *other);
void set (AttachmentType type, int ticks,
AbstractKart *previous_kart=NULL);

View File

@ -52,7 +52,7 @@ public:
// ------------------------------------------------------------------------
/** Updates a plugin. This is called once each time frame. If the
* function returns true, the attachment is discarded. */
virtual bool updateAndTestFinished(float dt) = 0;
virtual bool updateAndTestFinished(int ticks) = 0;
// ------------------------------------------------------------------------
/** Called when the animation of the Attachment's node is done. */

View File

@ -76,7 +76,7 @@ Bowling::Bowling(AbstractKart *kart)
getBody()->setCollisionFlags(flag);
// should not live forever, auto-destruct after 20 seconds
m_max_lifespan = 20;
m_max_lifespan = stk_config->time2Ticks(20);
m_roll_sfx = SFXManager::get()->createSoundSource("bowling_roll");
m_roll_sfx->play();
@ -118,9 +118,9 @@ void Bowling::init(const XMLNode &node, scene::IMesh *bowling)
* \param dt Time step size.
* \returns True of this object should be removed.
*/
bool Bowling::updateAndDelete(float dt)
bool Bowling::updateAndDelete(int ticks)
{
bool can_be_deleted = Flyable::updateAndDelete(dt);
bool can_be_deleted = Flyable::updateAndDelete(ticks);
if(can_be_deleted)
return true;

View File

@ -53,7 +53,7 @@ public:
Bowling(AbstractKart* kart);
virtual ~Bowling();
static void init(const XMLNode &node, scene::IMesh *bowling);
virtual bool updateAndDelete(float dt);
virtual bool updateAndDelete(int ticks);
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
virtual HitEffect *getHitEffect() const;

View File

@ -70,7 +70,7 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
m_animation = NULL;
m_mass = mass;
m_adjust_up_velocity = true;
m_time_since_thrown = 0;
m_ticks_since_thrown = 0;
m_position_offset = Vec3(0,0,0);
m_owner_has_temporary_immunity = true;
m_do_terrain_info = true;
@ -371,23 +371,33 @@ void Flyable::setAnimation(AbstractKartAnimation *animation)
m_animation = animation;
} // addAnimation
//-----------------------------------------------------------------------------
/** Called once per rendered frame. It is used to only update any graphical
* effects.
* \param dt Time step size (since last call).
*/
void Flyable::updateGraphics(float dt)
{
Moveable::updateGraphics(dt, Vec3(0, 0, 0), btQuaternion(0, 0, 0, 1));
} // updateGraphics
//-----------------------------------------------------------------------------
/** Updates this flyable. It calls Moveable::update. If this function returns
* true, the flyable will be deleted by the projectile manager.
* \param dt Time step size.
* \returns True if this object can be deleted.
*/
bool Flyable::updateAndDelete(float dt)
bool Flyable::updateAndDelete(int ticks)
{
if (hasAnimation())
{
m_animation->update(dt);
Moveable::update(dt);
m_animation->update(stk_config->ticks2Time(ticks));
Moveable::update(ticks);
return false;
} // if animation
m_time_since_thrown += dt;
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
m_ticks_since_thrown += ticks;
if(m_max_lifespan > -1 && m_ticks_since_thrown > m_max_lifespan)
hit(NULL);
if(m_has_hit_something) return true;
@ -465,7 +475,7 @@ bool Flyable::updateAndDelete(float dt)
setVelocity(v);
} // if m_adjust_up_velocity
Moveable::update(dt);
Moveable::update(ticks);
return false;
} // updateAndDelete
@ -478,8 +488,8 @@ bool Flyable::updateAndDelete(float dt)
bool Flyable::isOwnerImmunity(const AbstractKart* kart_hit) const
{
return m_owner_has_temporary_immunity &&
kart_hit == m_owner &&
m_time_since_thrown < 2.0f;
kart_hit == m_owner &&
m_ticks_since_thrown < stk_config->time2Ticks(2.0f);
} // isOwnerImmunity
// ----------------------------------------------------------------------------

View File

@ -22,17 +22,18 @@
#ifndef HEADER_FLYABLE_HPP
#define HEADER_FLYABLE_HPP
#include "items/powerup_manager.hpp"
#include "karts/moveable.hpp"
#include "tracks/terrain_info.hpp"
#include "utils/cpp2011.hpp"
#include <irrString.h>
namespace irr
{
namespace scene { class IMesh; }
}
#include <irrString.h>
using namespace irr;
#include "items/powerup_manager.hpp"
#include "karts/moveable.hpp"
#include "tracks/terrain_info.hpp"
class AbstractKart;
class AbstractKartAnimation;
class HitEffect;
@ -127,11 +128,11 @@ protected:
/** Time since thrown. used so a kart can't hit himself when trying
* something, and also to put some time limit to some collectibles */
float m_time_since_thrown;
int m_ticks_since_thrown;
/** Set to something > -1 if this flyable should auto-destrcut after
* a while. */
float m_max_lifespan;
* that may ticks. */
int m_max_lifespan;
/** If set to true, the kart that throwns this flyable can't collide
* with it for a short time. */
@ -167,7 +168,8 @@ public:
virtual ~Flyable ();
static void init (const XMLNode &node, scene::IMesh *model,
PowerupManager::PowerupType type);
virtual bool updateAndDelete(float);
void updateGraphics(float dt) OVERRIDE;
virtual bool updateAndDelete(int ticks);
virtual void setAnimation(AbstractKartAnimation *animation);
virtual HitEffect* getHitEffect() const;
bool isOwnerImmunity(const AbstractKart *kart_hit) const;

View File

@ -28,6 +28,7 @@
#include "modes/easter_egg_hunt.hpp"
#include "modes/three_strikes_battle.hpp"
#include "modes/world.hpp"
#include "network/rewind_manager.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/drive_graph.hpp"
#include "tracks/drive_node.hpp"
@ -117,8 +118,8 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
m_item_id = -1;
m_collected = false;
m_original_type = ITEM_NONE;
m_deactive_time = 0;
m_time_till_return = 0.0f; // not strictly necessary, see isCollected()
m_deactive_ticks = 0;
m_ticks_till_return = 0; // not strictly necessary, see isCollected()
m_emitter = NULL;
m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER);
switch(m_type)
@ -264,8 +265,8 @@ Item::~Item()
void Item::reset()
{
m_collected = false;
m_time_till_return = 0.0f;
m_deactive_time = 0.0f;
m_ticks_till_return = 0;
m_deactive_ticks = 0;
switch(m_type)
{
case ITEM_BUBBLEGUM:
@ -295,24 +296,24 @@ void Item::reset()
*/
void Item::setParent(AbstractKart* parent)
{
m_event_handler = parent;
m_emitter = parent;
m_deactive_time = 1.5f;
m_event_handler = parent;
m_emitter = parent;
m_deactive_ticks = stk_config->time2Ticks(1.5f);
} // setParent
//-----------------------------------------------------------------------------
/** Updated the item - rotates it, takes care of items coming back into
* the game after it has been collected.
* \param dt Time step size.
* \param ticks Number of physics time steps - should be 1.
*/
void Item::update(float dt)
void Item::update(int ticks)
{
if(m_deactive_time > 0) m_deactive_time -= dt;
if(m_deactive_ticks > 0) m_deactive_ticks -= ticks;
if(m_collected)
{
m_time_till_return -= dt;
if(m_time_till_return<0)
m_ticks_till_return -= ticks;
if(m_ticks_till_return<0)
{
m_collected=false;
@ -321,13 +322,14 @@ void Item::update(float dt)
m_node->setScale(core::vector3df(1,1,1));
}
} // time till return <0 --> is fully visible again
else if ( m_time_till_return <=1.0f )
else if ( m_ticks_till_return <= stk_config->time2Ticks(1.0f) )
{
if (m_node != NULL)
{
// Make it visible by scaling it from 0 to 1:
m_node->setVisible(true);
m_node->setScale(core::vector3df(1,1,1)*(1-m_time_till_return));
float t = stk_config->ticks2Time(m_ticks_till_return);
m_node->setScale(core::vector3df(1,1,1)*(1-t));
}
} // time till return < 1
} // if collected
@ -336,7 +338,11 @@ void Item::update(float dt)
if(!m_rotate || m_node == NULL) return;
// have it rotate
m_rotation_angle += dt * M_PI ;
if (!RewindManager::get()->isRewinding())
{
float dt = stk_config->ticks2Time(ticks);
m_rotation_angle += dt * M_PI;
}
if (m_rotation_angle > M_PI * 2) m_rotation_angle -= M_PI * 2;
btMatrix3x3 m;
@ -362,7 +368,7 @@ void Item::collected(const AbstractKart *kart, float t)
m_event_handler = kart;
if(m_type==ITEM_EASTER_EGG)
{
m_time_till_return=99999;
m_ticks_till_return=stk_config->time2Ticks(99999);
EasterEggHunt *world = dynamic_cast<EasterEggHunt*>(World::getWorld());
assert(world);
world->collectedEasterEgg(kart);
@ -377,16 +383,16 @@ void Item::collected(const AbstractKart *kart, float t)
// Deactivates the item for a certain amount of time. It is used to
// prevent bubble gum from hitting a kart over and over again (in each
// frame) by giving it time to drive away.
m_deactive_time = 0.5f;
m_deactive_ticks = stk_config->time2Ticks(0.5f);
// Set the time till reappear to -1 seconds --> the item will
// reappear immediately.
m_time_till_return = -1;
m_ticks_till_return = -1;
}
else
{
// Note if the time is negative, in update the m_collected flag will
// be automatically set to false again.
m_time_till_return = t;
m_ticks_till_return = stk_config->time2Ticks(t);
if (m_node != NULL)
{
m_node->setVisible(false);
@ -400,7 +406,7 @@ void Item::collected(const AbstractKart *kart, float t)
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
{
m_time_till_return *= 3;
m_ticks_till_return *= 3;
}
} // isCollected

View File

@ -111,7 +111,7 @@ private:
bool m_collected;
/** Time till a collected item reappears. */
float m_time_till_return;
int m_ticks_till_return;
/** Scene node of this item. */
LODNode *m_node;
@ -131,7 +131,7 @@ private:
bool m_rotate;
/** Optionally set this if this item was laid by a particular kart. in
* this case the 'm_deactive_time' will also be set - see below. */
* this case the 'm_deactive_ticks' will also be set - see below. */
const AbstractKart *m_event_handler;
/** Kart that emitted this item if any */
@ -139,7 +139,7 @@ private:
/** Optionally if item was placed by a kart, a timer can be used to
* temporarly deactivate collision so a kart is not hit by its own item */
float m_deactive_time;
int m_deactive_ticks;
/** Counts how often an item is used before it disappears. Used for
* bubble gum to make them disappear after a while. A value >0
@ -176,7 +176,7 @@ public:
Item(const Vec3& xyz, float distance,
TriggerItemListener* trigger);
virtual ~Item ();
void update (float delta);
void update(int ticks);
virtual void collected(const AbstractKart *kart, float t=2.0f);
void setParent(AbstractKart* parent);
void reset();
@ -195,7 +195,7 @@ public:
*/
bool hitKart(const Vec3 &xyz, const AbstractKart *kart=NULL) const
{
if (m_event_handler == kart && m_deactive_time > 0)
if (m_event_handler == kart && m_deactive_ticks > 0)
return false;
Vec3 lc = quatRotate(m_original_rotation, xyz - m_xyz);
// Don't be too strict if the kart is a bit above the item
@ -216,7 +216,7 @@ protected:
bool hitLine(const core::line3df &line,
const AbstractKart *kart=NULL) const
{
if(m_event_handler==kart && m_deactive_time >0) return false;
if(m_event_handler==kart && m_deactive_ticks >0) return false;
Vec3 closest = line.getClosestPoint(m_xyz.toIrrVector());
return hitKart(closest, kart);
@ -251,10 +251,10 @@ public:
* details.
* \param f Time till the item can be used again.
*/
void setDisableTime(float f) { m_time_till_return = f; }
void setDisableTicks(int t) { m_ticks_till_return = t; }
// ------------------------------------------------------------------------
/** Returns the time the item is disabled for. */
float getDisableTime() const { return m_time_till_return; }
int getDisableTicks() const { return m_ticks_till_return; }
// ------------------------------------------------------------------------
/** Returns the XYZ position of the item. */
const Vec3& getXYZ() const { return m_xyz; }

View File

@ -156,7 +156,7 @@ void ItemManager::removeTextures()
* of each race. */
ItemManager::ItemManager()
{
m_switch_time = -1.0f;
m_switch_ticks = -1;
// The actual loading is done in loadDefaultItems
// Prepare the switch to array, which stores which item should be
@ -266,7 +266,7 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
insertItem(item);
if(parent != NULL) item->setParent(parent);
if(m_switch_time>=0)
if(m_switch_ticks>=0)
{
Item::ItemType new_type = m_switch_to[item->getType()];
item->switchTo(new_type, m_item_mesh[(int)new_type],
@ -333,7 +333,7 @@ void ItemManager::checkItemHit(AbstractKart* kart)
if((*i)->hitKart(kart->getXYZ(), kart))
{
// if we're not playing online, pick the item.
if (!RaceEventManager::getInstance()->isRunning())
if (!NetworkConfig::get()->isNetworking())
collectedItem(*i, kart);
else if (NetworkConfig::get()->isServer())
{
@ -354,14 +354,14 @@ void ItemManager::checkItemHit(AbstractKart* kart)
void ItemManager::reset()
{
// If items are switched, switch them back first.
if(m_switch_time>=0)
if(m_switch_ticks>=0)
{
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
if(*i) (*i)->switchBack();
}
m_switch_time = -1.0f;
m_switch_ticks = -1;
}
@ -388,36 +388,36 @@ void ItemManager::reset()
}
} // whilem_all_items.end() i
m_switch_time = -1;
m_switch_ticks = -1;
} // reset
//-----------------------------------------------------------------------------
/** Updates all items, and handles switching items back if the switch time
* is over.
* \param dt Time step.
* \param ticks Number of physics time steps - should be 1.
*/
void ItemManager::update(float dt)
void ItemManager::update(int ticks)
{
// If switch time is over, switch all items back
if(m_switch_time>=0)
if(m_switch_ticks>=0)
{
m_switch_time -= dt;
if(m_switch_time<0)
m_switch_ticks -= ticks;
if(m_switch_ticks<0)
{
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
if(*i) (*i)->switchBack();
} // for m_all_items
} // m_switch_time < 0
} // m_switch_time>=0
} // m_switch_ticks < 0
} // m_switch_ticks>=0
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
if(*i)
{
(*i)->update(dt);
(*i)->update(ticks);
if( (*i)->isUsedUp())
{
deleteItem( *i );
@ -472,16 +472,16 @@ void ItemManager::switchItems()
Item::ItemType new_type = m_switch_to[(*i)->getType()];
if(m_switch_time<0)
if(m_switch_ticks<0)
(*i)->switchTo(new_type, m_item_mesh[(int)new_type], m_item_lowres_mesh[(int)new_type]);
else
(*i)->switchBack();
} // for m_all_items
// if the items are already switched (m_switch_time >=0)
// then switch back, and set m_switch_time to -1 to indicate
// if the items are already switched (m_switch_ticks >=0)
// then switch back, and set m_switch_ticks to -1 to indicate
// that the items are now back to normal.
m_switch_time = m_switch_time < 0 ? stk_config->m_item_switch_time : -1;
m_switch_ticks = m_switch_ticks < 0 ? stk_config->m_item_switch_ticks : -1;
} // switchItems

View File

@ -90,7 +90,7 @@ private:
/** Remaining time that items should remain switched. If the
* value is <0, it indicates that the items are not switched atm. */
float m_switch_time;
int m_switch_ticks;
void insertItem(Item *item);
void deleteItem(Item *item);
@ -106,7 +106,7 @@ public:
AbstractKart* parent=NULL);
Item* newItem (const Vec3& xyz, float distance,
TriggerItemListener* listener);
void update (float delta);
void update (int ticks);
void checkItemHit (AbstractKart* kart);
void reset ();
void collectedItem (Item *item, AbstractKart *kart,

View File

@ -122,24 +122,24 @@ void Plunger::init(const XMLNode &node, scene::IMesh *plunger_model)
* \param dt Time step size.
* \returns True of this object should be removed.
*/
bool Plunger::updateAndDelete(float dt)
bool Plunger::updateAndDelete(int ticks)
{
// In keep-alive mode, just update the rubber band
if(m_keep_alive >= 0)
{
m_keep_alive -= dt;
m_keep_alive -= ticks;
if(m_keep_alive<=0)
{
setHasHit();
return true;
}
if(m_rubber_band != NULL) m_rubber_band->update(dt);
if(m_rubber_band != NULL) m_rubber_band->update(ticks);
return false;
}
// Else: update the flyable and rubber band
bool ret = Flyable::updateAndDelete(dt);
if(m_rubber_band != NULL) m_rubber_band->update(dt);
bool ret = Flyable::updateAndDelete(ticks);
if(m_rubber_band != NULL) m_rubber_band->update(ticks);
return ret;
@ -179,11 +179,12 @@ bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
}
else
{
m_keep_alive = m_owner->getKartProperties()->getPlungerBandDuration();
m_keep_alive = stk_config->time2Ticks(m_owner->getKartProperties()
->getPlungerBandDuration() );
// Make this object invisible by placing it faaar down. Not that if this
// objects is simply removed from the scene graph, it might be auto-deleted
// because the ref count reaches zero.
// Make this object invisible by placing it faaar down. Not that if
// this objects is simply removed from the scene graph, it might be
// auto-deleted because the ref count reaches zero.
scene::ISceneNode *node = getNode();
if(node)
{

View File

@ -40,8 +40,10 @@ class Plunger : public Flyable
private:
/** The rubber band attached to a plunger. */
RubberBand *m_rubber_band;
/** Timer to keep the plunger alive while the rubber band is working. */
float m_keep_alive;
/** Ticks to keep the plunger alive while the rubber band is working. */
int m_keep_alive;
btVector3 m_initial_velocity;
bool m_reverse_mode;
@ -49,7 +51,7 @@ public:
Plunger(AbstractKart *kart);
~Plunger();
static void init(const XMLNode &node, scene::IMesh* missile);
virtual bool updateAndDelete(float dt);
virtual bool updateAndDelete(int ticks);
virtual void hitTrack ();
virtual bool hit (AbstractKart *kart, PhysicalObject *obj=NULL);
@ -57,7 +59,7 @@ public:
/** Sets the keep-alive value. Setting it to 0 will remove the plunger
* at the next update - which is used if the rubber band snaps.
*/
void setKeepAlive(float t) {m_keep_alive = t;}
void setKeepAlive(int ticks) {m_keep_alive = ticks;}
// ------------------------------------------------------------------------
/** No hit effect when it ends. */
virtual HitEffect *getHitEffect() const {return NULL; }

View File

@ -62,10 +62,25 @@ void ProjectileManager::cleanup()
} // cleanup
// -----------------------------------------------------------------------------
/** General projectile update call. */
void ProjectileManager::update(float dt)
/** Called once per rendered frame. It is used to only update any graphical
* effects, and calls updateGraphics in any flyable objects.
* \param dt Time step size (since last call).
*/
void ProjectileManager::updateGraphics(float dt)
{
updateServer(dt);
for (auto p = m_active_projectiles.begin();
p != m_active_projectiles.end(); ++p)
{
(*p)->updateGraphics(dt);
}
} // updateGraphics
// -----------------------------------------------------------------------------
/** General projectile update call. */
void ProjectileManager::update(int ticks)
{
updateServer(ticks);
HitEffects::iterator he = m_active_hit_effects.begin();
while(he!=m_active_hit_effects.end())
@ -77,7 +92,7 @@ void ProjectileManager::update(float dt)
he = next;
}
// Update this hit effect. If it can be removed, remove it.
else if((*he)->updateAndDelete(dt))
else if((*he)->updateAndDelete(ticks))
{
delete *he;
HitEffects::iterator next = m_active_hit_effects.erase(he);
@ -90,12 +105,12 @@ void ProjectileManager::update(float dt)
// -----------------------------------------------------------------------------
/** Updates all rockets on the server (or no networking). */
void ProjectileManager::updateServer(float dt)
void ProjectileManager::updateServer(int ticks)
{
Projectiles::iterator p = m_active_projectiles.begin();
while(p!=m_active_projectiles.end())
{
bool can_be_deleted = (*p)->updateAndDelete(dt);
bool can_be_deleted = (*p)->updateAndDelete(ticks);
if(can_be_deleted)
{
HitEffect *he = (*p)->getHitEffect();

View File

@ -52,13 +52,14 @@ private:
* being shown or have a sfx playing. */
HitEffects m_active_hit_effects;
void updateServer(float dt);
void updateServer(int ticks);
public:
ProjectileManager() {}
~ProjectileManager() {}
void loadData ();
void cleanup ();
void update (float dt);
void update (int ticks);
void updateGraphics (float dt);
Flyable* newProjectile (AbstractKart *kart,
PowerupManager::PowerupType type);
void Deactivate (Flyable *p) {}

View File

@ -42,7 +42,7 @@ float RubberBall::m_st_squash_duration;
float RubberBall::m_st_squash_slowdown;
float RubberBall::m_st_target_distance;
float RubberBall::m_st_target_max_angle;
float RubberBall::m_st_delete_time;
int RubberBall::m_st_delete_ticks;
float RubberBall::m_st_max_height_difference;
float RubberBall::m_st_fast_ping_distance;
float RubberBall::m_st_early_target_factor;
@ -75,7 +75,7 @@ RubberBall::RubberBall(AbstractKart *kart)
// Do not adjust the up velocity
setAdjustUpVelocity(false);
m_max_lifespan = 9999;
m_max_lifespan = stk_config->time2Ticks(9999);
m_target = NULL;
m_aiming_at_target = false;
m_fast_ping = false;
@ -89,7 +89,7 @@ RubberBall::RubberBall(AbstractKart *kart)
m_previous_xyz = m_owner->getXYZ();
m_previous_height = 2.0f; //
// A negative value indicates that the timer is not active
m_delete_timer = -1.0f;
m_delete_ticks = -1;
m_tunnel_count = 0;
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
@ -173,13 +173,13 @@ void RubberBall::computeTarget()
{
// If the firing kart itself is the first kart (that is
// still driving), prepare to remove the rubber ball
if(m_target==m_owner && m_delete_timer < 0)
if(m_target==m_owner && m_delete_ticks < 0)
{
#ifdef PRINT_BALL_REMOVE_INFO
Log::debug("[RubberBall]",
"ball %d removed because owner is target.", m_id);
#endif
m_delete_timer = m_st_delete_time;
m_delete_ticks = m_st_delete_ticks;
}
return;
}
@ -192,7 +192,7 @@ void RubberBall::computeTarget()
Log::debug("[RubberBall]" "ball %d removed because no more active target.",
m_id);
#endif
m_delete_timer = m_st_delete_time;
m_delete_ticks = m_st_delete_ticks;
m_target = m_owner;
} // computeTarget
@ -268,7 +268,7 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
m_st_min_interpolation_distance = 30.0f;
m_st_target_distance = 50.0f;
m_st_target_max_angle = 25.0f;
m_st_delete_time = 10.0f;
m_st_delete_ticks = stk_config->time2Ticks(10.0f);
m_st_max_height_difference = 10.0f;
m_st_fast_ping_distance = 50.0f;
m_st_early_target_factor = 1.0f;
@ -288,8 +288,10 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
if(!node.get("target-distance", &m_st_target_distance))
Log::warn("powerup",
"No target-distance specified for rubber ball.");
if(!node.get("delete-time", &m_st_delete_time))
float f;
if(!node.get("delete-time", &f))
Log::warn("powerup", "No delete-time specified for rubber ball.");
m_st_delete_ticks = stk_config->time2Ticks(f);
if(!node.get("target-max-angle", &m_st_target_max_angle))
Log::warn("powerup", "No target-max-angle specified for rubber ball.");
m_st_target_max_angle *= DEGREE_TO_RAD;
@ -318,17 +320,17 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
* \param dt Time step size.
* \returns True if the rubber ball should be removed.
*/
bool RubberBall::updateAndDelete(float dt)
bool RubberBall::updateAndDelete(int ticks)
{
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return true;
if(m_delete_timer>0)
if(m_delete_ticks>0)
{
m_delete_timer -= dt;
if(m_delete_timer<=0)
m_delete_ticks -= 1;
if(m_delete_ticks<=0)
{
hit(NULL);
#ifdef PRINT_BALL_REMOVE_INFO
@ -343,7 +345,7 @@ bool RubberBall::updateAndDelete(float dt)
// Flyable will call update() of the animation to
// update the ball's position.
m_previous_xyz = getXYZ();
return Flyable::updateAndDelete(dt);
return Flyable::updateAndDelete(ticks);
}
// Update the target in case that the first kart was overtaken (or has
@ -355,9 +357,9 @@ bool RubberBall::updateAndDelete(float dt)
// since it still needs to be adjusted for the height of the terrain.
Vec3 next_xyz;
if(m_aiming_at_target)
moveTowardsTarget(&next_xyz, dt);
moveTowardsTarget(&next_xyz, ticks);
else
interpolate(&next_xyz, dt);
interpolate(&next_xyz, ticks);
// If the ball is close to the ground, we have to start the raycast
// slightly higher (to avoid that the ball tunnels through the floor).
@ -374,7 +376,7 @@ bool RubberBall::updateAndDelete(float dt)
// Flyable::update for rubber balls.
TerrainInfo::update(next_xyz + getNormal()*vertical_offset, -getNormal());
m_height_timer += dt;
m_height_timer += stk_config->ticks2Time(ticks);
float height = updateHeight()+m_extend.getY()*0.5f;
if(UserConfigParams::logFlyable())
@ -426,7 +428,7 @@ bool RubberBall::updateAndDelete(float dt)
// Determine new distance along track
TrackSector::update(next_xyz);
return Flyable::updateAndDelete(dt);
return Flyable::updateAndDelete(ticks);
} // updateAndDelete
// ----------------------------------------------------------------------------
@ -434,9 +436,9 @@ bool RubberBall::updateAndDelete(float dt)
* once the rubber ball is close to its target. It restricts the angle by
* which the rubber ball can change its direction per frame.
* \param next_xyz The position the ball should move to.
* \param dt Time step size.
* \param ticks Number of physics steps - should be 1.
*/
void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
void RubberBall::moveTowardsTarget(Vec3 *next_xyz, int ticks)
{
// If the rubber ball is already close to a target, i.e. aiming
// at it directly, stop interpolating, instead fly straight
@ -447,7 +449,11 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
if(diff.length2()==0)
*next_xyz = getXYZ() - getNormal()*m_previous_height;
else
*next_xyz = getXYZ() - getNormal()*m_previous_height +(dt*m_speed / diff.length())*diff;
{
float dt = stk_config->ticks2Time(ticks);
*next_xyz = getXYZ() - getNormal()*m_previous_height
+ (dt*m_speed / diff.length())*diff;
}
// If ball is close to the target, then explode
if (diff.length() < m_target->getKartLength())
@ -467,10 +473,11 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, float dt)
* \param next_xyz Returns the new position.
* \param The time step size.
*/
void RubberBall::interpolate(Vec3 *next_xyz, float dt)
void RubberBall::interpolate(Vec3 *next_xyz, int ticks)
{
// If we have reached or overshot the next control point, move to the
// the next section of the spline
float dt = stk_config->ticks2Time(ticks);
m_t += m_t_increase * dt;
if(m_t > 1.0f)
{
@ -673,7 +680,7 @@ void RubberBall::updateDistanceToTarget()
// original target, and start deleting it.
if(m_distance_to_target > 0.9f * Track::getCurrentTrack()->getTrackLength())
{
m_delete_timer = m_st_delete_time;
m_delete_ticks = m_st_delete_ticks;
#ifdef PRINT_BALL_REMOVE_INFO
Log::debug("[RubberBall]", "ball %d lost target (overtook?).",
m_id);

View File

@ -23,6 +23,7 @@
#include "items/flyable.hpp"
#include "tracks/track_sector.hpp"
#include "utils/cpp2011.hpp"
class AbstractKart;
class SFXBase;
@ -79,7 +80,7 @@ private:
/** If the ball overtakes its target or starts to aim at the kart which
* originally shot the rubber ball, after this amount of time the
* ball will be deleted. */
static float m_st_delete_time;
static int m_st_delete_ticks;
/** Timer before another rubber ball can be picked up. This is to ensure
* that there are not too many rubber balls on the track in races with many
@ -166,7 +167,7 @@ private:
* originally shot the rubber ball, after a certain amount of time the
* ball will be deleted. This timer tracks this time. If it is < 0
* it indicates that the ball is targeting another kart atm. */
float m_delete_timer;
int m_delete_ticks;
/** The current maximum height of the ball. This value will be
* reduced if the ball gets closer to the target. */
@ -192,8 +193,8 @@ private:
float *f=NULL);
void getNextControlPoint();
float updateHeight();
void interpolate(Vec3 *next_xyz, float dt);
void moveTowardsTarget(Vec3 *next_xyz, float dt);
void interpolate(Vec3 *next_xyz, int ticks);
void moveTowardsTarget(Vec3 *next_xyz, int ticks);
void initializeControlPoints(const Vec3 &xyz);
float getTunnelHeight(const Vec3 &next_xyz,
const float vertical_offset) const;
@ -202,7 +203,7 @@ public:
RubberBall (AbstractKart* kart);
virtual ~RubberBall();
static void init(const XMLNode &node, scene::IMesh *rubberball);
virtual bool updateAndDelete(float dt);
virtual bool updateAndDelete(int ticks) OVERRIDE;
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
virtual void setAnimation(AbstractKartAnimation *animation);
// ------------------------------------------------------------------------

View File

@ -146,7 +146,7 @@ void RubberBand::updatePosition()
* so, an explosion is triggered.
* \param dt: Time step size.
*/
void RubberBand::update(float dt)
void RubberBand::update(int ticks)
{
const KartProperties *kp = m_owner->getKartProperties();
@ -155,7 +155,7 @@ void RubberBand::update(float dt)
// Rubber band snaps
m_plunger->hit(NULL);
// This causes the plunger to be removed at the next update
m_plunger->setKeepAlive(0.0f);
m_plunger->setKeepAlive(0);
return;
}
@ -171,7 +171,7 @@ void RubberBand::update(float dt)
// Rubber band snaps
m_plunger->hit(NULL);
// This causes the plunger to be removed at the next update
m_plunger->setKeepAlive(0.0f);
m_plunger->setKeepAlive(0);
}
// Apply forces (if applicable)
@ -187,7 +187,7 @@ void RubberBand::update(float dt)
// Rubber band snaps
m_plunger->hit(NULL);
// This causes the plunger to be removed at the next update
m_plunger->setKeepAlive(0.0f);
m_plunger->setKeepAlive(0);
return;
}
@ -196,8 +196,8 @@ void RubberBand::update(float dt)
m_owner->increaseMaxSpeed(MaxSpeed::MS_INCREASE_RUBBER,
kp->getPlungerBandSpeedIncrease(),
/*engine_force*/ 0.0f,
/*duration*/0.1f,
kp->getPlungerBandFadeOutTime());
/*duration*/stk_config->time2Ticks(0.1f),
kp->getPlungerBandFadeOutTicks());
if(m_attached_state==RB_TO_KART)
m_hit_kart->getBody()->applyCentralForce(diff*(-force));
}
@ -260,7 +260,7 @@ void RubberBand::hit(AbstractKart *kart_hit, const Vec3 *track_xyz)
if(kart_hit->isShielded())
{
kart_hit->decreaseShieldTime();
m_plunger->setKeepAlive(0.0f);
m_plunger->setKeepAlive(0);
return;
}

View File

@ -66,7 +66,7 @@ private:
public:
RubberBand(Plunger *plunger, AbstractKart *kart);
~RubberBand();
void update(float dt);
void update(int ticks);
void hit(AbstractKart *kart_hit, const Vec3 *track_xyz=NULL);
}; // RubberBand
#endif

View File

@ -114,8 +114,9 @@ Swatter::~Swatter()
* \param dt Time step size.
* \return True if the attachment should be discarded.
*/
bool Swatter::updateAndTestFinished(float dt)
bool Swatter::updateAndTestFinished(int ticks)
{
float dt = stk_config->ticks2Time(ticks);
if (!m_discard_now)
{
if (m_removing_bomb)

View File

@ -21,6 +21,7 @@
#include "config/stk_config.hpp"
#include "items/attachment_plugin.hpp"
#include "utils/cpp2011.hpp"
#include "utils/no_copy.hpp"
#include "utils/random_generator.hpp"
@ -79,7 +80,7 @@ public:
Swatter(AbstractKart *kart, bool was_bomb,
scene::ISceneNode* bomb_scene_node);
virtual ~Swatter();
bool updateAndTestFinished(float dt);
bool updateAndTestFinished(int ticks) OVERRIDE;
// ------------------------------------------------------------------------
/** Returns if the swatter is currently aiming, i.e. can be used to

View File

@ -253,7 +253,7 @@ public:
virtual float getFinishTime() const = 0;
// ------------------------------------------------------------------------
/** Returns true if the kart has a plunger attached to its face. */
virtual float getBlockedByPlungerTime() const = 0;
virtual int getBlockedByPlungerTicks() const = 0;
// ------------------------------------------------------------------------
/** Sets that the view is blocked by a plunger. The duration depends on
* the difficulty, see KartPorperties getPlungerInFaceTime. */
@ -282,10 +282,9 @@ public:
virtual float getCurrentMaxSpeed() const = 0;
// ------------------------------------------------------------------------
/** Returns how much increased speed time is left over in the given
* category. Not pure abstract, since there is no need to implement this
* e.g. in Ghost.
* category.
* \param category Which category to report on. */
virtual float getSpeedIncreaseTimeLeft(unsigned int category) const = 0;
virtual int getSpeedIncreaseTicksLeft(unsigned int category) const = 0;
// ------------------------------------------------------------------------
/** Sets the kart AI boost state.
@ -333,7 +332,7 @@ public:
* \param max_speed_fraction Fraction of top speed to allow only.
* \param fade_in_time How long till maximum speed is capped. */
virtual void setSlowdown(unsigned int category, float max_speed_fraction,
float fade_in_time) = 0;
int fade_in_time) = 0;
// ------------------------------------------------------------------------
/** Returns the remaining collected energy. */
virtual float getEnergy() const = 0;
@ -394,7 +393,7 @@ public:
/** Return whether nitro is being used despite the nitro button not being
* pressed due to minimal use time requirements
*/
virtual float isOnMinNitroTime() const = 0;
virtual bool isOnMinNitroTime() const = 0;
// ------------------------------------------------------------------------
/** Returns the current material the kart is on. */
virtual const Material *getMaterial() const = 0;
@ -445,7 +444,7 @@ public:
/** Returns if the kart is invulnerable. */
virtual bool isInvulnerable() const = 0;
// ------------------------------------------------------------------------
virtual void setInvulnerableTime(float t) = 0;
virtual void setInvulnerableTicks(int ticks) = 0;
// ------------------------------------------------------------------------
/** Returns if the kart is protected by a shield. */
virtual bool isShielded() const = 0;
@ -496,10 +495,6 @@ public:
/** Set a text that is displayed on top of a kart.
*/
virtual void setOnScreenText(const wchar_t *text) = 0;
// -------------------------------------------------------------------------
/** Counter which is used for displaying wrong way message after a delay */
virtual float getWrongwayCounter() = 0;
virtual void setWrongwayCounter(float counter) = 0;
// ------------------------------------------------------------------------
/** Returns whether this kart wins or loses. */
virtual bool getRaceResult() const = 0;

View File

@ -53,7 +53,7 @@ void AIBaseController::reset()
//-----------------------------------------------------------------------------
void AIBaseController::update(float dt)
void AIBaseController::update(int ticks)
{
m_stuck = false;
}
@ -193,7 +193,7 @@ void AIBaseController::setSteering(float angle, float dt)
if (steer_fraction > 1.0f) steer_fraction = 1.0f;
else if(steer_fraction < -1.0f) steer_fraction = -1.0f;
if(m_kart->getBlockedByPlungerTime()>0)
if(m_kart->getBlockedByPlungerTicks()>0)
{
if (steer_fraction > 0.5f) steer_fraction = 0.5f;
else if(steer_fraction < -0.5f) steer_fraction = -0.5f;

View File

@ -20,6 +20,7 @@
#define HEADER_AI_BASE_CONTROLLER_HPP
#include "karts/controller/controller.hpp"
#include "utils/cpp2011.hpp"
class AIProperties;
class Track;
@ -71,9 +72,10 @@ protected:
/** This can be called to detect if the kart is stuck (i.e. repeatedly
* hitting part of the track). */
bool isStuck() const { return m_stuck; }
// ------------------------------------------------------------------------
void determineTurnRadius(const Vec3 &end, Vec3 *center,
float *radius) const;
virtual void update (float delta);
virtual void update(int ticks);
virtual void setSteering (float angle, float dt);
// ------------------------------------------------------------------------
/** Return true if AI can skid now. */
@ -83,21 +85,28 @@ public:
AIBaseController(AbstractKart *kart);
virtual ~AIBaseController() {};
virtual void reset();
virtual bool disableSlipstreamBonus() const;
virtual void crashed(const Material *m);
virtual bool disableSlipstreamBonus() const OVERRIDE;
virtual void crashed(const Material *m) OVERRIDE;
static void enableDebug() {m_ai_debug = true; }
static void setTestAI(int n) {m_test_ai = n; }
static int getTestAI() { return m_test_ai; }
virtual void crashed(const AbstractKart *k) {};
virtual void handleZipper(bool play_sound) {};
virtual void finishedRace(float time) {};
virtual void crashed(const AbstractKart *k) OVERRIDE {};
virtual void handleZipper(bool play_sound) OVERRIDE {};
virtual void finishedRace(float time) OVERRIDE {};
virtual void collectedItem(const Item &item, int add_info=-1,
float previous_energy=0) {};
virtual void setPosition(int p) {};
virtual bool isPlayerController() const { return false; }
virtual bool isLocalPlayerController() const { return false; }
virtual void action(PlayerAction action, int value) {};
float previous_energy=0) OVERRIDE {};
virtual void setPosition(int p) OVERRIDE {};
virtual bool isPlayerController() const OVERRIDE { return false; }
virtual bool isLocalPlayerController() const OVERRIDE { return false; }
virtual bool action(PlayerAction action, int value, bool dry_run=false) OVERRIDE
{
return true;
};
virtual void skidBonusTriggered() {};
// ------------------------------------------------------------------------
/** Not used for AIs. */
virtual void saveState(BareNetworkString *buffer) const OVERRIDE {}
virtual void rewindTo(BareNetworkString *buffer) OVERRIDE {}
}; // AIBaseController

View File

@ -195,11 +195,11 @@ void AIBaseLapController::computePath()
/** Updates the ai base controller each time step. Note that any calls to
* isStuck() must be done before update is called, since update will call
* AIBaseController::update() which will reset the isStuck flag!
* \param dt Time step size.
* \param ticks Number of physics time steps - should be 1.
*/
void AIBaseLapController::update(float dt)
void AIBaseLapController::update(int ticks)
{
AIBaseController::update(dt);
AIBaseController::update(ticks);
if(DriveGraph::get())
{
// Update the current node:
@ -252,7 +252,7 @@ float AIBaseLapController::steerToAngle(const unsigned int sector,
//Desired angle minus current angle equals how many angles to turn
float steer_angle = angle - m_kart->getHeading();
if(m_kart->getBlockedByPlungerTime()>0)
if(m_kart->getBlockedByPlungerTicks()>0)
steer_angle += add_angle*0.2f;
else
steer_angle += add_angle;

View File

@ -53,9 +53,9 @@ protected:
* graph nodes. */
std::vector<std::vector<int> > m_all_look_aheads;
virtual void update (float delta) ;
virtual void update(int ticks);
virtual unsigned int getNextSector(unsigned int index);
virtual void newLap (int lap);
virtual void newLap(int lap);
//virtual void setControllerName(const std::string &name);
float steerToAngle (const unsigned int sector, const float angle);

View File

@ -59,8 +59,8 @@ void ArenaAI::reset()
m_reverse_point = Vec3(0, 0, 0);
m_time_since_last_shot = 0.0f;
m_time_since_driving = 0.0f;
m_time_since_off_road = 0.0f;
m_time_since_reversing = 0.0f;
m_ticks_since_off_road = 0;
m_ticks_since_reversing = 0;
m_time_since_uturn = 0.0f;
m_turn_radius = 0.0f;
m_steering_angle = 0.0f;
@ -74,9 +74,9 @@ void ArenaAI::reset()
/** This is the main entry point for the AI.
* It is called once per frame for each AI and determines the behaviour of
* the AI, e.g. steering, accelerating/braking, firing.
* \param dt Time step size.
* \param ticks Number of physics time steps - should be 1.
*/
void ArenaAI::update(float dt)
void ArenaAI::update(int ticks)
{
// This is used to enable firing an item backwards.
m_controls->setLookBack(false);
@ -96,30 +96,31 @@ void ArenaAI::update(float dt)
if (!isKartOnRoad() && m_kart->isOnGround())
{
m_time_since_off_road += dt;
m_ticks_since_off_road += ticks;
}
else if (m_time_since_off_road != 0.0f)
else if (m_ticks_since_off_road != 0)
{
m_time_since_off_road = 0.0f;
m_ticks_since_off_road = 0;
}
// If the kart needs to be rescued, do it now (and nothing else)
if (m_time_since_off_road > 5.0f && m_kart->isOnGround())
if (m_ticks_since_off_road > stk_config->time2Ticks(5.0f) &&
m_kart->isOnGround() )
{
m_time_since_off_road = 0.0f;
m_ticks_since_off_road = 0;
new RescueAnimation(m_kart);
AIBaseController::update(dt);
AIBaseController::update(ticks);
return;
}
if (isWaiting())
{
AIBaseController::update(dt);
AIBaseController::update(ticks);
return;
}
float dt = stk_config->ticks2Time(ticks);
checkIfStuck(dt);
if (gettingUnstuck(dt))
if (gettingUnstuck(ticks))
return;
findTarget();
@ -156,7 +157,7 @@ void ArenaAI::update(float dt)
setSteering(m_steering_angle, dt);
}
AIBaseController::update(dt);
AIBaseController::update(ticks);
} // update
@ -385,22 +386,23 @@ void ArenaAI::doUTurn(const float dt)
* \param dt Time step size.
* \return True if getting stuck is needed to be done.
*/
bool ArenaAI::gettingUnstuck(const float dt)
bool ArenaAI::gettingUnstuck(int ticks)
{
if (!m_is_stuck || m_is_uturn) return false;
resetAfterStop();
float dt = stk_config->ticks2Time(ticks);
setSteering(0.0f, dt);
m_controls->setBrake(true);
m_time_since_reversing += dt;
m_ticks_since_reversing += ticks;
if (m_time_since_reversing >= 1.0f)
if (m_ticks_since_reversing >= stk_config->time2Ticks(1.0f))
{
m_is_stuck = false;
m_time_since_reversing = 0.0f;
m_ticks_since_reversing = 0;
}
AIBaseController::update(dt);
AIBaseController::update(ticks);
return true;
} // gettingUnstuck

View File

@ -89,7 +89,7 @@ private:
* until facing in front of it. */
Vec3 m_reverse_point;
/** Indicates that the kart is currently stuck, and m_time_since_reversing
/** Indicates that the kart is currently stuck, and m_ticks_since_reversing
* is counting down. */
bool m_is_stuck;
@ -105,7 +105,7 @@ private:
float m_time_since_last_shot;
/** This is a timer that counts down when the kart is reversing to get unstuck. */
float m_time_since_reversing;
float m_ticks_since_reversing;
/** This is a timer that counts down when the kart is starting to drive. */
float m_time_since_driving;
@ -114,7 +114,7 @@ private:
float m_time_since_uturn;
/** This is a timer that counts when the kart start going off road. */
float m_time_since_off_road;
int m_ticks_since_off_road;
/** Used to determine braking and nitro usage. */
float m_turn_radius;
@ -142,7 +142,7 @@ private:
// ------------------------------------------------------------------------
void doUTurn(const float dt);
// ------------------------------------------------------------------------
bool gettingUnstuck(const float dt);
bool gettingUnstuck(int ticks);
// ------------------------------------------------------------------------
bool updateAimingPosition(Vec3* target_point);
// ------------------------------------------------------------------------
@ -183,11 +183,11 @@ public:
// ------------------------------------------------------------------------
virtual ~ArenaAI() {}
// ------------------------------------------------------------------------
virtual void update (float delta) OVERRIDE;
virtual void update(int ticks) OVERRIDE;
// ------------------------------------------------------------------------
virtual void reset () OVERRIDE;
virtual void reset() OVERRIDE;
// ------------------------------------------------------------------------
virtual void newLap (int lap) OVERRIDE {}
virtual void newLap(int lap) OVERRIDE {}
};

View File

@ -21,6 +21,8 @@
#include <irrString.h>
using namespace irr;
class BareNetworkString;
/**
* \defgroup controller Karts/controller
* Contains kart controllers, which are either human players or AIs
@ -31,6 +33,7 @@ using namespace irr;
#include "states_screens/state_manager.hpp"
class AbstractKart;
class BareNetworString;
class Item;
class KartControl;
class Material;
@ -58,7 +61,7 @@ public:
Controller (AbstractKart *kart);
virtual ~Controller () {};
virtual void reset () = 0;
virtual void update (float dt) = 0;
virtual void update (int ticks) = 0;
virtual void handleZipper (bool play_sound) = 0;
virtual void collectedItem (const Item &item, int add_info=-1,
float previous_energy=0) = 0;
@ -74,6 +77,9 @@ public:
* rubber-banding. */
virtual bool isPlayerController () const = 0;
virtual bool disableSlipstreamBonus() const = 0;
virtual void saveState(BareNetworkString *buffer) const = 0;
virtual void rewindTo(BareNetworkString *buffer) = 0;
// ---------------------------------------------------------------------------
/** Sets the controller name for this controller. */
virtual void setControllerName(const std::string &name)
@ -83,7 +89,7 @@ public:
const std::string &getControllerName() const { return m_controller_name; }
// ------------------------------------------------------------------------
/** Default: ignore actions. Only PlayerController get them. */
virtual void action(PlayerAction action, int value) = 0;
virtual bool action(PlayerAction action, int value, bool dry_run=false) = 0;
// ------------------------------------------------------------------------
/** Callback whenever a new lap is triggered. Used by the AI
* to trigger a recomputation of the way to use. */

View File

@ -172,7 +172,7 @@ void EndController::action(PlayerAction action, int value)
} // action
//-----------------------------------------------------------------------------
void EndController::update(float dt)
void EndController::update(int ticks)
{
// This is used to enable firing an item backwards.
m_controls->setLookBack(false);
@ -180,7 +180,7 @@ void EndController::update(float dt)
m_controls->setBrake(false);
m_controls->setAccel(1.0f);
AIBaseLapController::update(dt);
AIBaseLapController::update(ticks);
// In case of battle mode: don't do anything
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES ||
@ -198,6 +198,7 @@ void EndController::update(float dt)
calcSteps();
/*Response handling functions*/
float dt = stk_config->ticks2Time(ticks);
handleSteering(dt);
handleRescue(dt);
} // update

View File

@ -84,7 +84,7 @@ public:
EndController(AbstractKart *kart,
Controller *prev_controller);
~EndController();
virtual void update (float delta) ;
virtual void update (int ticks) ;
virtual void reset ();
virtual void action (PlayerAction action, int value);
virtual void newLap (int lap);

View File

@ -35,7 +35,7 @@ void GhostController::reset()
} // reset
//-----------------------------------------------------------------------------
void GhostController::update(float dt)
void GhostController::update(int ticks)
{
m_current_time = World::getWorld()->getTime();
// Find (if necessary) the next index to use
@ -82,9 +82,10 @@ void GhostController::addReplayTime(float time)
} // addReplayTime
//-----------------------------------------------------------------------------
void GhostController::action(PlayerAction action, int value)
bool GhostController::action(PlayerAction action, int value, bool dry_run)
{
// Watching replay use only
if (action == PA_LOOK_BACK)
m_controls->setLookBack(value!=0);
return true;
} // action

View File

@ -47,7 +47,7 @@ public:
GhostController(AbstractKart *kart, core::stringw display_name);
virtual ~GhostController() {};
virtual void reset() OVERRIDE;
virtual void update (float dt) OVERRIDE;
virtual void update (int ticks) OVERRIDE;
virtual bool disableSlipstreamBonus() const OVERRIDE { return true; }
virtual void crashed(const Material *m) OVERRIDE {}
virtual void crashed(const AbstractKart *k) OVERRIDE {}
@ -58,9 +58,13 @@ public:
virtual void setPosition(int p) OVERRIDE {}
virtual bool isPlayerController() const OVERRIDE { return false; }
virtual bool isLocalPlayerController() const OVERRIDE { return false; }
virtual void action(PlayerAction action, int value) OVERRIDE;
virtual bool action(PlayerAction action, int value,
bool dry_run=false) OVERRIDE;
virtual void skidBonusTriggered() OVERRIDE {}
virtual void newLap(int lap) OVERRIDE {}
virtual void saveState(BareNetworkString *buffer) const {};
virtual void rewindTo(BareNetworkString *buffer) {};
void addReplayTime(float time);
// ------------------------------------------------------------------------
bool isReplayEnd() const

View File

@ -18,6 +18,7 @@
#include "karts/controller/kart_control.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/rewind_manager.hpp"
@ -38,7 +39,7 @@ void KartControl::rewind(BareNetworkString *buffer)
if(buffer->getTotalSize()>1)
{
// Full state including accel and steering was saved
setFromBuffer(buffer);
rewindTo(buffer);
}
else // only a button event was stored
{
@ -46,140 +47,58 @@ void KartControl::rewind(BareNetworkString *buffer)
}
} // rewind
// ------------------------------------------------------------------------
/** Sets this KartControl form the given value (basically a copy). This
* function uses the explicit setSteer() etc function, which means that
* rewind information will be collected.
*/
void KartControl::set(const KartControl &c)
{
setAccel(c.getAccel());
setBrake(c.getBrake());
setFire(c.getFire());
setLookBack(c.getLookBack());
setNitro(c.getNitro());
setRescue(c.getRescue());
setSkidControl(c.getSkidControl());
setSteer(c.getSteer());
} // set
// ------------------------------------------------------------------------
/** Sets the current steering value. */
void KartControl::setSteer(float f)
{
float old_steer = m_steer;
m_steer = f;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_steer != m_steer )
{
// Save full status
BareNetworkString *buffer = new BareNetworkString(getLength());
copyToBuffer(buffer);
RewindManager::get()->addEvent(this, buffer);
}
} // setSteer
// ----------------------------------------------------------------------------
/** Sets the acceleration. */
void KartControl::setAccel(float f)
{
float old_accel = m_accel;
m_accel = f;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_accel != m_accel )
{
BareNetworkString *buffer = new BareNetworkString(getLength());
copyToBuffer(buffer);
RewindManager::get()->addEvent(this, buffer);
}
} // setAccel
// ----------------------------------------------------------------------------
/** Sets if the kart is braking. */
void KartControl::setBrake(bool b)
{
bool old_brake = m_brake;
m_brake = b;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_brake != m_brake )
{
// Only store the buttons in this case
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // setBrake
// ----------------------------------------------------------------------------
/** Sets if the kart activates nitro. */
void KartControl::setNitro(bool b)
{
bool old_nitro = m_nitro;
m_nitro = b;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_nitro != m_nitro )
{
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // setNitro
// ----------------------------------------------------------------------------
/** Sets the skid control for this kart. */
void KartControl::setSkidControl(SkidControl sc)
{
SkidControl old_skid = m_skid;
m_skid = sc;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_skid != m_skid )
{
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // seSkidControl
// ----------------------------------------------------------------------------
/** Returns if this kart wants to get rescued. */
void KartControl::setRescue(bool b)
{
bool old_rescue = m_rescue;
m_rescue = b;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_rescue != m_rescue)
{
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // setRescue
// ----------------------------------------------------------------------------
/** Sets if the kart wants to fire. */
void KartControl::setFire(bool b)
{
bool old_fire = m_fire;
m_fire = b;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_fire != m_fire )
{
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // setFire
// ----------------------------------------------------------------------------
/** Sets if the kart wants to look (and therefore also fires) backwards. */
void KartControl::setLookBack(bool b)
{
bool old_look = m_look_back;
m_look_back = b;
if (RewindManager::isEnabled() && !RewindManager::get()->isRewinding() &&
old_look != m_look_back)
{
BareNetworkString *buffer = new BareNetworkString(1);
buffer->addUInt8(getButtonsCompressed());
RewindManager::get()->addEvent(this, buffer);
}
} // setLookBack

View File

@ -61,7 +61,6 @@ public:
void setRescue(bool b);
void setFire(bool b);
void setLookBack(bool b);
void set(const KartControl &c);
// ------------------------------------------------------------------------
KartControl()
@ -101,7 +100,7 @@ public:
static int getLength() { return 9; }
// ------------------------------------------------------------------------
/** Copies the important data from this objects into a memory buffer. */
void copyToBuffer(BareNetworkString *buffer) const
void saveState(BareNetworkString *buffer) const
{
buffer->add(m_steer);
buffer->add(m_accel);
@ -110,7 +109,7 @@ public:
// ------------------------------------------------------------------------
/** Restores this object from a previously saved memory buffer. */
void setFromBuffer(BareNetworkString *buffer)
void rewindTo(BareNetworkString *buffer)
{
m_steer = buffer->getFloat();
m_accel = buffer->getFloat();

View File

@ -38,7 +38,8 @@
#include "karts/rescue_animation.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/race_event_manager.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/rewind_manager.hpp"
#include "race/history.hpp"
#include "states_screens/race_gui_base.hpp"
#include "tracks/track.hpp"
@ -138,36 +139,50 @@ void LocalPlayerController::resetInputState()
* if between 1 and 32767, it indicates an analog value,
* and if it's 0 it indicates that the corresponding button
* was released.
* \param dry_run If set it will return if this action will trigger a
* state change or not.
* \return True if dry_run==true and a state change would be triggered.
* If dry_run==false, it returns true.
*/
void LocalPlayerController::action(PlayerAction action, int value)
bool LocalPlayerController::action(PlayerAction action, int value,
bool dry_run)
{
PlayerController::action(action, value);
// If this event does not change the control state (e.g.
// it's a (auto) repeat event), do nothing. This especially
// optimises traffic to the server and other clients.
if (!PlayerController::action(action, value, /*dry_run*/true)) return false;
// If this is a client, send the action to the server
if (World::getWorld()->isNetworkWorld() &&
NetworkConfig::get()->isClient() &&
RaceEventManager::getInstance()->isRunning() )
// Register event with history
if(!history->replayHistory())
history->addEvent(m_kart->getWorldKartId(), action, value);
// If this is a client, send the action to networking layer
if (World::getWorld()->isNetworkWorld() &&
NetworkConfig::get()->isClient() &&
!RewindManager::get()->isRewinding() )
{
RaceEventManager::getInstance()->controllerAction(this, action, value);
GameProtocol::lock()
->controllerAction(m_kart->getWorldKartId(),
action, value,
m_steer_val_l, m_steer_val_r);
}
return PlayerController::action(action, value, /*dry_run*/false);
} // action
//-----------------------------------------------------------------------------
/** Handles steering for a player kart.
*/
void LocalPlayerController::steer(float dt, int steer_val)
void LocalPlayerController::steer(int ticks, int steer_val)
{
if(UserConfigParams::m_gamepad_debug)
{
Log::debug("LocalPlayerController", "steering: steer_val %d ", steer_val);
RaceGUIBase* gui_base = World::getWorld()->getRaceGUI();
gui_base->clearAllMessages();
gui_base->addMessage(StringUtils::insertValues(L"steer_val %i", steer_val),
m_kart, 1.0f,
video::SColor(255, 255, 0, 255), false);
}
PlayerController::steer(dt, steer_val);
PlayerController::steer(ticks, steer_val);
if(UserConfigParams::m_gamepad_debug)
{
@ -179,7 +194,7 @@ void LocalPlayerController::steer(float dt, int steer_val)
//-----------------------------------------------------------------------------
/** Updates the player kart, called once each timestep.
*/
void LocalPlayerController::update(float dt)
void LocalPlayerController::update(int ticks)
{
if (UserConfigParams::m_gamepad_debug)
{
@ -188,7 +203,7 @@ void LocalPlayerController::update(float dt)
Log::debug("LocalPlayerController", "irr_driver", "-------------------------------------");
}
PlayerController::update(dt);
PlayerController::update(ticks);
// look backward when the player requests or
// if automatic reverse camera is active

View File

@ -54,14 +54,15 @@ private:
SFXBuffer *m_grab_sound;
SFXBuffer *m_full_sound;
virtual void steer(float, int) OVERRIDE;
virtual void steer(int, int) OVERRIDE;
virtual void displayPenaltyWarning() OVERRIDE;
public:
LocalPlayerController(AbstractKart *kart,
const int local_playerID);
~LocalPlayerController();
void update (float) OVERRIDE;
void action (PlayerAction action, int value) OVERRIDE;
void update (int ticks) OVERRIDE;
bool action (PlayerAction action, int value,
bool dry_run=false) OVERRIDE;
virtual void handleZipper (bool play_sound) OVERRIDE;
void collectedItem (const Item &item, int add_info=-1,
float previous_energy=0) OVERRIDE;

View File

@ -38,7 +38,7 @@
PlayerController::PlayerController(AbstractKart *kart)
: Controller(kart)
{
m_penalty_time = 0.0f;
m_penalty_ticks = 0;
} // PlayerController
//-----------------------------------------------------------------------------
@ -53,13 +53,13 @@ PlayerController::~PlayerController()
*/
void PlayerController::reset()
{
m_steer_val_l = 0;
m_steer_val_r = 0;
m_steer_val = 0;
m_prev_brake = 0;
m_prev_accel = 0;
m_prev_nitro = false;
m_penalty_time = 0;
m_steer_val_l = 0;
m_steer_val_r = 0;
m_steer_val = 0;
m_prev_brake = 0;
m_prev_accel = 0;
m_prev_nitro = false;
m_penalty_ticks = 0;
} // reset
// ----------------------------------------------------------------------------
@ -85,98 +85,144 @@ void PlayerController::resetInputState()
* releasing right, the steering must switch to left again. Similarly it
* handles 'press left, press right, release left' (in which case still
* right must be selected). Similarly for braking and acceleration.
* \param action The action to be executed.
* \param value If 32768, it indicates a digital value of 'fully set'
* if between 1 and 32767, it indicates an analog value,
* and if it's 0 it indicates that the corresponding button
* was released.
* This function can be run in two modes: first, if 'dry_run' is set,
* it will return true if this action will cause a state change. This
* is sued in networking to avoid sending events to the server (and then
* to other clients) if they are just (e.g. auto) repeated events/
* \param action The action to be executed.
* \param value If 32768, it indicates a digital value of 'fully set'
* if between 1 and 32767, it indicates an analog value,
* and if it's 0 it indicates that the corresponding button
* was released.
* \param dry_run If set, it will only test if the parameter will trigger
* a state change. If not set, the appropriate actions
* (i.e. input state change) will be done.
* \return If dry_run is set, will return true if this action will
* cause a state change. If dry_run is not set, will return
* false.
*/
void PlayerController::action(PlayerAction action, int value)
bool PlayerController::action(PlayerAction action, int value, bool dry_run)
{
/** If dry_run (parameter) is true, this macro tests if this action would
* trigger a state change in the specified variable (without actually
* doing it). If it will trigger a state change, the macro will
* immediatley return to the caller. If dry_run is false, it will only
* assign the new value to the variable (and not return to the user
* early). The do-while(0) helps using this macro e.g. in the 'then'
* clause of an if statement. */
#define SET_OR_TEST(var, value) \
do \
{ \
if(dry_run) \
{ \
if (var != (value) ) return true; \
} \
else \
{ \
var = value; \
} \
} while(0)
/** Basically the same as the above macro, but is uses getter/setter
* functions. The name of the setter/getter is set'name'(value) and
* get'name'(). */
#define SET_OR_TEST_GETTER(name, value) \
do \
{ \
if(dry_run) \
{ \
if (m_controls->get##name() != (value) ) return true; \
} \
else \
{ \
m_controls->set##name(value); \
} \
} while(0)
switch (action)
{
case PA_STEER_LEFT:
m_steer_val_l = value;
SET_OR_TEST(m_steer_val_l, value);
if (value)
{
m_steer_val = value;
if(m_controls->getSkidControl()==KartControl::SC_NO_DIRECTION)
m_controls->setSkidControl(KartControl::SC_LEFT);
SET_OR_TEST(m_steer_val, value);
if (m_controls->getSkidControl() == KartControl::SC_NO_DIRECTION)
SET_OR_TEST_GETTER(SkidControl, KartControl::SC_LEFT);
}
else
m_steer_val = m_steer_val_r;
SET_OR_TEST(m_steer_val, m_steer_val_r);
break;
case PA_STEER_RIGHT:
m_steer_val_r = -value;
SET_OR_TEST(m_steer_val_r, -value);
if (value)
{
m_steer_val = -value;
if(m_controls->getSkidControl()==KartControl::SC_NO_DIRECTION)
m_controls->setSkidControl(KartControl::SC_RIGHT);
SET_OR_TEST(m_steer_val, -value);
if (m_controls->getSkidControl() == KartControl::SC_NO_DIRECTION)
SET_OR_TEST_GETTER(SkidControl, KartControl::SC_RIGHT);
}
else
m_steer_val = m_steer_val_l;
SET_OR_TEST(m_steer_val, m_steer_val_l);
break;
case PA_ACCEL:
m_prev_accel = value;
if (value && !(m_penalty_time > 0.0f))
SET_OR_TEST(m_prev_accel, value);
if (value && !(m_penalty_ticks > 0))
{
m_controls->setAccel(value/32768.0f);
m_controls->setBrake(false);
m_controls->setNitro(m_prev_nitro);
SET_OR_TEST_GETTER(Accel, value/32768.0f);
SET_OR_TEST_GETTER(Brake, false);
SET_OR_TEST_GETTER(Nitro, m_prev_nitro);
}
else
{
m_controls->setAccel(0.0f);
m_controls->setBrake(m_prev_brake);
m_controls->setNitro(false);
SET_OR_TEST_GETTER(Accel, 0.0f);
SET_OR_TEST_GETTER(Brake, m_prev_brake);
SET_OR_TEST_GETTER(Nitro, false);
}
break;
case PA_BRAKE:
m_prev_brake = value!=0;
SET_OR_TEST(m_prev_brake, value!=0);
// let's consider below that to be a deadzone
if(value > 32768/2)
{
m_controls->setBrake(true);
m_controls->setAccel(0.0f);
m_controls->setNitro(false);
SET_OR_TEST_GETTER(Brake, true);
SET_OR_TEST_GETTER(Accel, 0.0f);
SET_OR_TEST_GETTER(Nitro, false);
}
else
{
m_controls->setBrake(false);
m_controls->setAccel(m_prev_accel/32768.0f);
SET_OR_TEST_GETTER(Brake, false);
SET_OR_TEST_GETTER(Accel, m_prev_accel/32768.0f);
// Nitro still depends on whether we're accelerating
m_controls->setNitro(m_prev_nitro && m_prev_accel);
SET_OR_TEST_GETTER(Nitro, m_prev_nitro && m_prev_accel);
}
break;
case PA_NITRO:
// This basically keeps track whether the button still is being pressed
m_prev_nitro = (value != 0);
SET_OR_TEST(m_prev_nitro, value != 0 );
// Enable nitro only when also accelerating
m_controls->setNitro( ((value!=0) && m_controls->getAccel()) );
SET_OR_TEST_GETTER(Nitro, ((value!=0) && m_controls->getAccel()) );
break;
case PA_RESCUE:
m_controls->setRescue(value!=0);
SET_OR_TEST_GETTER(Rescue, value!=0);
break;
case PA_FIRE:
m_controls->setFire(value!=0);
SET_OR_TEST_GETTER(Fire, value!=0);
break;
case PA_LOOK_BACK:
m_controls->setLookBack(value!=0);
SET_OR_TEST_GETTER(LookBack, value!=0);
break;
case PA_DRIFT:
if(value==0)
m_controls->setSkidControl(KartControl::SC_NONE);
if (value == 0)
SET_OR_TEST_GETTER(SkidControl, KartControl::SC_NONE);
else
{
if(m_steer_val==0)
m_controls->setSkidControl(KartControl::SC_NO_DIRECTION);
if (m_steer_val == 0)
SET_OR_TEST_GETTER(SkidControl, KartControl::SC_NO_DIRECTION);
else
m_controls->setSkidControl(m_steer_val<0
? KartControl::SC_RIGHT
: KartControl::SC_LEFT );
SET_OR_TEST_GETTER(SkidControl, m_steer_val<0
? KartControl::SC_RIGHT
: KartControl::SC_LEFT );
}
break;
case PA_PAUSE_RACE:
@ -185,13 +231,25 @@ void PlayerController::action(PlayerAction action, int value)
default:
break;
}
if (dry_run) return false;
return true;
#undef SET_OR_TEST
#undef SET_OR_TEST_GETTER
} // action
//-----------------------------------------------------------------------------
void PlayerController::actionFromNetwork(PlayerAction p_action, int value,
int value_l, int value_r)
{
m_steer_val_l = value_l;
m_steer_val_r = value_r;
action(p_action, value);
} // actionFromNetwork
//-----------------------------------------------------------------------------
/** Handles steering for a player kart.
*/
void PlayerController::steer(float dt, int steer_val)
void PlayerController::steer(int ticks, int steer_val)
{
// Get the old value, compute the new steering value,
// and set it at the end of this function
@ -206,6 +264,7 @@ void PlayerController::steer(float dt, int steer_val)
// Amount the steering is changed for digital devices.
// If the steering is 'back to straight', a different steering
// change speed is used.
float dt = stk_config->ticks2Time(ticks);
const float STEER_CHANGE = ( (steer_val<=0 && steer<0) ||
(steer_val>=0 && steer>0) )
? dt/m_kart->getKartProperties()->getTurnTimeResetSteer()
@ -239,7 +298,6 @@ void PlayerController::steer(float dt, int steer_val)
if(steer>0.0f) steer=0.0f;
} // if steer<=0.0f
} // no key is pressed
m_controls->setSteer(std::min(1.0f, std::max(-1.0f, steer)) );
} // steer
@ -256,13 +314,9 @@ void PlayerController::skidBonusTriggered()
//-----------------------------------------------------------------------------
/** Updates the player kart, called once each timestep.
*/
void PlayerController::update(float dt)
void PlayerController::update(int ticks)
{
// Don't do steering if it's replay. In position only replay it doesn't
// matter, but if it's physics replay the gradual steering causes
// incorrect results, since the stored values are already adjusted.
if (!history->replayHistory())
steer(dt, m_steer_val);
steer(ticks, m_steer_val);
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
{
@ -279,11 +333,11 @@ void PlayerController::update(float dt)
// Only give penalty time in SET_PHASE.
// Penalty time check makes sure it doesn't get rendered on every
// update.
if (m_penalty_time == 0.0 &&
if (m_penalty_ticks == 0 &&
World::getWorld()->getPhase() == WorldStatus::SET_PHASE)
{
displayPenaltyWarning();
m_penalty_time = stk_config->m_penalty_time;
m_penalty_ticks = stk_config->m_penalty_ticks;
} // if penalty_time = 0
m_controls->setBrake(false);
@ -293,9 +347,9 @@ void PlayerController::update(float dt)
return;
} // if isStartPhase
if (m_penalty_time>0.0)
if (m_penalty_ticks>0)
{
m_penalty_time-=dt;
m_penalty_ticks-=ticks;
return;
}
@ -316,3 +370,18 @@ void PlayerController::handleZipper(bool play_sound)
{
m_kart->showZipperFire();
} // handleZipper
//-----------------------------------------------------------------------------
void PlayerController::saveState(BareNetworkString *buffer) const
{
buffer->addUInt32(m_steer_val).addUInt32(m_steer_val_l)
.addUInt32(m_steer_val_r);
} // copyToBuffer
//-----------------------------------------------------------------------------
void PlayerController::rewindTo(BareNetworkString *buffer)
{
m_steer_val = buffer->getUInt32();
m_steer_val_l = buffer->getUInt32();
m_steer_val_r = buffer->getUInt32();
} // rewindTo

View File

@ -32,9 +32,9 @@ protected:
bool m_prev_brake;
bool m_prev_nitro;
float m_penalty_time;
int m_penalty_ticks;
virtual void steer(float, int);
virtual void steer(int ticks, int steer_val);
// ------------------------------------------------------------------------
/** Called when this kart started too early and got a start penalty. */
virtual void displayPenaltyWarning() {}
@ -43,12 +43,17 @@ protected:
public:
PlayerController(AbstractKart *kart);
virtual ~PlayerController ();
virtual void update (float) OVERRIDE;
virtual void action (PlayerAction action, int value) OVERRIDE;
virtual void update (int ticks) OVERRIDE;
virtual bool action (PlayerAction action, int value,
bool dry_run = false ) OVERRIDE;
virtual void actionFromNetwork(PlayerAction action, int value,
int value_l, int value_r);
virtual void skidBonusTriggered() OVERRIDE;
virtual void reset () OVERRIDE;
virtual void handleZipper(bool play_sound) OVERRIDE;
virtual void resetInputState();
virtual void saveState(BareNetworkString *buffer) const OVERRIDE;
virtual void rewindTo(BareNetworkString *buffer) OVERRIDE;
// ------------------------------------------------------------------------
virtual void collectedItem(const Item &item, int add_info=-1,
float previous_energy=0 ) OVERRIDE

View File

@ -161,7 +161,7 @@ void SkiddingAI::reset()
{
m_time_since_last_shot = 0.0f;
m_start_kart_crash_direction = 0;
m_start_delay = -1.0f;
m_start_delay = -1;
m_time_since_stuck = 0.0f;
m_kart_ahead = NULL;
m_distance_ahead = 0.0f;
@ -218,8 +218,9 @@ unsigned int SkiddingAI::getNextSector(unsigned int index)
* It is called once per frame for each AI and determines the behaviour of
* the AI, e.g. steering, accelerating/braking, firing.
*/
void SkiddingAI::update(float dt)
void SkiddingAI::update(int ticks)
{
float dt = stk_config->ticks2Time(ticks);
// This is used to enable firing an item backwards.
m_controls->setLookBack(false);
m_controls->setNitro(false);
@ -293,14 +294,14 @@ void SkiddingAI::update(float dt)
if(isStuck() && !m_kart->getKartAnimation())
{
new RescueAnimation(m_kart);
AIBaseLapController::update(dt);
AIBaseLapController::update(ticks);
return;
}
if( m_world->isStartPhase() )
{
handleRaceStart();
AIBaseLapController::update(dt);
AIBaseLapController::update(ticks);
return;
}
@ -309,7 +310,7 @@ void SkiddingAI::update(float dt)
m_kart->setSlowdown(MaxSpeed::MS_DECREASE_AI,
m_ai_properties->getSpeedCap(m_distance_to_player),
/*fade_in_time*/0.0f);
/*fade_in_time*/0);
//Detect if we are going to crash with the track and/or kart
checkCrashes(m_kart->getXYZ());
determineTrackDirection();
@ -351,8 +352,8 @@ void SkiddingAI::update(float dt)
if(!commands_set)
{
/*Response handling functions*/
handleAcceleration(dt);
handleSteering(dt); //Item handling relocated there to be direction aware
handleAcceleration(ticks);
handleSteering(dt);
handleRescue(dt);
handleBraking();
// If a bomb is attached, nitro might already be set.
@ -364,7 +365,7 @@ void SkiddingAI::update(float dt)
if(m_controls->getNitro() &&
m_kart->getPowerup()->getType()==PowerupManager::POWERUP_ZIPPER &&
m_kart->getSpeed()>1.0f &&
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0 &&
m_kart->getSpeedIncreaseTicksLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0 &&
!m_avoid_item_close)
{
// Make sure that not all AI karts use the zipper at the same
@ -379,7 +380,7 @@ void SkiddingAI::update(float dt)
}
/*And obviously general kart stuff*/
AIBaseLapController::update(dt);
AIBaseLapController::update(ticks);
} // update
//-----------------------------------------------------------------------------
@ -857,7 +858,7 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
// If the item is unavailable keep on testing. It is not necessary
// to test if an item has turned bad, this was tested before this
// function is called.
if(m_item_to_collect->getDisableTime()>0)
if(m_item_to_collect->getDisableTicks()>0)
return false;
const Vec3 &xyz = m_item_to_collect->getXYZ();
@ -1047,7 +1048,7 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
const KartProperties *kp = m_kart->getKartProperties();
// Ignore items that are currently disabled
if(item->getDisableTime()>0) return;
if(item->getDisableTicks()>0) return;
// If the item type is not handled here, ignore it
Item::ItemType type = item->getType();
@ -1841,12 +1842,12 @@ void SkiddingAI::computeNearestKarts()
/** Determines if the AI should accelerate or not.
* \param dt Time step size.
*/
void SkiddingAI::handleAcceleration( const float dt)
void SkiddingAI::handleAcceleration(int ticks)
{
//Do not accelerate until we have delayed the start enough
if( m_start_delay > 0.0f )
if( m_start_delay > 0 )
{
m_start_delay -= dt;
m_start_delay -= ticks;
m_controls->setAccel(0.0f);
return;
}
@ -1857,7 +1858,7 @@ void SkiddingAI::handleAcceleration( const float dt)
return;
}
if(m_kart->getBlockedByPlungerTime()>0)
if(m_kart->getBlockedByPlungerTicks()>0)
{
if(m_kart->getSpeed() < m_kart->getCurrentMaxSpeed() / 2)
m_controls->setAccel(0.05f);
@ -1873,14 +1874,15 @@ void SkiddingAI::handleAcceleration( const float dt)
//-----------------------------------------------------------------------------
void SkiddingAI::handleRaceStart()
{
if( m_start_delay < 0.0f )
if( m_start_delay < 0 )
{
// Each kart starts at a different, random time, and the time is
// smaller depending on the difficulty.
m_start_delay = m_ai_properties->m_min_start_delay
m_start_delay = stk_config->time2Ticks(
m_ai_properties->m_min_start_delay
+ (float) rand() / RAND_MAX
* (m_ai_properties->m_max_start_delay -
m_ai_properties->m_min_start_delay);
m_ai_properties->m_min_start_delay) );
float false_start_probability =
m_superpower == RaceManager::SUPERPOWER_NOLOK_BOSS
@ -1889,7 +1891,7 @@ void SkiddingAI::handleRaceStart()
// Now check for a false start. If so, add 1 second penalty time.
if(rand() < RAND_MAX * false_start_probability)
{
m_start_delay+=stk_config->m_penalty_time;
m_start_delay+=stk_config->m_penalty_ticks;
return;
}
}
@ -1970,7 +1972,8 @@ void SkiddingAI::handleNitroAndZipper()
}
//Nitro continue to be advantageous during the fadeout
float nitro_time = ( m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_NITRO)
int nitro_ticks = m_kart->getSpeedIncreaseTicksLeft(MaxSpeed::MS_INCREASE_NITRO);
float nitro_time = ( stk_config->ticks2Time(nitro_ticks)
+ m_kart->getKartProperties()->getNitroFadeOutTime() );
float nitro_max_time = m_kart->getKartProperties()->getNitroDuration()
+ m_kart->getKartProperties()->getNitroFadeOutTime();
@ -1982,9 +1985,9 @@ void SkiddingAI::handleNitroAndZipper()
//Nitro skill 2 : Don't use nitro if there is more than 1,2 seconds of effect/fadeout left. Use it when at
// max speed or under 5 of speed (after rescue, etc.). Use it to pass bombs.
// Tries to builds a reserve of 4 energy to use towards the end
//Nitro skill 3 : Same as level 2, but don't use until 0,5 seconds of effect/fadeout left, and don't use close
//Nitro skill 3 : Same as level 2, but don't use until 0.5 seconds of effect/fadeout left, and don't use close
// to bad items, and has a target reserve of 8 energy
//Nitro skill 4 : Same as level 3, but don't use until 0,05 seconds of effect/fadeout left and ignore the plunger
//Nitro skill 4 : Same as level 3, but don't use until 0.05 seconds of effect/fadeout left and ignore the plunger
// and has a target reserve of 12 energy
m_controls->setNitro(false);
@ -2011,7 +2014,7 @@ void SkiddingAI::handleNitroAndZipper()
if(!m_kart->isOnGround() || m_kart->hasFinishedRace()) return;
// Don't use nitro or zipper when the AI has a plunger in the face!
if(m_kart->getBlockedByPlungerTime()>0)
if(m_kart->getBlockedByPlungerTicks()>0)
{
if ((nitro_skill < 4) && (ai_skill < 5))
{
@ -2082,7 +2085,7 @@ void SkiddingAI::handleNitroAndZipper()
{
float finish = m_world->getEstimatedFinishTime(m_kart->getWorldKartId()) - m_world->getTime();
float max_time_effect = nitro_max_time / m_kart->getKartProperties()->getNitroConsumption()
* m_kart->getEnergy()*2; //the minimum burst consumes around 0,5 energy
* m_kart->getEnergy()*2; //the minimum burst consumes around 0.5 energy
// The burster forces the AI to consume its reserve by series of 2 bursts
// Otherwise the bursting differences of the various nitro skill wouldn't matter here
@ -2148,7 +2151,7 @@ void SkiddingAI::handleNitroAndZipper()
// Use zipper
if(ai_skill >= 2 && m_kart->getSpeed()>1.0f &&
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
m_kart->getSpeedIncreaseTicksLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
{
DriveNode::DirectionType dir;
unsigned int last;
@ -2856,7 +2859,7 @@ void SkiddingAI::setSteering(float angle, float dt)
else if(steer_fraction < -1.0f) steer_fraction = -1.0f;
// Restrict steering when a plunger is in the face
if(m_kart->getBlockedByPlungerTime()>0)
if(m_kart->getBlockedByPlungerTicks()>0)
{
if (steer_fraction > 0.5f) steer_fraction = 0.5f;
else if(steer_fraction < -0.5f) steer_fraction = -0.5f;

View File

@ -51,8 +51,6 @@
#include <line3d.h>
class LinearWorld;
class DriveGraph;
class ShowCurve;
class Track;
namespace irr
@ -145,8 +143,8 @@ private:
/** Distance to the kard behind. */
float m_distance_behind;
/** The actual start delay used. */
float m_start_delay;
/** The actual start delay used in ticks. */
int m_start_delay;
/** Time an item has been collected and not used. */
float m_time_since_last_shot;
@ -242,7 +240,7 @@ private:
*specific action (more like, associated with inaction).
*/
void handleRaceStart();
void handleAcceleration(const float dt);
void handleAcceleration(int ticks);
void handleSteering(float dt);
void handleItems(const float dt, const Vec3 *aim_point,
int last_node);
@ -278,7 +276,7 @@ protected:
public:
SkiddingAI(AbstractKart *kart);
~SkiddingAI();
virtual void update (float delta) ;
virtual void update (int ticks);
virtual void reset ();
virtual const irr::core::stringw& getNamePostfix() const;
};

View File

@ -107,7 +107,7 @@ void SoccerAI::reset()
* after goal.
* \param dt Time step size.
*/
void SoccerAI::update(float dt)
void SoccerAI::update(int ticks)
{
#ifdef BALL_AIM_DEBUG
Vec3 red = m_world->getBallAimPosition(SOCCER_TEAM_RED);
@ -125,11 +125,11 @@ void SoccerAI::update(float dt)
resetAfterStop();
m_controls->setBrake(false);
m_controls->setAccel(0.0f);
AIBaseController::update(dt);
AIBaseController::update(ticks);
return;
}
ArenaAI::update(dt);
ArenaAI::update(ticks);
} // update
//-----------------------------------------------------------------------------

View File

@ -100,12 +100,9 @@ private:
public:
SoccerAI(AbstractKart *kart);
// ------------------------------------------------------------------------
~SoccerAI();
// ------------------------------------------------------------------------
virtual void update (float delta) OVERRIDE;
// ------------------------------------------------------------------------
virtual void reset () OVERRIDE;
virtual void update (int ticks) OVERRIDE;
virtual void reset() OVERRIDE;
};

View File

@ -56,8 +56,8 @@ SpareTireAI::SpareTireAI(AbstractKart *kart)
void SpareTireAI::reset()
{
BattleAI::reset();
m_idx = 0;
m_timer = 0.0f;
m_idx = 0;
m_timer = 0;
} // reset
//-----------------------------------------------------------------------------
@ -65,12 +65,12 @@ void SpareTireAI::reset()
* \ref m_timer reaches zero which it will be decreased here.
* \param dt Time step size.
*/
void SpareTireAI::update(float dt)
void SpareTireAI::update(int ticks)
{
BattleAI::update(dt);
m_kart->setSlowdown(MaxSpeed::MS_DECREASE_AI, 0.5f, /*fade_in_time*/0.0f);
m_timer -= dt;
if (m_timer < 0.0f)
BattleAI::update(ticks);
m_kart->setSlowdown(MaxSpeed::MS_DECREASE_AI, 0.5f, /*fade_in_time*/0);
m_timer -= ticks;
if (m_timer < 0)
unspawn();
} // update
@ -108,10 +108,10 @@ void SpareTireAI::findTarget()
* moving around.
* \param time_to_last Time before calling \ref unspawn.
*/
void SpareTireAI::spawn(float time_to_last)
void SpareTireAI::spawn(int ticks_to_last)
{
findDefaultPath();
m_timer = time_to_last;
m_timer = ticks_to_last;
Physics::getInstance()->addKart(m_kart);
m_kart->startEngineSFX();

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