Merge with latest master
This commit is contained in:
commit
fc969982da
@ -27,7 +27,7 @@
|
||||
<label proportion="1" align="center" text_align="right" I18N="In the multitouch settings screen" text="Buttons scale"/>
|
||||
<div proportion="1" align="center" height="fit" layout="horizontal-row" >
|
||||
<spacer width="40" height="10" />
|
||||
<gauge id="scale" proportion="1" min_value="50" max_value="150"/>
|
||||
<gauge id="scale" proportion="1" min_value="80" max_value="160"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div y="2%" width="100%" height="96%" layout="vertical-row">
|
||||
<div x="1%" y="2%" width="98%" height="96%" layout="vertical-row">
|
||||
|
||||
<div width="100%" height="40%" layout="vertical-row">
|
||||
<div width="100%" height="25%" layout="vertical-row" >
|
||||
<label id="name" width="100%" text_align="center"/>
|
||||
</div>
|
||||
<!-- This is filled in programmatically -->
|
||||
<box width="98%" height="75%" align="center" layout="vertical-row" padding="1">
|
||||
<box width="100%" height="75%" align="center" layout="vertical-row" padding="1">
|
||||
<list id="current_replay_info" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
</div>
|
||||
@ -18,8 +18,8 @@
|
||||
</div>
|
||||
|
||||
<div width="64%" height="100%" layout="vertical-row">
|
||||
<div width="95%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="40" layout="horizontal-row" >
|
||||
<div width="95%" align="center" layout="vertical-row" height="50%">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="record-race" I18N="Ghost replay info action" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" id="record-race-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Record the race for ghost replay"/>
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="95%" height="50%" align="center">
|
||||
<div width="95%" height="40%" align="center">
|
||||
<buttonbar id="actions" x="0" y="0" height="100%" width="100%" align="center">
|
||||
<icon-button id="start" width="128" height="128"
|
||||
icon="gui/icons/green_check.png"
|
||||
|
@ -13,50 +13,55 @@
|
||||
<list id="replay_list" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
|
||||
<tabs id="race_mode" height="6%" max_height="110" x="2%" width="98%" align="center">
|
||||
<tabs id="race_mode" height="6%" max_height="110" x="1%" width="98%" align="center">
|
||||
<icon-button id="tab_time_trial" width="128" height="128" icon="gui/icons/mode_tt.png"
|
||||
I18N="In the ghost replay selection screen" text="Time trial"/>
|
||||
<icon-button id="tab_egg_hunt" width="128" height="128" icon="gui/icons/mode_easter.png"
|
||||
I18N="In the ghost replay selection screen" text="Egg hunt"/>
|
||||
</tabs>
|
||||
|
||||
<spacer width="100%" height="1.5%" />
|
||||
<spacer width="100%" height="2%" />
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="best_times_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show the best times"/>
|
||||
</div>
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<div width="40%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="compare_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" id="compare-toggle-text" text_align="left" I18N="In the ghost replay selection screen" text="Compare replay"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="2" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/>
|
||||
</div>
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_multiplayer_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Hide multiplayer replays"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_version_toggle" text_align="left"/>
|
||||
<spacer width="1%" height="fit" />
|
||||
<spacer width="2%" height="fit" />
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current version"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record a ghost replay"/>
|
||||
<div width="98%" align="center" layout="horizontal-row" height="fit">
|
||||
<div width="60%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_multiplayer_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Hide multiplayer replays"/>
|
||||
</div>
|
||||
<div width="40%" height="fit" layout="horizontal-row" >
|
||||
<spacer proportion="1" height="5"/>
|
||||
<button width="fit" id="record-ghost" I18N="In the ghost replay selection screen" text="Record a ghost replay"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<checkbox width="fit" id="private_server" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
I18N="In the server selection screen" text="Show only private server(s)"/>
|
||||
I18N="In the server selection screen" text="Show private server(s)"/>
|
||||
<checkbox width="fit" id="game_started" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
|
@ -67,7 +67,7 @@
|
||||
The actual turn radius is piece-wise linearly interpolated. This
|
||||
allows for tighter turning at lower speeds, and also avoids that
|
||||
the kart becomes too hard to control at high speed (speeds of
|
||||
higher than 23 can only be reached with powerups).
|
||||
higher than 25 can only be reached with powerups).
|
||||
time-full-steer: This is the amount of change in steering depending
|
||||
on current steering. So if the steering is between 0 and 0.5,
|
||||
the time-for-steering-change is 0.15. If the current steering is
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
||||
|
||||
<!-- Minimum and maxium server versions that be be read by this binary.
|
||||
Older versions will be ignored. -->
|
||||
<server-version min="1" max="1"/>
|
||||
<server-version min="2" max="2"/>
|
||||
|
||||
<!-- Maximum number of karts to be used at the same time. This limit
|
||||
can easily be increased, but some tracks might not have valid start
|
||||
@ -114,7 +114,7 @@
|
||||
that the bit is to be set to 0, otherwise the bit will be set.
|
||||
|
||||
This field takes two
|
||||
values: the first value is 'and'ed with bullet's default values
|
||||
values: the first value is 'and'ed with bullet's default values
|
||||
(i.e. it can be used to unset bullet defaults), the second value
|
||||
is 'or'ed (i.e. is used to set a bit). A value of -1 for 'and'
|
||||
means to keep all bits. The valid names are listed in stk_config.cpp
|
||||
@ -125,7 +125,7 @@
|
||||
smooth-angle-limit="0.65"
|
||||
fps="120"
|
||||
default-track-friction="0.5"
|
||||
default-moveable-friction="0.5"
|
||||
default-moveable-friction="0.5"
|
||||
solver-iterations="4"
|
||||
solver-split-impulse="true"
|
||||
solver-split-impulse-threshold="-0.00001"
|
||||
@ -149,14 +149,14 @@
|
||||
<replay max-frames="12000" delta-t="0.200" delta-speed="0.6"
|
||||
delta-steering="0.35" />
|
||||
|
||||
<!-- Determines the minimap related values.
|
||||
<!-- Determines the minimap related values.
|
||||
size: The size of the minimap (scaled afterwards) 480 = full screen height)
|
||||
ai-icon: The size of the icons for the AI karts on the minimap.
|
||||
player-icon: The size of the icons for the player karts. -->
|
||||
|
||||
<minimap size="180.0" ai-icon="16.0" player-icon="20.0"/>
|
||||
|
||||
<urls donate="https://supertuxkart.net/Donate"
|
||||
<urls donate="https://supertuxkart.net/Donate"
|
||||
password-reset="http://addons.supertuxkart.net/password-reset.php" />
|
||||
|
||||
<!-- Skidmark data: maximum number of skid marks, and
|
||||
@ -201,7 +201,7 @@
|
||||
away if there is an explosion. -->
|
||||
<explosion impulse-objects="500.0" />
|
||||
|
||||
<!-- Networking
|
||||
<!-- Networking
|
||||
state-frequency: how many states the server will send per second.
|
||||
steering-reduction: Reduce a remote kart's steering by this factor
|
||||
each frame. This helps reduces oversteering by high latency
|
||||
|
@ -133,6 +133,20 @@ namespace scene
|
||||
}
|
||||
}
|
||||
|
||||
virtual void recursiveUpdateAbsolutePosition()
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// update absolute position
|
||||
updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
|
||||
ISceneNodeList::Iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->recursiveUpdateAbsolutePosition();
|
||||
}
|
||||
}
|
||||
|
||||
//! Renders the node.
|
||||
virtual void render() = 0;
|
||||
|
@ -249,6 +249,10 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
|
||||
LastTimeMs = timeMs;
|
||||
|
||||
IAnimatedMeshSceneNode::OnAnimate(timeMs);
|
||||
|
||||
// For up-to-date current frame bone-child attachment
|
||||
for (u32 n=0;n<JointChildSceneNodes.size();++n)
|
||||
JointChildSceneNodes[n]->recursiveUpdateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,6 +186,9 @@ void CIrrDeviceAndroid::createVideoModeList()
|
||||
|
||||
int width = ANativeWindow_getWidth(Android->window);
|
||||
int height = ANativeWindow_getHeight(Android->window);
|
||||
|
||||
os::Printer::log("Window width:", core::stringc(width).c_str(), ELL_DEBUG);
|
||||
os::Printer::log("Window height:", core::stringc(height).c_str(), ELL_DEBUG);
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
|
@ -762,7 +762,7 @@ namespace UserConfigParams
|
||||
&m_network_group, "Use random port for server connection "
|
||||
"(check stk_config.xml for default value)"));
|
||||
PARAM_PREFIX BoolUserConfigParam m_lobby_chat
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "lobby-chat",
|
||||
PARAM_DEFAULT(BoolUserConfigParam(true, "lobby-chat",
|
||||
&m_network_group, "Enable chatting in networking lobby, if off than "
|
||||
"no chat message will be displayed from any players."));
|
||||
PARAM_PREFIX IntUserConfigParam m_max_players
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/particle_kind_manager.hpp"
|
||||
#include "graphics/sp/sp_texture_manager.hpp"
|
||||
@ -57,9 +58,10 @@ MaterialManager::MaterialManager()
|
||||
MaterialManager::~MaterialManager()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
SP::SPTextureManager::get()->stopThreads();
|
||||
if (CVS->isGLSL())
|
||||
SP::SPTextureManager::get()->stopThreads();
|
||||
#endif
|
||||
|
||||
|
||||
for(unsigned int i=0; i<m_materials.size(); i++)
|
||||
{
|
||||
delete m_materials[i];
|
||||
|
@ -272,7 +272,9 @@ PlayerKartWidget::~PlayerKartWidget()
|
||||
|
||||
if (m_kart_name->getIrrlichtElement() != NULL)
|
||||
m_kart_name->getIrrlichtElement()->remove();
|
||||
getCurrentScreen()->manualRemoveWidget(this);
|
||||
|
||||
if (getCurrentScreen() != NULL)
|
||||
getCurrentScreen()->manualRemoveWidget(this);
|
||||
|
||||
#ifdef DEBUG
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
|
@ -631,3 +631,26 @@ std::string AssetsAndroid::getDataPath()
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Get a path for internal lib directory
|
||||
* \return Path for internal lib directory or empty string when failed
|
||||
*/
|
||||
std::string AssetsAndroid::getLibPath()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
AndroidApplicationInfo application_info =
|
||||
CIrrDeviceAndroid::getApplicationInfo(global_android_app->activity);
|
||||
|
||||
std::string lib_path = application_info.native_lib_dir;
|
||||
|
||||
if (access(lib_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
lib_path = "";
|
||||
}
|
||||
|
||||
return lib_path;
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
void init();
|
||||
static std::string getDataPath();
|
||||
static std::string getLibPath();
|
||||
};
|
||||
|
||||
|
||||
|
@ -110,7 +110,8 @@ Attachment::~Attachment()
|
||||
*/
|
||||
void Attachment::set(AttachmentType type, int ticks,
|
||||
AbstractKart *current_kart,
|
||||
bool disable_swatter_animation)
|
||||
bool disable_swatter_animation,
|
||||
bool set_by_rewind_parachute)
|
||||
{
|
||||
// Don't override currently player swatter removing bomb animation
|
||||
Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||
@ -179,7 +180,8 @@ void Attachment::set(AttachmentType type, int ticks,
|
||||
// A parachute can be attached as result of the usage of an item. In this
|
||||
// case we have to save the current kart speed so that it can be detached
|
||||
// by slowing down.
|
||||
if(m_type==ATTACH_PARACHUTE)
|
||||
// if set by rewind the parachute ticks is already correct
|
||||
if (m_type == ATTACH_PARACHUTE && !set_by_rewind_parachute)
|
||||
{
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
float speed_mult;
|
||||
@ -306,19 +308,16 @@ void Attachment::rewindTo(BareNetworkString *buffer)
|
||||
|
||||
// Attaching an object can be expensive (loading new models, ...)
|
||||
// so avoid doing this if there is no change in attachment type
|
||||
// Don't use set to reset a model on local player if it's already cleared
|
||||
// (or m_initial_speed is redone / model is re-shown again when rewinding)
|
||||
if (m_type == new_type || m_type == ATTACH_NOTHING)
|
||||
if (m_type == new_type)
|
||||
{
|
||||
setTicksLeft(ticks_left);
|
||||
if (m_type != new_type && new_type != ATTACH_SWATTER)
|
||||
m_type = new_type;
|
||||
return;
|
||||
}
|
||||
|
||||
set(new_type, ticks_left, m_previous_owner,
|
||||
new_type == ATTACH_SWATTER && !is_removing_bomb
|
||||
/*disable_swatter_animation*/);
|
||||
/*disable_swatter_animation*/,
|
||||
new_type == ATTACH_PARACHUTE);
|
||||
} // rewindTo
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -353,6 +352,12 @@ void Attachment::hitBanana(ItemState *item_state)
|
||||
return;
|
||||
}
|
||||
|
||||
// Make it consistent with attachment rewind when eating banana with bomb
|
||||
// see if (m_type == ATTACH_BOMB && m_kart->getKartAnimation() != NULL)
|
||||
// in 515
|
||||
if (m_kart->getKartAnimation())
|
||||
return;
|
||||
|
||||
AttachmentType new_attachment = ATTACH_NOTHING;
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
// Use this as a basic random number to make sync with server easier.
|
||||
@ -529,13 +534,19 @@ void Attachment::update(int ticks)
|
||||
m_node->setVisible((division & 0x1) == 0);
|
||||
}
|
||||
|
||||
if(m_plugin)
|
||||
if (m_plugin)
|
||||
{
|
||||
bool discard = m_plugin->updateAndTestFinished(ticks);
|
||||
if(discard)
|
||||
int discard_ticks = m_plugin->updateAndTestFinished(ticks);
|
||||
if (discard_ticks != -1)
|
||||
{
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
// Save it for rewinding
|
||||
m_ticks_left =
|
||||
discard_ticks - World::getWorld()->getTicksSinceStart();
|
||||
if (m_ticks_left <= 0)
|
||||
{
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,8 @@ public:
|
||||
void handleCollisionWithKart(AbstractKart *other);
|
||||
void set (AttachmentType type, int ticks,
|
||||
AbstractKart *previous_kart=NULL,
|
||||
bool disable_swatter_animation = false);
|
||||
bool disable_swatter_animation = false,
|
||||
bool set_by_rewind_parachute = false);
|
||||
void rewindTo(BareNetworkString *buffer);
|
||||
void saveState(BareNetworkString *buffer) const;
|
||||
|
||||
|
@ -53,8 +53,9 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Updates a plugin. This is called once each time frame. If the
|
||||
* function returns true, the attachment is discarded. */
|
||||
virtual bool updateAndTestFinished(int ticks) = 0;
|
||||
* function returns a non-negative number, the attachment is discarded
|
||||
* when world ticks >= that number. */
|
||||
virtual int updateAndTestFinished(int ticks) = 0;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when the animation of the Attachment's node is done. */
|
||||
|
@ -224,6 +224,10 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of flyable. */
|
||||
PowerupManager::PowerupType getType() const {return m_type;}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the owner's kart */
|
||||
AbstractKart *getOwner() const { return m_owner;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the owner's kart */
|
||||
AbstractKart *getOwner() const { return m_owner;}
|
||||
|
@ -37,6 +37,25 @@
|
||||
#include <ISceneManager.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor.
|
||||
* \param type Type of the item.
|
||||
* \param owner If not NULL it is the kart that dropped this item; NULL
|
||||
* indicates an item that's part of the track.
|
||||
* \param id Index of this item in the array of all items.
|
||||
*/
|
||||
ItemState::ItemState(ItemType type, const AbstractKart *owner, int id)
|
||||
{
|
||||
setType(type);
|
||||
m_item_id = id;
|
||||
m_previous_owner = owner;
|
||||
m_used_up_counter = -1;
|
||||
if (owner)
|
||||
setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
else
|
||||
setDeactivatedTicks(0);
|
||||
} // ItemState(ItemType)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the disappear counter depending on type. */
|
||||
void ItemState::setDisappearCounter()
|
||||
@ -52,9 +71,23 @@ void ItemState::setDisappearCounter()
|
||||
} // switch
|
||||
} // setDisappearCounter
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
* \param type Type for this item.
|
||||
*/
|
||||
void ItemState::initItem(ItemType type, const Vec3& xyz)
|
||||
{
|
||||
m_xyz = xyz;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_ticks_till_return = 0;
|
||||
setDisappearCounter();
|
||||
} // initItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Update the state of the item, called once per physics frame.
|
||||
* \param ticks Number of ticks to simulate (typically 1).
|
||||
* \param ticks Number of ticks to simulate. While this value is 1 when
|
||||
* called during the normal game loop, during a rewind this value
|
||||
* can be (much) larger than 1.
|
||||
*/
|
||||
void ItemState::update(int ticks)
|
||||
{
|
||||
@ -107,12 +140,17 @@ void ItemState::collected(const AbstractKart *kart)
|
||||
* \param normal The normal upon which the item is placed (so that it can
|
||||
* be aligned properly with the ground).
|
||||
* \param mesh The mesh to be used for this item.
|
||||
* \param owner 'Owner' of this item, i.e. the kart that drops it. This is
|
||||
* used to deactivate this item for the owner, i.e. avoid that a kart
|
||||
* 'collects' its own bubble gum. NULL means no owner, and the item
|
||||
* can be collected immediatley by any kart.
|
||||
* \param is_predicted True if the creation of the item is predicted by
|
||||
* a client. Only used in networking.
|
||||
*/
|
||||
Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh, bool is_predicted)
|
||||
: ItemState(type)
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
|
||||
const AbstractKart *owner, bool is_predicted)
|
||||
: ItemState(type, owner)
|
||||
{
|
||||
assert(type != ITEM_TRIGGER); // use other constructor for that
|
||||
|
||||
@ -190,7 +228,6 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
{
|
||||
ItemState::initItem(type, xyz);
|
||||
m_previous_owner = NULL;
|
||||
m_rotate = (getType()!=ITEM_BUBBLEGUM) &&
|
||||
(getType()!=ITEM_TRIGGER );
|
||||
// Now determine in which quad this item is, and its distance
|
||||
@ -334,17 +371,6 @@ void Item::reset()
|
||||
}
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets which karts dropped an item. This is used to avoid that a kart is
|
||||
* affected by its own items.
|
||||
* \param parent Kart that dropped the item.
|
||||
*/
|
||||
void Item::setParent(const AbstractKart* parent)
|
||||
{
|
||||
m_previous_owner = parent;
|
||||
ItemState::setDeactivatedTicks(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.
|
||||
|
@ -122,35 +122,25 @@ private:
|
||||
* and then converting this value to a Vec3. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
protected:
|
||||
/** The 'owner' of the item, i.e. the kart that dropped this item.
|
||||
* Is NULL if the item is part of the track. */
|
||||
* Is NULL if the item is part of the track. */
|
||||
const AbstractKart *m_previous_owner;
|
||||
|
||||
protected:
|
||||
|
||||
friend class ItemManager;
|
||||
friend class NetworkItemManager;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setType(ItemType type) { m_type = type; }
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
* \param type Type of the item.
|
||||
* \param id Index of this item in the array of all items.
|
||||
* \param kart_id If !=-1 the kart that dropped this item; -1
|
||||
* indicates an item that's part of the track. */
|
||||
ItemState(ItemType type, int id=-1, AbstractKart *kart=NULL)
|
||||
{
|
||||
setType(type);
|
||||
m_item_id = id;
|
||||
m_previous_owner = kart;
|
||||
} // ItemState(ItemType)
|
||||
|
||||
ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1);
|
||||
void initItem(ItemType type, const Vec3& xyz);
|
||||
void update(int ticks);
|
||||
void setDisappearCounter();
|
||||
virtual void collected(const AbstractKart *kart);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~ItemState() {}
|
||||
void setDisappearCounter();
|
||||
void update(int ticks);
|
||||
virtual void collected(const AbstractKart *kart);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void reset()
|
||||
@ -166,19 +156,6 @@ public:
|
||||
}
|
||||
} // reset
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
* \param type Type for this item.
|
||||
*/
|
||||
void initItem(ItemType type, const Vec3& xyz)
|
||||
{
|
||||
m_xyz = xyz;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_deactive_ticks = 0;
|
||||
m_ticks_till_return = 0;
|
||||
setDisappearCounter();
|
||||
} // initItem
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Switches an item to be of a different type. Used for the switch
|
||||
* powerup.
|
||||
@ -329,20 +306,19 @@ private:
|
||||
public:
|
||||
Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
|
||||
const AbstractKart *owner,
|
||||
bool is_predicted=false);
|
||||
Item(const Vec3& xyz, float distance,
|
||||
TriggerItemListener* trigger);
|
||||
virtual ~Item ();
|
||||
void updateGraphics(float dt);
|
||||
virtual void collected(const AbstractKart *kart) OVERRIDE;
|
||||
void setParent(const AbstractKart* parent);
|
||||
void reset();
|
||||
void switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh);
|
||||
void switchTo(ItemType type, scene::IMesh *mesh,
|
||||
scene::IMesh *lowmesh);
|
||||
void switchBack();
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the Kart is close enough to hit this item, the item is
|
||||
* not deactivated anymore, and it wasn't placed by this kart (this is
|
||||
* e.g. used to avoid that a kart hits a bubble gum it just dropped).
|
||||
@ -352,7 +328,7 @@ public:
|
||||
*/
|
||||
bool hitKart(const Vec3 &xyz, const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if (m_previous_owner == kart && getDeactivatedTicks() > 0)
|
||||
if (getPreviousOwner() == kart && getDeactivatedTicks() > 0)
|
||||
return false;
|
||||
Vec3 lc = quatRotate(m_original_rotation, xyz - getXYZ());
|
||||
// Don't be too strict if the kart is a bit above the item
|
||||
@ -373,7 +349,8 @@ protected:
|
||||
bool hitLine(const core::line3df &line,
|
||||
const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if (m_previous_owner == kart && getDeactivatedTicks() >0) return false;
|
||||
if (getPreviousOwner() == kart && getDeactivatedTicks() > 0)
|
||||
return false;
|
||||
|
||||
Vec3 closest = line.getClosestPoint(getXYZ().toIrrVector());
|
||||
return hitKart(closest, kart);
|
||||
|
@ -31,6 +31,7 @@
|
||||
*/
|
||||
ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
|
||||
{
|
||||
m_ticks_till_return = 0;
|
||||
m_type = (EventType)buffer->getUInt8();
|
||||
m_ticks = buffer->getTime();
|
||||
m_kart_id = buffer->getInt8();
|
||||
@ -41,7 +42,11 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
|
||||
m_xyz = buffer->getVec3();
|
||||
*count -= 12;
|
||||
}
|
||||
|
||||
else if (m_type == IEI_COLLECT)
|
||||
{
|
||||
m_ticks_till_return = buffer->getUInt16();
|
||||
*count -= 2;
|
||||
}
|
||||
} // ItemEventInfo(BareNetworkString, int *count)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -55,7 +60,6 @@ void ItemEventInfo::saveState(BareNetworkString *buffer)
|
||||
.addUInt16(m_index);
|
||||
if(m_type == IEI_NEW)
|
||||
buffer->add(m_xyz);
|
||||
else if (m_type == IEI_COLLECT)
|
||||
buffer->addUInt16(m_ticks_till_return);
|
||||
} // saveState
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "items/item.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@ -51,13 +52,20 @@ private:
|
||||
/** In case of new items the position of the new item. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** Ticks for the item to return, atm used by collecting banana
|
||||
* with bomb to delay the return for banana. */
|
||||
int16_t m_ticks_till_return;
|
||||
|
||||
public:
|
||||
/** Constructor for collecting an existing item.
|
||||
* \param ticks Time of the event.
|
||||
* \param item_id The index of the item that was collected.
|
||||
* \param kart_id the kart that collected the item. */
|
||||
ItemEventInfo(int ticks, int index, int kart_id)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id)
|
||||
* \param kart_id the kart that collected the item.
|
||||
* \param ttr Ticks till return after being collected. */
|
||||
|
||||
ItemEventInfo(int ticks, int index, int kart_id, int16_t ttr)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id),
|
||||
m_ticks_till_return(ttr)
|
||||
{
|
||||
m_type = IEI_COLLECT;
|
||||
} // ItemEventInfo(collected existing item)
|
||||
@ -69,14 +77,15 @@ public:
|
||||
*/
|
||||
ItemEventInfo(int ticks, ItemState::ItemType type, int index,
|
||||
int kart_id, const Vec3 &xyz)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz),
|
||||
m_ticks_till_return(0)
|
||||
{
|
||||
m_type = IEI_NEW;
|
||||
} // ItemEventInfo(new item)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** Constructor for switching items. */
|
||||
ItemEventInfo(int ticks) : m_ticks(ticks)
|
||||
ItemEventInfo(int ticks) : m_ticks(ticks), m_ticks_till_return(0)
|
||||
{
|
||||
m_type = IEI_SWITCH;
|
||||
} // ItemEventInfo(switch)
|
||||
@ -116,6 +125,9 @@ public:
|
||||
return m_xyz;
|
||||
} // getXYZ
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the ticks till return, used only by collection events. */
|
||||
int getTicksTillReturn() const { return m_ticks_till_return; }
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the type of this item. Note at this stage only bubble gums
|
||||
* can be created during a race. */
|
||||
ItemState::ItemType getNewItemType() const
|
||||
|
@ -226,13 +226,15 @@ unsigned int ItemManager::insertItem(Item *item)
|
||||
// previously deleted entry, otherwise at the end.
|
||||
int index = -1;
|
||||
for(index=(int)m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {}
|
||||
|
||||
if(index==-1) index = (int)m_all_items.size();
|
||||
|
||||
if(index<(int)m_all_items.size())
|
||||
m_all_items[index] = item;
|
||||
else
|
||||
if (index == -1)
|
||||
{
|
||||
index = (int)m_all_items.size();
|
||||
m_all_items.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_all_items[index] = item;
|
||||
}
|
||||
item->setItemId(index);
|
||||
|
||||
// Now insert into the appropriate quad list, if there is a quad list
|
||||
@ -286,9 +288,7 @@ Item* ItemManager::dropNewItem(ItemState::ItemType type,
|
||||
}
|
||||
|
||||
Item* item = new Item(type, pos, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
|
||||
if(kart != NULL) item->setParent(kart);
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/kart);
|
||||
insertItem(item);
|
||||
if(m_switch_ticks>=0)
|
||||
{
|
||||
@ -318,7 +318,7 @@ Item* ItemManager::placeItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
ItemState::ItemType mesh_type = type;
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/NULL);
|
||||
|
||||
insertItem(item);
|
||||
if (m_switch_ticks >= 0)
|
||||
@ -354,7 +354,7 @@ Item* ItemManager::placeTrigger(const Vec3& xyz, float distance,
|
||||
* \param item The item that was collected.
|
||||
* \param kart The kart that collected the item.
|
||||
*/
|
||||
void ItemManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
void ItemManager::collectedItem(ItemState *item, AbstractKart *kart)
|
||||
{
|
||||
assert(item);
|
||||
// Spare tire karts don't collect items
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
void updateGraphics (float dt);
|
||||
void checkItemHit (AbstractKart* kart);
|
||||
void reset ();
|
||||
virtual void collectedItem (Item *item, AbstractKart *kart);
|
||||
virtual void collectedItem (ItemState *item, AbstractKart *kart);
|
||||
void switchItems ();
|
||||
bool areItemSwitched() { return (m_switch_ticks > 0); }
|
||||
bool randomItemsForArena(const AlignedArray<btTransform>& pos);
|
||||
|
@ -95,17 +95,18 @@ void NetworkItemManager::initClientConfirmState()
|
||||
* \param item The item that was collected.
|
||||
* \param kart The kart that collected the item.
|
||||
*/
|
||||
void NetworkItemManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
void NetworkItemManager::collectedItem(ItemState *item, AbstractKart *kart)
|
||||
{
|
||||
if(NetworkConfig::get()->isServer())
|
||||
{
|
||||
ItemManager::collectedItem(item, kart);
|
||||
// The server saves the collected item as item event info
|
||||
m_item_events.lock();
|
||||
m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
|
||||
item->getItemId(),
|
||||
kart->getWorldKartId());
|
||||
item->getItemId(),
|
||||
kart->getWorldKartId(),
|
||||
item->getTicksTillReturn());
|
||||
m_item_events.unlock();
|
||||
ItemManager::collectedItem(item, kart);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -142,7 +143,7 @@ Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
|
||||
kart->getXYZ() );
|
||||
m_item_events.unlock();
|
||||
return item;
|
||||
} // newItem
|
||||
} // dropNewItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called by the GameProtocol when a confirmation for an item event is
|
||||
@ -237,9 +238,9 @@ void NetworkItemManager::forwardTime(int ticks)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Restores the state of the items to the current world time. It takes the
|
||||
* last saved
|
||||
|
||||
* using exactly 'count' bytes of the message.
|
||||
* last saved confirmed state, applies any updates from the server, and
|
||||
* then syncs up the confirmed state to the in-race items.
|
||||
* It uses exactly 'count' bytes of the message.
|
||||
* \param buffer the state content.
|
||||
* \param count Number of bytes used for this state.
|
||||
*/
|
||||
@ -267,6 +268,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// From here the replay can happen.
|
||||
|
||||
// 1) Remove predicted items:
|
||||
// --------------------------
|
||||
for (unsigned int i=0; i<m_all_items.size(); i++)
|
||||
{
|
||||
Item *item = m_all_items[i];
|
||||
@ -274,20 +276,22 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
{
|
||||
deleteItem(item);
|
||||
}
|
||||
}
|
||||
} // for i in m_all_items
|
||||
|
||||
// 2) Apply all events to current confirmed state:
|
||||
// -----------------------------------------------
|
||||
World *world = World::getWorld();
|
||||
int current_time = m_confirmed_state_time;
|
||||
bool has_state = count > 0;
|
||||
while(count > 0)
|
||||
{
|
||||
// 1) Decode the event in the message
|
||||
// ----------------------------------
|
||||
// 2.1) Decode the event in the message
|
||||
// ------------------------------------
|
||||
ItemEventInfo iei(buffer, &count);
|
||||
|
||||
// 2) If the event needs to be applied, forward
|
||||
// the time to the time of this event:
|
||||
// --------------------------------------------
|
||||
// 2.2) If the event needs to be applied, forward
|
||||
// the time to the time of this event:
|
||||
// ----------------------------------------------
|
||||
int dt = iei.getTicks() - current_time;
|
||||
// Skip an event that are 'in the past' (i.e. have been sent again by
|
||||
// the server because it has not yet received confirmation from all
|
||||
@ -297,13 +301,35 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// Forward the saved state:
|
||||
if (dt>0) forwardTime(dt);
|
||||
|
||||
// TODO: apply the various events types, atm only collection is supported:
|
||||
// TODO: apply the various events types, atm only collection
|
||||
// and new items are supported.
|
||||
if(iei.isItemCollection())
|
||||
{
|
||||
int index = iei.getIndex();
|
||||
// An item on the track was collected:
|
||||
AbstractKart *kart = World::getWorld()->getKart(iei.getKartId());
|
||||
m_confirmed_state[index]->collected(kart);
|
||||
AbstractKart *kart = world->getKart(iei.getKartId());
|
||||
|
||||
// The world clock was set by the RewindManager to be the time
|
||||
// of the state we are rewinding to. But this confirmed collection
|
||||
// event happened in the past (we are replaying item events since
|
||||
// the last confirmed state in order to get a new confirmed state).
|
||||
// So we need to reset the clock to the time at which this event
|
||||
// happened so that (e.g.) kart can use the right time (for
|
||||
// example, bubble gum torque depends on time, and would be wrong
|
||||
// otherwise resulting in stuttering).
|
||||
int old_time = world->getTicksSinceStart(); // Save time we rewind to
|
||||
world->setTicksForRewind(iei.getTicks()); // Set time of event
|
||||
|
||||
if (m_confirmed_state[index] != NULL)
|
||||
{
|
||||
m_confirmed_state[index]->collected(kart);// Collect item
|
||||
// Reset till ticks return from state (required for eating banana with bomb)
|
||||
int ttr = iei.getTicksTillReturn();
|
||||
m_confirmed_state[index]->setTicksTillReturn(ttr);
|
||||
}
|
||||
|
||||
world->setTicksForRewind(old_time); // Set time to rewind-to
|
||||
|
||||
if (m_confirmed_state[index]->isUsedUp())
|
||||
{
|
||||
delete m_confirmed_state[index];
|
||||
@ -312,9 +338,9 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
}
|
||||
else if(iei.isNewItem())
|
||||
{
|
||||
AbstractKart *kart = World::getWorld()->getKart(iei.getKartId());
|
||||
ItemState *is = new ItemState(iei.getNewItemType(), iei.getIndex(),
|
||||
kart);
|
||||
AbstractKart *kart = world->getKart(iei.getKartId());
|
||||
ItemState *is = new ItemState(iei.getNewItemType(), kart,
|
||||
iei.getIndex() );
|
||||
is->initItem(iei.getNewItemType(), iei.getXYZ());
|
||||
if (m_confirmed_state.size() <= is->getItemId())
|
||||
{
|
||||
@ -325,29 +351,34 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
if (m_confirmed_state[is->getItemId()] == NULL)
|
||||
m_confirmed_state[is->getItemId()] = is;
|
||||
else
|
||||
{
|
||||
*m_confirmed_state[is->getItemId()] = *is;
|
||||
delete is;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_time = iei.getTicks();
|
||||
} // while count >0
|
||||
|
||||
// Inform the server which events have been received.
|
||||
// Inform the server which events have been received (if there has
|
||||
// been any updates - no need to send messages if nothing has changed)
|
||||
|
||||
if (has_state)
|
||||
{
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendItemEventConfirmation(World::getWorld()->getTicksSinceStart());
|
||||
gp->sendItemEventConfirmation(world->getTicksSinceStart());
|
||||
}
|
||||
|
||||
// Forward the confirmed item state to the world time:
|
||||
int dt = World::getWorld()->getTicksSinceStart() - current_time;
|
||||
int dt = world->getTicksSinceStart() - current_time;
|
||||
if(dt>0) forwardTime(dt);
|
||||
|
||||
// Restore the state to the current world time:
|
||||
// ============================================
|
||||
// 3. Restore the state to the current world time:
|
||||
// ===============================================
|
||||
|
||||
for(unsigned int i=0; i<m_confirmed_state.size(); i++)
|
||||
{
|
||||
Item *item = m_all_items[i];
|
||||
Item *item = i < m_all_items.size() ? m_all_items[i] : NULL;
|
||||
const ItemState *is = m_confirmed_state[i];
|
||||
if (is && item)
|
||||
*(ItemState*)item = *is;
|
||||
@ -356,18 +387,33 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
Vec3 xyz = is->getXYZ();
|
||||
Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
|
||||
&xyz);
|
||||
if (i != item_new->getItemId())
|
||||
{
|
||||
// The server has this item at a different index in the list
|
||||
// of all items, which means the client has an incorrect
|
||||
// item at the index given by the server - delete that item
|
||||
Log::info("nim", "about to delete item with not matching index i %d item %d",
|
||||
i, item_new->getItemId());
|
||||
if(m_all_items[i])
|
||||
deleteItem(m_all_items[i]);
|
||||
m_all_items[item_new->getItemId()] = NULL;
|
||||
m_all_items[i] = item_new;
|
||||
item_new->setItemId(i);
|
||||
}
|
||||
item_new->setPredicted(false);
|
||||
item_new->setItemId(i);
|
||||
m_all_items[i] = item_new;
|
||||
item_new->setDeactivatedTicks(is->getDeactivatedTicks());
|
||||
*((ItemState*)m_all_items[i]) = *is;
|
||||
}
|
||||
else if (!is && item)
|
||||
{
|
||||
Log::info("nim", "About to delete item index %d i %d",
|
||||
item->getItemId(), i);
|
||||
|
||||
deleteItem(m_all_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we save the current local
|
||||
m_confirmed_state_time = World::getWorld()->getTicksSinceStart();
|
||||
m_confirmed_state_time = world->getTicksSinceStart();
|
||||
} // restoreState
|
||||
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
virtual void reset() OVERRIDE;
|
||||
virtual void setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
|
||||
int ticks) OVERRIDE;
|
||||
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
|
||||
const Vec3 *xyz=NULL) OVERRIDE;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
|
@ -256,7 +256,7 @@ BareNetworkString* Plunger::saveState(std::vector<std::string>* ru)
|
||||
BareNetworkString* buffer = Flyable::saveState(ru);
|
||||
buffer->addUInt16(m_keep_alive).addUInt8(m_moved_to_infinity ? 1 : 0);
|
||||
if (m_rubber_band)
|
||||
buffer->addUInt8(m_rubber_band->getRubberBandTo());
|
||||
buffer->addUInt8(m_rubber_band->get8BitState());
|
||||
else
|
||||
buffer->addUInt8(255);
|
||||
return buffer;
|
||||
@ -268,7 +268,20 @@ void Plunger::restoreState(BareNetworkString *buffer, int count)
|
||||
Flyable::restoreState(buffer, count);
|
||||
m_keep_alive = buffer->getUInt16();
|
||||
m_moved_to_infinity = buffer->getUInt8() == 1;
|
||||
int8_t rbt = buffer->getUInt8();
|
||||
if (rbt != -1 && m_rubber_band)
|
||||
m_rubber_band->setRubberBandTo((RubberBand::RubberBandTo)rbt);
|
||||
uint8_t bit_state = buffer->getUInt8();
|
||||
if (bit_state == 255 && m_rubber_band)
|
||||
{
|
||||
delete m_rubber_band;
|
||||
m_rubber_band = NULL;
|
||||
if (!m_reverse_mode)
|
||||
m_reverse_mode = true;
|
||||
}
|
||||
else if (bit_state != 255 && !m_rubber_band)
|
||||
{
|
||||
m_rubber_band = new RubberBand(this, m_owner);
|
||||
if (m_reverse_mode)
|
||||
m_reverse_mode = false;
|
||||
}
|
||||
if (bit_state != 255)
|
||||
m_rubber_band->set8BitState(bit_state);
|
||||
} // restoreState
|
||||
|
@ -563,7 +563,7 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
random_number);
|
||||
// FIXME Disable switch and bubblegum for now in network
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
(new_powerup == PowerupManager::POWERUP_BUBBLEGUM ||
|
||||
(new_powerup == PowerupManager::POWERUP_BUBBLEGUM ||
|
||||
new_powerup == PowerupManager::POWERUP_SWITCH))
|
||||
new_powerup = PowerupManager::POWERUP_BOWLING;
|
||||
|
||||
|
@ -314,3 +314,4 @@ std::shared_ptr<Rewinder>
|
||||
return nullptr;
|
||||
}
|
||||
} // addProjectileFromNetworkState
|
||||
|
||||
|
@ -101,3 +101,4 @@ extern ProjectileManager *projectile_manager;
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
|
||||
: m_plunger(plunger), m_owner(kart)
|
||||
{
|
||||
m_hit_kart = NULL;
|
||||
m_attached_state = RB_TO_PLUNGER;
|
||||
updatePosition();
|
||||
|
||||
@ -276,6 +277,7 @@ void RubberBand::hit(AbstractKart *kart_hit, const Vec3 *track_xyz)
|
||||
// =================
|
||||
m_hit_position = *track_xyz;
|
||||
m_attached_state = RB_TO_TRACK;
|
||||
m_hit_kart = NULL;
|
||||
} // hit
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -289,3 +291,24 @@ void RubberBand::remove()
|
||||
}
|
||||
#endif
|
||||
} // remove
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
uint8_t RubberBand::get8BitState() const
|
||||
{
|
||||
uint8_t state = (uint8_t)(m_attached_state & 3);
|
||||
state |= m_attached_state == RB_TO_KART && m_hit_kart ?
|
||||
(m_hit_kart->getWorldKartId() << 3) : 0;
|
||||
return state;
|
||||
} // get8BitState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RubberBand::set8BitState(uint8_t bit_state)
|
||||
{
|
||||
m_hit_kart = NULL;
|
||||
m_attached_state = (RubberBandTo)(bit_state & 3);
|
||||
if (m_attached_state == RB_TO_KART)
|
||||
{
|
||||
unsigned kart = bit_state >> 3;
|
||||
m_hit_kart = World::getWorld()->getKart(kart);
|
||||
}
|
||||
} // set8BitState
|
||||
|
@ -73,8 +73,8 @@ public:
|
||||
void updateGraphics(float dt);
|
||||
void update(int ticks);
|
||||
void hit(AbstractKart *kart_hit, const Vec3 *track_xyz=NULL);
|
||||
RubberBandTo getRubberBandTo() const { return m_attached_state; }
|
||||
void setRubberBandTo(RubberBandTo rbt) { m_attached_state = rbt; }
|
||||
uint8_t get8BitState() const;
|
||||
void set8BitState(uint8_t bit_state);
|
||||
void remove();
|
||||
}; // RubberBand
|
||||
#endif
|
||||
|
@ -161,20 +161,20 @@ void Swatter::updateGrahpics(float dt)
|
||||
/** Updates an armed swatter: it checks for any karts that are close enough
|
||||
* and not invulnerable, it swats the kart.
|
||||
* \param dt Time step size.
|
||||
* \return True if the attachment should be discarded.
|
||||
* \return World ticks to discard the swatter.
|
||||
*/
|
||||
bool Swatter::updateAndTestFinished(int ticks)
|
||||
int Swatter::updateAndTestFinished(int ticks)
|
||||
{
|
||||
const int ticks_start = World::getWorld()->getTicksSinceStart();
|
||||
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||
{
|
||||
if (ticks_start >= m_removed_bomb_ticks)
|
||||
return true;
|
||||
return false;
|
||||
return m_removed_bomb_ticks;
|
||||
return -1;
|
||||
} // if removing bomb
|
||||
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
if (!m_discard_now)
|
||||
{
|
||||
@ -186,7 +186,7 @@ bool Swatter::updateAndTestFinished(int ticks)
|
||||
// to make sure all clients know the existence of swatter each other
|
||||
if (ticks_start - m_swatter_start_ticks < 60 ||
|
||||
m_swatter_end_ticks - ticks_start < 60)
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
chooseTarget();
|
||||
pointToTarget();
|
||||
@ -258,15 +258,15 @@ bool Swatter::updateAndTestFinished(int ticks)
|
||||
|
||||
if (m_discard_now)
|
||||
{
|
||||
return ticks_start > m_end_swat_ticks;
|
||||
return m_end_swat_ticks;
|
||||
}
|
||||
else if (ticks_start > m_end_swat_ticks)
|
||||
{
|
||||
m_animation_phase = SWATTER_AIMING;
|
||||
m_end_swat_ticks = std::numeric_limits<int>::max();
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
return false;
|
||||
return -1;
|
||||
} // updateAndTestFinished
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
scene::ISceneNode* bomb_scene_node, int ticks);
|
||||
virtual ~Swatter();
|
||||
void updateGrahpics(float dt) OVERRIDE;
|
||||
bool updateAndTestFinished(int ticks) OVERRIDE;
|
||||
int updateAndTestFinished(int ticks) OVERRIDE;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the swatter is currently aiming, i.e. can be used to
|
||||
|
@ -261,6 +261,8 @@ public:
|
||||
/** Returns true if the kart has a plunger attached to its face. */
|
||||
virtual int getBlockedByPlungerTicks() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getGraphicalViewBlockedByPlunger() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime. */
|
||||
virtual void blockViewWithPlunger() = 0;
|
||||
|
@ -143,9 +143,19 @@ void AbstractKartAnimation::addNetworkAnimationChecker(bool reset_powerup)
|
||||
{
|
||||
// Prevent access to deleted kart animation object
|
||||
std::weak_ptr<int> cct = m_check_created_ticks;
|
||||
Vec3 original_position;
|
||||
AbstractKart* k = m_kart;
|
||||
if (k)
|
||||
original_position = k->getXYZ();
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(m_created_ticks,
|
||||
[](){},
|
||||
/*undo_function*/[cct, k, original_position]()
|
||||
{
|
||||
auto cct_sp = cct.lock();
|
||||
if (!cct_sp || !k)
|
||||
return;
|
||||
k->setXYZ(original_position);
|
||||
},
|
||||
/*replay_function*/[p]()
|
||||
{
|
||||
if (p)
|
||||
|
@ -30,6 +30,14 @@
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
enum KartAnimationType : uint8_t
|
||||
{
|
||||
KAT_RESCUE = 0,
|
||||
KAT_EXPLOSION_DIRECT_HIT = 1,
|
||||
KAT_EXPLOSION = 2,
|
||||
KAT_CANNON = 3
|
||||
};
|
||||
|
||||
/** The base class for all kart animation, like rescue, explosion, or cannon.
|
||||
* Kart animations are done by removing the physics body from the physics
|
||||
* world, and instead modifying the rotation and position of the kart
|
||||
@ -94,10 +102,12 @@ public:
|
||||
m_end_transform = t;
|
||||
m_end_ticks = ticks;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void checkNetworkAnimationCreationSucceed(const btTransform& fallback_trans);
|
||||
// ----------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
void checkNetworkAnimationCreationSucceed(const btTransform& fb_trans);
|
||||
// ------------------------------------------------------------------------
|
||||
int getEndTicks() const { return m_end_ticks; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const = 0;
|
||||
}; // AbstractKartAnimation
|
||||
|
||||
#endif
|
||||
|
@ -81,6 +81,8 @@ public:
|
||||
virtual ~CannonAnimation();
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool usePredefinedEndTransform() const { return false; }
|
||||
virtual bool usePredefinedEndTransform() const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const { return KAT_CANNON; }
|
||||
}; // CannonAnimation
|
||||
#endif
|
||||
|
@ -101,6 +101,8 @@ void NetworkAIController::convertAIToPlayerActions()
|
||||
0 : 32768);
|
||||
all_actions.emplace_back(PA_RESCUE,
|
||||
m_ai_controls->getRescue() ? 32768 : 0);
|
||||
all_actions.emplace_back(PA_LOOK_BACK,
|
||||
m_ai_controls->getLookBack() ? 32768 : 0);
|
||||
|
||||
for (const auto& a : all_actions)
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart)
|
||||
// ----------------------------------------------------------------------------
|
||||
ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
const Vec3 &explosion_position,
|
||||
bool direct_hit)
|
||||
bool direct_hit, bool from_state)
|
||||
: AbstractKartAnimation(kart, "ExplosionAnimation")
|
||||
{
|
||||
m_direct_hit = direct_hit;
|
||||
@ -148,7 +148,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
|
||||
m_kart->getAttachment()->clear();
|
||||
// Clear powerups when direct hit in CTF
|
||||
addNetworkAnimationChecker(m_reset_ticks != -1);
|
||||
if (!from_state)
|
||||
addNetworkAnimationChecker(m_reset_ticks != -1);
|
||||
} // ExplosionAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -74,9 +74,9 @@ protected:
|
||||
Vec3 m_reset_xyz, m_reset_normal;
|
||||
|
||||
ExplosionAnimation(AbstractKart *kart);
|
||||
ExplosionAnimation(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit);
|
||||
public:
|
||||
ExplosionAnimation(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit, bool from_state = false);
|
||||
static ExplosionAnimation *create(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit);
|
||||
static ExplosionAnimation *create(AbstractKart *kart);
|
||||
@ -85,5 +85,8 @@ public:
|
||||
virtual void update(int ticks);
|
||||
bool hasResetAlready() const
|
||||
{ return m_reset_ticks != -1 && m_timer < m_reset_ticks; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const
|
||||
{ return m_direct_hit ? KAT_EXPLOSION_DIRECT_HIT : KAT_EXPLOSION; }
|
||||
}; // ExplosionAnimation
|
||||
#endif
|
||||
|
@ -185,7 +185,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_terrain_sound = NULL;
|
||||
m_last_sound_material = NULL;
|
||||
m_previous_terrain_sound = NULL;
|
||||
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
} // Kart
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -370,6 +370,7 @@ void Kart::reset()
|
||||
m_current_lean = 0.0f;
|
||||
m_falling_time = 0.0f;
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
m_has_caught_nolok_bubblegum = false;
|
||||
m_is_jumping = false;
|
||||
m_flying = false;
|
||||
@ -590,8 +591,15 @@ void Kart::blockViewWithPlunger()
|
||||
{
|
||||
// Avoid that a plunger extends the plunger time
|
||||
if(m_view_blocked_by_plunger<=0 && !isShielded())
|
||||
{
|
||||
m_view_blocked_by_plunger =
|
||||
stk_config->time2Ticks(m_kart_properties->getPlungerInFaceTime());
|
||||
if (m_graphical_view_blocked_by_plunger == 0.0f)
|
||||
{
|
||||
m_graphical_view_blocked_by_plunger =
|
||||
m_kart_properties->getPlungerInFaceTime();
|
||||
}
|
||||
}
|
||||
if(isShielded())
|
||||
{
|
||||
decreaseShieldTime();
|
||||
@ -875,22 +883,27 @@ float Kart::getSpeedForTurnRadius(float radius) const
|
||||
InterpolationArray turn_angle_at_speed = m_kart_properties->getTurnRadius();
|
||||
// Convert the turn radius into turn angle
|
||||
for(int i = 0; i < (int)turn_angle_at_speed.size(); i++)
|
||||
turn_angle_at_speed.setY(i, sin(m_kart_properties->getWheelBase() /
|
||||
turn_angle_at_speed.getY(i)));
|
||||
turn_angle_at_speed.setY(i, sin( 1.0 / turn_angle_at_speed.getY(i)));
|
||||
|
||||
float angle = sin(m_kart_properties->getWheelBase() / radius);
|
||||
float angle = sin(1.0 / radius);
|
||||
return turn_angle_at_speed.getReverse(angle);
|
||||
} // getSpeedForTurnRadius
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the maximum steering angle (depending on speed). */
|
||||
/** Returns the maximum steering angle (depending on speed).
|
||||
This is proportional to kart length because physics reverse this effect,
|
||||
the results of this function should not be used to determine the
|
||||
real raw steer angle. */
|
||||
float Kart::getMaxSteerAngle(float speed) const
|
||||
{
|
||||
InterpolationArray turn_angle_at_speed = m_kart_properties->getTurnRadius();
|
||||
// Convert the turn radius into turn angle
|
||||
// We multiply by wheel base to keep turn radius identical
|
||||
// across karts of different lengths sharing the same
|
||||
// turn radius properties
|
||||
for(int i = 0; i < (int)turn_angle_at_speed.size(); i++)
|
||||
turn_angle_at_speed.setY(i, sin(m_kart_properties->getWheelBase() /
|
||||
turn_angle_at_speed.getY(i)));
|
||||
turn_angle_at_speed.setY(i, sin( 1.0 / turn_angle_at_speed.getY(i))
|
||||
* m_kart_properties->getWheelBase());
|
||||
|
||||
return turn_angle_at_speed.get(speed);
|
||||
} // getMaxSteerAngle
|
||||
@ -946,10 +959,16 @@ void Kart::finishedRace(float time, bool from_server)
|
||||
World::getWorld()->getTicksSinceStart(),
|
||||
/*undo_function*/[old_controller, this]()
|
||||
{
|
||||
if (m_network_finish_check_ticks == -1)
|
||||
return;
|
||||
|
||||
m_controller = old_controller;
|
||||
},
|
||||
/*replay_function*/[ec, old_controller, this]()
|
||||
{
|
||||
if (m_network_finish_check_ticks == -1)
|
||||
return;
|
||||
|
||||
m_saved_controller = old_controller;
|
||||
ec->reset();
|
||||
m_controller = ec;
|
||||
@ -1059,9 +1078,8 @@ void Kart::setRaceResult()
|
||||
}
|
||||
else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_FREE_FOR_ALL)
|
||||
{
|
||||
// the top kart wins
|
||||
FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
|
||||
m_race_result = ffa->getKartAtPosition(1) == this;
|
||||
m_race_result = ffa->getKartFFAResult(getWorldKartId());
|
||||
}
|
||||
else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG)
|
||||
{
|
||||
@ -1314,13 +1332,13 @@ void Kart::eliminate()
|
||||
*/
|
||||
void Kart::update(int ticks)
|
||||
{
|
||||
if (m_network_finish_check_ticks != 0 &&
|
||||
if (m_network_finish_check_ticks > 0 &&
|
||||
World::getWorld()->getTicksSinceStart() >
|
||||
m_network_finish_check_ticks &&
|
||||
!m_finished_race && m_saved_controller != NULL)
|
||||
{
|
||||
Log::warn("Kart", "Missing finish race from server.");
|
||||
m_network_finish_check_ticks = 0;
|
||||
m_network_finish_check_ticks = -1;
|
||||
delete m_controller;
|
||||
m_controller = m_saved_controller;
|
||||
m_saved_controller = NULL;
|
||||
@ -1423,7 +1441,10 @@ void Kart::update(int ticks)
|
||||
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= ticks;
|
||||
//unblock the view if kart just became shielded
|
||||
if(isShielded())
|
||||
{
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
}
|
||||
// Decrease remaining invulnerability time
|
||||
if(m_invulnerable_ticks>0)
|
||||
{
|
||||
@ -1532,7 +1553,7 @@ void Kart::update(int ticks)
|
||||
"v(16-18) %f %f %f steerf(20) %f maxangle(22) %f speed(24) %f "
|
||||
"steering(26-27) %f %f clock(29) %lf skidstate(31) %d factor(33) %f "
|
||||
"maxspeed(35) %f engf(37) %f braketick(39) %d brakes(41) %d heading(43) %f "
|
||||
"noderot(45) %f suslen %f",
|
||||
"bubticks(45) %d bubtor(47) %f",
|
||||
getIdent().c_str(),
|
||||
World::getWorld()->getTime(), World::getWorld()->getTicksSinceStart(),
|
||||
getXYZ().getX(), getXYZ().getY(), getXYZ().getZ(),
|
||||
@ -1553,8 +1574,8 @@ void Kart::update(int ticks)
|
||||
m_brake_ticks, //39
|
||||
m_controls.getButtonsCompressed(), //41
|
||||
getHeading(), //43
|
||||
m_node->getAbsoluteTransformation().getRotationDegrees().Y, //45
|
||||
m_vehicle->getWheelInfo(0).m_raycastInfo.m_suspensionLength
|
||||
m_bubblegum_ticks, // 45
|
||||
m_bubblegum_torque // 47
|
||||
);
|
||||
#endif
|
||||
// After the physics step was done, the position of the wheels (as stored
|
||||
@ -1663,6 +1684,7 @@ void Kart::update(int ticks)
|
||||
if (emergency)
|
||||
{
|
||||
m_view_blocked_by_plunger = 0;
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
if (m_flying)
|
||||
{
|
||||
stopFlying();
|
||||
@ -3039,6 +3061,10 @@ void Kart::updateGraphics(float dt)
|
||||
unsetSquash();
|
||||
}
|
||||
} // if squashed
|
||||
if (m_graphical_view_blocked_by_plunger > 0.0f)
|
||||
m_graphical_view_blocked_by_plunger -= dt;
|
||||
if (m_graphical_view_blocked_by_plunger < 0.0f)
|
||||
m_graphical_view_blocked_by_plunger = 0.0f;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < EMITTER_COUNT; i++)
|
||||
|
@ -223,6 +223,9 @@ protected:
|
||||
/** When a kart has its view blocked by the plunger, this variable will be
|
||||
* > 0 the number it contains is the time left before removing plunger. */
|
||||
int16_t m_view_blocked_by_plunger;
|
||||
|
||||
float m_graphical_view_blocked_by_plunger;
|
||||
|
||||
/** The current speed (i.e. length of velocity vector) of this kart. */
|
||||
float m_speed;
|
||||
|
||||
@ -394,6 +397,9 @@ public:
|
||||
virtual int getBlockedByPlungerTicks() const OVERRIDE
|
||||
{ return m_view_blocked_by_plunger; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getGraphicalViewBlockedByPlunger() const OVERRIDE
|
||||
{ return m_graphical_view_blocked_by_plunger; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime. */
|
||||
virtual void blockViewWithPlunger() OVERRIDE;
|
||||
|
@ -303,17 +303,12 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
m_gravity_center_shift.setZ(0);
|
||||
}
|
||||
|
||||
// In older STK versions the physical wheels where moved 'wheel_radius'
|
||||
// into the physical body (i.e. 'hypothetical' wheel shape would not
|
||||
// poke out of the physical shape). In order to make the karts a bit more
|
||||
// stable, the physical wheel position (i.e. location of raycast) were
|
||||
// moved to be on the corner of the shape. In order to retain the same
|
||||
// steering behaviour, the wheel base (which in turn determines the
|
||||
// turn angle at certain speeds) is shortened by 2*wheel_radius
|
||||
// Wheel radius was always 0.25, and is now not used anymore, but in order
|
||||
// to keep existing steering behaviour, the same formula is still
|
||||
// used.
|
||||
m_wheel_base = fabsf(m_kart_model->getLength() - 2*0.25f);
|
||||
// The longer the kart,the bigger its turn radius if using an identical
|
||||
// wheel base, exactly proportionally to its length.
|
||||
// The wheel base is used to compensate this
|
||||
// We divide by 1.425 to have a default turn radius which conforms
|
||||
// closely (+-0,1%) with the specifications in kart_characteristics.xml
|
||||
m_wheel_base = fabsf(m_kart_model->getLength()/1.425f);
|
||||
|
||||
m_shadow_material = material_manager->getMaterialSPM(m_shadow_file, "",
|
||||
"alphablend");
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/abstract_kart_animation.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/rescue_animation.hpp"
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/max_speed.hpp"
|
||||
@ -52,6 +53,7 @@ KartRewinder::KartRewinder(const std::string& ident,
|
||||
*/
|
||||
void KartRewinder::reset()
|
||||
{
|
||||
m_last_animation_end_ticks = -1;
|
||||
m_transfrom_from_network =
|
||||
btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
Kart::reset();
|
||||
@ -138,7 +140,9 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
buffer->add(trans.getOrigin());
|
||||
btQuaternion quat = trans.getRotation();
|
||||
buffer->add(quat);
|
||||
buffer->addUInt32(ka->getEndTicks());
|
||||
unsigned et = ka->getEndTicks() & 134217727;
|
||||
et |= ka->getAnimationType() << 27;
|
||||
buffer->addUInt32(et);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -207,10 +211,38 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
|
||||
if (has_animation)
|
||||
{
|
||||
int end_ticks = buffer->getUInt32();
|
||||
AbstractKartAnimation* ka = getKartAnimation();
|
||||
if (ka)
|
||||
ka->setEndTransformTicks(m_transfrom_from_network, end_ticks);
|
||||
unsigned et = buffer->getUInt32();
|
||||
int end_ticks = et & 134217727;
|
||||
KartAnimationType kat = (KartAnimationType)(et >> 27);
|
||||
if (!getKartAnimation() && end_ticks != m_last_animation_end_ticks)
|
||||
{
|
||||
Log::info("KartRewinder", "Creating animation %d from state", kat);
|
||||
switch (kat)
|
||||
{
|
||||
case KAT_RESCUE:
|
||||
new RescueAnimation(this, false/*is_auto_rescue*/,
|
||||
true/*from_state*/);
|
||||
break;
|
||||
case KAT_EXPLOSION_DIRECT_HIT:
|
||||
new ExplosionAnimation(this, getSmoothedXYZ(),
|
||||
true/*direct_hit*/, true/*from_state*/);
|
||||
break;
|
||||
case KAT_EXPLOSION:
|
||||
new ExplosionAnimation(this, getSmoothedXYZ(),
|
||||
false/*direct_hit*/, true/*from_state*/);
|
||||
break;
|
||||
default:
|
||||
Log::warn("KartRewinder", "Unknown animation %d from state",
|
||||
kat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (getKartAnimation())
|
||||
{
|
||||
getKartAnimation()->setEndTransformTicks(m_transfrom_from_network,
|
||||
end_ticks);
|
||||
}
|
||||
m_last_animation_end_ticks = end_ticks;
|
||||
}
|
||||
|
||||
Vec3 lv = buffer->getVec3();
|
||||
|
@ -33,6 +33,7 @@ private:
|
||||
btTransform m_transfrom_from_network;
|
||||
float m_prev_steering, m_steering_smoothing_dt, m_steering_smoothing_time;
|
||||
|
||||
int m_last_animation_end_ticks;
|
||||
public:
|
||||
KartRewinder(const std::string& ident, unsigned int world_kart_id,
|
||||
int position, const btTransform& init_transform,
|
||||
|
@ -40,7 +40,8 @@
|
||||
* and initialised the timer.
|
||||
* \param kart Pointer to the kart which is animated.
|
||||
*/
|
||||
RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
|
||||
RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue,
|
||||
bool from_state)
|
||||
: AbstractKartAnimation(kart, "RescueAnimation")
|
||||
{
|
||||
btTransform prev_trans = kart->getTrans();
|
||||
@ -89,8 +90,11 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
|
||||
}
|
||||
|
||||
// Clear powerups when rescue in CTF
|
||||
addNetworkAnimationChecker(race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG);
|
||||
if (!from_state)
|
||||
{
|
||||
addNetworkAnimationChecker(race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG);
|
||||
}
|
||||
} // RescueAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -49,9 +49,13 @@ protected:
|
||||
Referee *m_referee;
|
||||
|
||||
public:
|
||||
RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false);
|
||||
RescueAnimation(AbstractKart *kart,
|
||||
bool is_auto_rescue = false,
|
||||
bool from_state = false);
|
||||
float maximumHeight();
|
||||
virtual ~RescueAnimation();
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual KartAnimationType getAnimationType() const { return KAT_RESCUE; }
|
||||
}; // RescueAnimation
|
||||
#endif
|
||||
|
@ -421,6 +421,7 @@ void Skidding::update(int ticks, bool is_on_ground,
|
||||
m_predicted_curve->setHeading(m_kart->getHeading());
|
||||
float angle = m_kart->getMaxSteerAngle(SPEED)
|
||||
* fabsf(getSteeringFraction());
|
||||
//FIXME : what is this for ?
|
||||
float r = kp->getWheelBase()
|
||||
/ asin(angle)*1.0f;
|
||||
|
||||
|
10
src/main.cpp
10
src/main.cpp
@ -1936,8 +1936,11 @@ int main(int argc, char *argv[] )
|
||||
}
|
||||
else if (CommandLine::has("--lan-server", &s))
|
||||
{
|
||||
ProfileWorld::disableGraphics();
|
||||
UserConfigParams::m_enable_sound = false;
|
||||
if (no_graphics)
|
||||
{
|
||||
ProfileWorld::disableGraphics();
|
||||
UserConfigParams::m_enable_sound = false;
|
||||
}
|
||||
NetworkConfig::get()->setIsServer(true);
|
||||
ServerConfig::m_server_name = s;
|
||||
ServerConfig::m_wan_server = false;
|
||||
@ -2354,7 +2357,8 @@ static void cleanSuperTuxKart()
|
||||
#ifndef SERVER_ONLY
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
if(!NewsManager::get()->waitForReadyToDeleted(2.0f))
|
||||
if (UserConfigParams::m_internet_status == Online::RequestManager::
|
||||
IPERM_ALLOWED && !NewsManager::get()->waitForReadyToDeleted(2.0f))
|
||||
{
|
||||
Log::info("Thread", "News manager not stopping, exiting anyway.");
|
||||
}
|
||||
|
@ -55,10 +55,10 @@ void override_default_params()
|
||||
{
|
||||
case ACONFIGURATION_SCREENSIZE_SMALL:
|
||||
case ACONFIGURATION_SCREENSIZE_NORMAL:
|
||||
UserConfigParams::m_multitouch_scale = 1.3f;
|
||||
UserConfigParams::m_multitouch_scale = 1.4f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_LARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.2f;
|
||||
UserConfigParams::m_multitouch_scale = 1.3f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_XLARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.1f;
|
||||
|
@ -308,16 +308,22 @@ void MainLoop::run()
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
if (msg.message == WM_QUIT)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
// If parent is killed, abort the child main loop too
|
||||
if (WaitForSingleObject(parent, 0) != WAIT_TIMEOUT)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// POSIX equivalent
|
||||
if (m_parent_pid != 0 && getppid() != (int)m_parent_pid)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
#endif
|
||||
PROFILER_PUSH_CPU_MARKER("Main loop", 0xFF, 0x00, 0xF7);
|
||||
|
||||
@ -328,23 +334,28 @@ void MainLoop::run()
|
||||
|
||||
// Shutdown next frame if shutdown request is sent while loading the
|
||||
// world
|
||||
if (STKHost::existHost() &&
|
||||
(STKHost::get()->requestedShutdown() || m_request_abort))
|
||||
if ((STKHost::existHost() && STKHost::get()->requestedShutdown()) ||
|
||||
m_request_abort)
|
||||
{
|
||||
bool exist_host = STKHost::existHost();
|
||||
core::stringw msg = _("Server connection timed out.");
|
||||
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
if (!m_request_abort)
|
||||
{
|
||||
SFXManager::get()->quickSound("anvil");
|
||||
if (!STKHost::get()->getErrorMessage().empty())
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
msg = STKHost::get()->getErrorMessage();
|
||||
SFXManager::get()->quickSound("anvil");
|
||||
if (!STKHost::get()->getErrorMessage().empty())
|
||||
{
|
||||
msg = STKHost::get()->getErrorMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STKHost::get()->shutdown();
|
||||
// In case the user opened a race pause dialog
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
if (exist_host == true)
|
||||
{
|
||||
STKHost::get()->shutdown();
|
||||
}
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (CVS->isGLSL())
|
||||
@ -357,24 +368,32 @@ void MainLoop::run()
|
||||
irr_driver->getActualScreenSize().Height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// In case the user opened a race pause dialog
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
if (World::getWorld())
|
||||
{
|
||||
race_manager->clearNetworkGrandPrixResult();
|
||||
race_manager->exitRace();
|
||||
}
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
|
||||
if (exist_host == true)
|
||||
{
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
StateManager::get()->resetAndSetStack(
|
||||
NetworkConfig::get()->getResetScreens().data());
|
||||
MessageQueue::add(MessageQueue::MT_ERROR, msg);
|
||||
}
|
||||
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
}
|
||||
|
||||
if (m_request_abort)
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
}
|
||||
|
||||
if (m_request_abort)
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
if (!m_abort)
|
||||
@ -404,84 +423,96 @@ void MainLoop::run()
|
||||
PROFILER_PUSH_CPU_MARKER("Database polling update", 0x00, 0x7F, 0x7F);
|
||||
Online::RequestManager::get()->update(frame_duration);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
m_ticks_adjustment.lock();
|
||||
if (m_ticks_adjustment.getData() != 0)
|
||||
{
|
||||
if (m_ticks_adjustment.getData() > 0)
|
||||
m_ticks_adjustment.lock();
|
||||
if (m_ticks_adjustment.getData() != 0)
|
||||
{
|
||||
num_steps += m_ticks_adjustment.getData();
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
else if (m_ticks_adjustment.getData() < 0)
|
||||
{
|
||||
int new_steps = num_steps + m_ticks_adjustment.getData();
|
||||
if (new_steps < 0)
|
||||
if (m_ticks_adjustment.getData() > 0)
|
||||
{
|
||||
num_steps = 0;
|
||||
m_ticks_adjustment.getData() = new_steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_steps = new_steps;
|
||||
num_steps += m_ticks_adjustment.getData();
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ticks_adjustment.unlock();
|
||||
|
||||
for(int i=0; i<num_steps; i++)
|
||||
{
|
||||
if (World::getWorld() && history->replayHistory())
|
||||
history->updateReplay(World::getWorld()->getTicksSinceStart());
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update",
|
||||
0x7F, 0x00, 0x7F);
|
||||
if (auto pm = ProtocolManager::lock())
|
||||
{
|
||||
pm->update(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
|
||||
if (World::getWorld()) updateRace(1);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// We need to check again because update_race may have requested
|
||||
// the main loop to abort; and it's not a good idea to continue
|
||||
// since the GUI engine is no more to be called then.
|
||||
if (m_abort) break;
|
||||
|
||||
if (m_frame_before_loading_world)
|
||||
{
|
||||
m_frame_before_loading_world = false;
|
||||
break;
|
||||
}
|
||||
if (World::getWorld())
|
||||
{
|
||||
if (World::getWorld()->getPhase() == WorldStatus::SETUP_PHASE)
|
||||
else if (m_ticks_adjustment.getData() < 0)
|
||||
{
|
||||
// Skip the large num steps contributed by loading time
|
||||
World::getWorld()->updateTime(1);
|
||||
int new_steps = num_steps + m_ticks_adjustment.getData();
|
||||
if (new_steps < 0)
|
||||
{
|
||||
num_steps = 0;
|
||||
m_ticks_adjustment.getData() = new_steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_steps = new_steps;
|
||||
m_ticks_adjustment.getData() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ticks_adjustment.unlock();
|
||||
|
||||
for (int i = 0; i < num_steps; i++)
|
||||
{
|
||||
if (World::getWorld() && history->replayHistory())
|
||||
{
|
||||
history->updateReplay(
|
||||
World::getWorld()->getTicksSinceStart());
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Protocol manager update",
|
||||
0x7F, 0x00, 0x7F);
|
||||
if (auto pm = ProtocolManager::lock())
|
||||
{
|
||||
pm->update(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Update race", 0, 255, 255);
|
||||
if (World::getWorld())
|
||||
{
|
||||
updateRace(1);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// We need to check again because update_race may have requested
|
||||
// the main loop to abort; and it's not a good idea to continue
|
||||
// since the GUI engine is no more to be called then.
|
||||
if (m_abort || m_request_abort)
|
||||
break;
|
||||
|
||||
if (m_frame_before_loading_world)
|
||||
{
|
||||
m_frame_before_loading_world = false;
|
||||
break;
|
||||
}
|
||||
World::getWorld()->updateTime(1);
|
||||
}
|
||||
} // for i < num_steps
|
||||
|
||||
if (World::getWorld())
|
||||
{
|
||||
if (World::getWorld()->getPhase()==WorldStatus::SETUP_PHASE)
|
||||
{
|
||||
// Skip the large num steps contributed by loading time
|
||||
World::getWorld()->updateTime(1);
|
||||
break;
|
||||
}
|
||||
World::getWorld()->updateTime(1);
|
||||
}
|
||||
} // for i < num_steps
|
||||
|
||||
// Handle controller the last to avoid slow PC sending actions too late
|
||||
if (!m_abort)
|
||||
{
|
||||
// Handle controller the last to avoid slow PC sending actions too
|
||||
// late
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
// User aborted (e.g. closed window)
|
||||
bool abort = !irr_driver->getDevice()->run();
|
||||
|
||||
if (abort)
|
||||
m_abort = true;
|
||||
{
|
||||
m_request_abort = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto gp = GameProtocol::lock())
|
||||
{
|
||||
gp->sendActions();
|
||||
}
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER(); // MainLoop pop
|
||||
PROFILER_SYNC_FRAME();
|
||||
|
@ -159,7 +159,8 @@ const std::string& EasterEggHunt::getIdent() const
|
||||
/** Called when a kart has collected an egg.
|
||||
* \param kart The kart that collected an egg.
|
||||
*/
|
||||
void EasterEggHunt::collectedItem(const AbstractKart *kart, const Item *item)
|
||||
void EasterEggHunt::collectedItem(const AbstractKart *kart,
|
||||
const ItemState *item )
|
||||
{
|
||||
if(item->getType() != ItemState::ITEM_EASTER_EGG) return;
|
||||
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
virtual void getKartsDisplayInfo(
|
||||
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
|
||||
virtual void collectedItem(const AbstractKart *kart,
|
||||
const Item *item ) OVERRIDE;
|
||||
const ItemState *item ) OVERRIDE;
|
||||
void collectedEasterEggGhost(int world_id);
|
||||
|
||||
const int numberOfEggsFound() { return m_eggs_found; }
|
||||
|
@ -196,3 +196,14 @@ video::SColor FreeForAll::getColor(unsigned int kart_id) const
|
||||
{
|
||||
return GUIEngine::getSkin()->getColor("font::normal");
|
||||
} // getColor
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool FreeForAll::getKartFFAResult(int kart_id) const
|
||||
{
|
||||
// the kart(s) which has the top score wins
|
||||
AbstractKart* k = getKartAtPosition(1);
|
||||
if (!k)
|
||||
return false;
|
||||
int top_score = getKartScore(k->getWorldKartId());
|
||||
return getKartScore(kart_id) == top_score;
|
||||
} // getKartFFAResult
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
void setKartScoreFromServer(NetworkString& ns);
|
||||
// ------------------------------------------------------------------------
|
||||
int getKartScore(int kart_id) const { return m_scores.at(kart_id); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool getKartFFAResult(int kart_id) const;
|
||||
}; // FreeForAll
|
||||
|
||||
|
||||
|
@ -213,11 +213,11 @@ const std::string& SoccerWorld::getIdent() const
|
||||
void SoccerWorld::update(int ticks)
|
||||
{
|
||||
updateBallPosition(ticks);
|
||||
updateSectorForKarts();
|
||||
if (Track::getCurrentTrack()->hasNavMesh() &&
|
||||
!NetworkConfig::get()->isNetworking())
|
||||
if (Track::getCurrentTrack()->hasNavMesh())
|
||||
{
|
||||
updateAIData();
|
||||
updateSectorForKarts();
|
||||
if (!NetworkConfig::get()->isNetworking())
|
||||
updateAIData();
|
||||
}
|
||||
|
||||
WorldWithRank::update(ticks);
|
||||
@ -652,6 +652,9 @@ int SoccerWorld::getAttacker(KartTeam team) const
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned int SoccerWorld::getRescuePositionIndex(AbstractKart *kart)
|
||||
{
|
||||
if (!Track::getCurrentTrack()->hasNavMesh())
|
||||
return m_kart_position_map.at(kart->getWorldKartId());
|
||||
|
||||
int last_valid_node =
|
||||
getTrackSector(kart->getWorldKartId())->getLastValidGraphNode();
|
||||
if (last_valid_node >= 0)
|
||||
@ -663,6 +666,9 @@ unsigned int SoccerWorld::getRescuePositionIndex(AbstractKart *kart)
|
||||
//-----------------------------------------------------------------------------
|
||||
btTransform SoccerWorld::getRescueTransform(unsigned int rescue_pos) const
|
||||
{
|
||||
if (!Track::getCurrentTrack()->hasNavMesh())
|
||||
return WorldWithRank::getRescueTransform(rescue_pos);
|
||||
|
||||
const Vec3 &xyz = Graph::get()->getQuad(rescue_pos)->getCenter();
|
||||
const Vec3 &normal = Graph::get()->getQuad(rescue_pos)->getNormal();
|
||||
btTransform pos;
|
||||
|
@ -587,6 +587,9 @@ void World::onGo()
|
||||
*/
|
||||
void World::terminateRace()
|
||||
{
|
||||
// In case the user opened paused dialog in network
|
||||
GUIEngine::ModalDialog::dismiss();
|
||||
|
||||
m_schedule_pause = false;
|
||||
m_schedule_unpause = false;
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
class AbstractKart;
|
||||
class btRigidBody;
|
||||
class Controller;
|
||||
class Item;
|
||||
class ItemState;
|
||||
class PhysicalObject;
|
||||
|
||||
namespace Scripting
|
||||
@ -263,7 +263,8 @@ public:
|
||||
int *amount );
|
||||
// ------------------------------------------------------------------------
|
||||
/** Receives notification if an item is collected. Used for easter eggs. */
|
||||
virtual void collectedItem(const AbstractKart *kart, const Item *item) {}
|
||||
virtual void collectedItem(const AbstractKart *kart,
|
||||
const ItemState *item ) {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void endRaceEarly() { return; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -154,8 +154,27 @@ void RewindManager::saveState()
|
||||
|
||||
m_overall_state_size = 0;
|
||||
std::vector<std::string> rewinder_using;
|
||||
|
||||
// We must save the item state first (so that it is restored first),
|
||||
// otherwise state updates for a kart could be overwritten by
|
||||
// e.g. simulating the item collection later (which resets bubblegum
|
||||
// counter).
|
||||
BareNetworkString* buffer = NULL;
|
||||
if(auto r = m_all_rewinder["N"].lock())
|
||||
buffer = r->saveState(&rewinder_using);
|
||||
if (buffer)
|
||||
{
|
||||
m_overall_state_size += buffer->size();
|
||||
gp->addState(buffer);
|
||||
}
|
||||
delete buffer; // buffer can be freed
|
||||
|
||||
for (auto& p : m_all_rewinder)
|
||||
{
|
||||
// The Network ItemManager was saved first before this loop,
|
||||
// so skip it here.
|
||||
if(p.first=="N") continue;
|
||||
|
||||
// TODO: check if it's worth passing in a sufficiently large buffer from
|
||||
// GameProtocol - this would save the copy operation.
|
||||
BareNetworkString* buffer = NULL;
|
||||
|
@ -136,7 +136,7 @@ void loadServerConfigXML(const XMLNode* root)
|
||||
return;
|
||||
}
|
||||
|
||||
int config_file_version = -1;
|
||||
/*int config_file_version = -1;
|
||||
if (root->get("version", &config_file_version) < 1 ||
|
||||
config_file_version < stk_config->m_min_server_version ||
|
||||
config_file_version > stk_config->m_max_server_version)
|
||||
@ -146,7 +146,7 @@ void loadServerConfigXML(const XMLNode* root)
|
||||
delete root;
|
||||
writeServerConfigToDisk();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
for (unsigned i = 0; i < g_server_params.size(); i++)
|
||||
g_server_params[i]->findYourDataInAChildOf(root);
|
||||
|
@ -269,7 +269,7 @@ namespace ServerConfig
|
||||
|
||||
// ========================================================================
|
||||
/** Server version, will be advanced if there are protocol changes. */
|
||||
static const uint32_t m_server_version = 1;
|
||||
static const uint32_t m_server_version = 2;
|
||||
// ========================================================================
|
||||
void loadServerConfig(const std::string& path = "");
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -634,8 +634,7 @@ void STKHost::setErrorMessage(const irr::core::stringw &message)
|
||||
{
|
||||
if (!message.empty())
|
||||
{
|
||||
irr::core::stringc s(message.c_str());
|
||||
Log::error("STKHost", "%s", s.c_str());
|
||||
Log::error("STKHost", "%s", StringUtils::wideToUtf8(message).c_str());
|
||||
}
|
||||
m_error_message = message;
|
||||
} // setErrorMessage
|
||||
|
@ -326,7 +326,11 @@ namespace Online
|
||||
setProgress(-1.0f);
|
||||
|
||||
Request::afterOperation();
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
if (m_curl_session)
|
||||
{
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
m_curl_session = NULL;
|
||||
}
|
||||
} // afterOperation
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -63,7 +63,7 @@ namespace Online
|
||||
std::string m_filename;
|
||||
|
||||
/** Pointer to the curl data structure for this request. */
|
||||
CURL *m_curl_session;
|
||||
CURL *m_curl_session = NULL;
|
||||
|
||||
/** curl return code. */
|
||||
CURLcode m_curl_code;
|
||||
@ -93,7 +93,14 @@ namespace Online
|
||||
int priority = 1);
|
||||
HTTPRequest(const char * const filename, bool manage_memory = false,
|
||||
int priority = 1);
|
||||
virtual ~HTTPRequest() {}
|
||||
virtual ~HTTPRequest()
|
||||
{
|
||||
if (m_curl_session)
|
||||
{
|
||||
curl_easy_cleanup(m_curl_session);
|
||||
m_curl_session = NULL;
|
||||
}
|
||||
}
|
||||
virtual bool isAllowedToAdd() const OVERRIDE;
|
||||
void setApiURL(const std::string& url, const std::string &action);
|
||||
void setAddonsURL(const std::string& path);
|
||||
|
@ -213,7 +213,13 @@ namespace Online
|
||||
me->m_current_request->execute();
|
||||
// This test is necessary in case that execute() was aborted
|
||||
// (otherwise the assert in addResult will be triggered).
|
||||
if (!me->getAbort()) me->addResult(me->m_current_request);
|
||||
if (!me->getAbort())
|
||||
me->addResult(me->m_current_request);
|
||||
else if (me->m_current_request->manageMemory())
|
||||
{
|
||||
delete me->m_current_request;
|
||||
me->m_current_request = NULL;
|
||||
}
|
||||
me->m_request_queue.lock();
|
||||
} // while handle all requests
|
||||
|
||||
|
@ -139,10 +139,10 @@ GUIEngine::EventPropagation MultitouchSettingsDialog::processEvent(
|
||||
{
|
||||
case ACONFIGURATION_SCREENSIZE_SMALL:
|
||||
case ACONFIGURATION_SCREENSIZE_NORMAL:
|
||||
UserConfigParams::m_multitouch_scale = 1.3f;
|
||||
UserConfigParams::m_multitouch_scale = 1.4f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_LARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.2f;
|
||||
UserConfigParams::m_multitouch_scale = 1.3f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_XLARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.1f;
|
||||
|
@ -52,9 +52,15 @@ GhostReplaySelection::~GhostReplaySelection()
|
||||
void GhostReplaySelection::tearDown()
|
||||
{
|
||||
m_replay_list_widget->setIcons(NULL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GhostReplaySelection::unloaded()
|
||||
{
|
||||
delete m_icon_bank;
|
||||
m_icon_bank = NULL;
|
||||
}
|
||||
} // unloaded
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Triggers a refresh of the replay file list.
|
||||
@ -117,6 +123,24 @@ void GhostReplaySelection::loadedFromFile()
|
||||
m_mode_tabs = getWidget<GUIEngine::RibbonWidget>("race_mode");
|
||||
m_active_mode = RaceManager::MINOR_MODE_TIME_TRIAL;
|
||||
m_active_mode_is_linear = true;
|
||||
|
||||
m_icon_bank = new irr::gui::STKModifiedSpriteBank( GUIEngine::getGUIEnv());
|
||||
|
||||
for(unsigned int i=0; i<kart_properties_manager->getNumberOfKarts(); i++)
|
||||
{
|
||||
const KartProperties* prop = kart_properties_manager->getKartById(i);
|
||||
m_icon_bank->addTextureAsSprite(prop->getIconMaterial()->getTexture());
|
||||
}
|
||||
|
||||
video::ITexture* kart_not_found = irr_driver->getTexture(
|
||||
file_manager->getAsset(FileManager::GUI_ICON, "main_help.png"));
|
||||
|
||||
m_icon_unknown_kart = m_icon_bank->addTextureAsSprite(kart_not_found);
|
||||
|
||||
video::ITexture* lock = irr_driver->getTexture( file_manager->getAsset(
|
||||
FileManager::GUI_ICON, "gui_lock.png"));
|
||||
|
||||
m_icon_lock = m_icon_bank->addTextureAsSprite(lock);
|
||||
} // loadedFromFile
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -148,24 +172,6 @@ void GhostReplaySelection::init()
|
||||
Screen::init();
|
||||
m_cur_difficulty = race_manager->getDifficulty();
|
||||
|
||||
m_icon_bank = new irr::gui::STKModifiedSpriteBank( GUIEngine::getGUIEnv());
|
||||
|
||||
for(unsigned int i=0; i<kart_properties_manager->getNumberOfKarts(); i++)
|
||||
{
|
||||
const KartProperties* prop = kart_properties_manager->getKartById(i);
|
||||
m_icon_bank->addTextureAsSprite(prop->getIconMaterial()->getTexture());
|
||||
}
|
||||
|
||||
video::ITexture* kart_not_found = irr_driver->getTexture( file_manager->getAsset(FileManager::GUI_ICON,
|
||||
"main_help.png" ));
|
||||
|
||||
m_icon_unknown_kart = m_icon_bank->addTextureAsSprite(kart_not_found);
|
||||
|
||||
video::ITexture* lock = irr_driver->getTexture( file_manager->getAsset(FileManager::GUI_ICON,
|
||||
"gui_lock.png" ));
|
||||
|
||||
m_icon_lock = m_icon_bank->addTextureAsSprite(lock);
|
||||
|
||||
int icon_height = getHeight()/24;
|
||||
// 128 is the height of the image file
|
||||
//FIXME : this isn't guaranteed
|
||||
|
@ -106,6 +106,8 @@ public:
|
||||
virtual void init() OVERRIDE;
|
||||
|
||||
virtual void tearDown() OVERRIDE;
|
||||
|
||||
virtual void unloaded() OVERRIDE;
|
||||
|
||||
virtual bool onEscapePressed() OVERRIDE;
|
||||
|
||||
|
@ -258,9 +258,9 @@ void CreateServerScreen::createServer()
|
||||
return;
|
||||
}
|
||||
|
||||
const bool private_server = !password.empty();
|
||||
ServerConfig::m_private_server_password = password;
|
||||
if (!password.empty())
|
||||
password = std::string(" --server-password=") + password;
|
||||
password = std::string(" --server-password=") + password;
|
||||
|
||||
TransportAddress server_address(0x7f000001,
|
||||
stk_config->m_server_discovery_port);
|
||||
@ -268,7 +268,7 @@ void CreateServerScreen::createServer()
|
||||
auto server = std::make_shared<Server>(0/*server_id*/, name,
|
||||
max_players, /*current_player*/0, (RaceManager::Difficulty)
|
||||
difficulty_widget->getSelection(PLAYER_ID_GAME_MASTER),
|
||||
0, server_address, !password.empty(), false);
|
||||
0, server_address, private_server, false);
|
||||
|
||||
#undef USE_GRAPHICS_SERVER
|
||||
#ifdef USE_GRAPHICS_SERVER
|
||||
|
@ -274,7 +274,6 @@ void OptionsScreenVideo::init()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
if (!found_config_res)
|
||||
{
|
||||
r.width = UserConfigParams::m_width;
|
||||
@ -291,6 +290,7 @@ void OptionsScreenVideo::init()
|
||||
}
|
||||
} // next found resolution
|
||||
|
||||
#ifndef ANDROID
|
||||
// Add default resolutions that were not found by irrlicht
|
||||
if (!found_1024_768)
|
||||
{
|
||||
|
@ -270,12 +270,13 @@ void RaceGUI::renderGlobal(float dt)
|
||||
if(world->getPhase() == World::GOAL_PHASE)
|
||||
drawGlobalGoal();
|
||||
|
||||
if (!m_enabled) return;
|
||||
|
||||
// MiniMap is drawn when the players wait for the start countdown to end
|
||||
drawGlobalMiniMap();
|
||||
|
||||
|
||||
// Timer etc. are not displayed unless the game is actually started.
|
||||
if(!world->isRacePhase()) return;
|
||||
if (!m_enabled) return;
|
||||
|
||||
//drawGlobalTimer checks if it should display in the current phase/mode
|
||||
drawGlobalTimer();
|
||||
@ -539,7 +540,8 @@ void RaceGUI::drawGlobalMiniMap()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
//TODO : exception for some game modes ? Another option "Hidden in race, shown in battle ?"
|
||||
if(UserConfigParams::m_minimap_display == 2 /*map hidden*/)
|
||||
if (UserConfigParams::m_minimap_display == 2 /*map hidden*/ ||
|
||||
UserConfigParams::m_multitouch_scale > 1.3f)
|
||||
return;
|
||||
|
||||
// draw a map when arena has a navigation mesh.
|
||||
|
@ -670,8 +670,8 @@ void RaceGUIBase::drawGlobalReadySetGo()
|
||||
} // drawGlobalReadySetGo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Draw players icons and their times (if defined in the current mode).
|
||||
* Also takes care of icon looking different due to plumber, squashing, ...
|
||||
/** Draw players icons and, depending on the current mode, their time
|
||||
* or their score (battle lives, egg collected, etc.).
|
||||
*/
|
||||
void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
|
||||
{
|
||||
@ -1138,3 +1138,5 @@ void RaceGUIBase::removeReferee()
|
||||
m_referee->removeFromSceneGraph();
|
||||
}
|
||||
} // removeReferee
|
||||
|
||||
|
||||
|
@ -56,13 +56,13 @@ RaceGUIMultitouch::RaceGUIMultitouch(RaceGUIBase* race_gui)
|
||||
|
||||
m_device = input_manager->getDeviceManager()->getMultitouchDevice();
|
||||
|
||||
if (UserConfigParams::m_multitouch_scale > 1.5f)
|
||||
if (UserConfigParams::m_multitouch_scale > 1.6f)
|
||||
{
|
||||
UserConfigParams::m_multitouch_scale = 1.5f;
|
||||
UserConfigParams::m_multitouch_scale = 1.6f;
|
||||
}
|
||||
else if (UserConfigParams::m_multitouch_scale < 0.5f)
|
||||
else if (UserConfigParams::m_multitouch_scale < 0.8f)
|
||||
{
|
||||
UserConfigParams::m_multitouch_scale = 0.5f;
|
||||
UserConfigParams::m_multitouch_scale = 0.8f;
|
||||
}
|
||||
|
||||
init();
|
||||
@ -340,6 +340,7 @@ void RaceGUIMultitouch::draw(const AbstractKart* kart,
|
||||
}
|
||||
else if (button->type == MultitouchButtonType::BUTTON_FIRE &&
|
||||
kart->getPowerup()->getNum() > 1 &&
|
||||
!kart->hasFinishedRace() &&
|
||||
m_gui_action == false)
|
||||
{
|
||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||
|
@ -2492,6 +2492,10 @@ Vec3 Track::flagCommand(const XMLNode *node)
|
||||
}
|
||||
#endif
|
||||
|
||||
m_track_object_manager->castRay
|
||||
(loc, loc + (-10000 * quad_normal), &hit_point, &m, &normal,
|
||||
/*interpolate*/false);
|
||||
|
||||
const std::string &name = node->getName();
|
||||
if (name == "red-flag")
|
||||
{
|
||||
|
@ -167,9 +167,11 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
else if (type == "sfx-emitter")
|
||||
{
|
||||
// FIXME: at this time sound emitters are just disabled in multiplayer
|
||||
// otherwise the sounds would be constantly heard
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
m_presentation = new TrackObjectPresentationSound(xml_node, parent);
|
||||
// otherwise the sounds would be constantly heard, for networking
|
||||
// the index of item needs to be same so we create and disable it
|
||||
// in TrackObjectPresentationSound constructor
|
||||
m_presentation = new TrackObjectPresentationSound(xml_node, parent,
|
||||
race_manager->getNumLocalPlayers() > 1);
|
||||
}
|
||||
else if (type == "action-trigger")
|
||||
{
|
||||
|
@ -652,7 +652,8 @@ void TrackObjectPresentationMesh::reset()
|
||||
// ----------------------------------------------------------------------------
|
||||
TrackObjectPresentationSound::TrackObjectPresentationSound(
|
||||
const XMLNode& xml_node,
|
||||
scene::ISceneNode* parent)
|
||||
scene::ISceneNode* parent,
|
||||
bool disable_for_multiplayer)
|
||||
: TrackObjectPresentation(xml_node)
|
||||
{
|
||||
// TODO: respect 'parent' if any
|
||||
@ -680,6 +681,13 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(
|
||||
float max_dist = 390.0f;
|
||||
xml_node.get("max_dist", &max_dist );
|
||||
|
||||
if (trigger_when_near)
|
||||
{
|
||||
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this);
|
||||
}
|
||||
|
||||
if (disable_for_multiplayer)
|
||||
return;
|
||||
// first try track dir, then global dir
|
||||
std::string soundfile = Track::getCurrentTrack()->getTrackFile(sound);
|
||||
//std::string soundfile = file_manager->getAsset(FileManager::MODEL,sound);
|
||||
@ -708,10 +716,6 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(
|
||||
else
|
||||
Log::error("TrackObject", "Sound emitter object could not be created.");
|
||||
|
||||
if (trigger_when_near)
|
||||
{
|
||||
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this);
|
||||
}
|
||||
} // TrackObjectPresentationSound
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -286,7 +286,8 @@ private:
|
||||
public:
|
||||
|
||||
TrackObjectPresentationSound(const XMLNode& xml_node,
|
||||
scene::ISceneNode* parent);
|
||||
scene::ISceneNode* parent,
|
||||
bool disable_for_multiplayer);
|
||||
virtual ~TrackObjectPresentationSound();
|
||||
virtual void onTriggerItemApproached() OVERRIDE;
|
||||
virtual void update(float dt) OVERRIDE;
|
||||
|
@ -283,9 +283,27 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
|
||||
}
|
||||
|
||||
std::string data_path = AssetsAndroid::getDataPath();
|
||||
std::string main_path = data_path + "/lib/libmain.so";
|
||||
std::string main_path;
|
||||
|
||||
if (data_path.empty() || access(main_path.c_str(), R_OK) != 0)
|
||||
if (!data_path.empty())
|
||||
{
|
||||
main_path = data_path + "/lib/libmain.so";
|
||||
}
|
||||
|
||||
if (main_path.empty() || access(main_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
std::string lib_path = AssetsAndroid::getLibPath();
|
||||
|
||||
if (!lib_path.empty())
|
||||
{
|
||||
main_path = lib_path + "/libmain.so";
|
||||
}
|
||||
|
||||
Log::info("SeparateProcess", "Trying to use fallback lib path: %s",
|
||||
main_path.c_str());
|
||||
}
|
||||
|
||||
if (main_path.empty() || access(main_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
Log::error("SeparateProcess", "Error: Cannot read libmain.so");
|
||||
return false;
|
||||
|
194
tools/android_builder.sh
Executable file
194
tools/android_builder.sh
Executable file
@ -0,0 +1,194 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# (C) 2018 Dawid Gan, under the GPLv3
|
||||
#
|
||||
# A script that builds Android APKs for all architectures
|
||||
#
|
||||
# The script assumes that you know what you are doing. It allows to generate all
|
||||
# packages for Google Play Store with single command. If you just want to build
|
||||
# STK for your own use, then use android/make.sh script instead.
|
||||
|
||||
export BUILD_TYPE=Beta
|
||||
export PROJECT_VERSION=git20181001
|
||||
export PROJECT_CODE=48
|
||||
export STOREPASS="xxx"
|
||||
export KEYSTORE="/path/to/stk.keystore"
|
||||
export ALIAS="alias"
|
||||
|
||||
|
||||
check_error()
|
||||
{
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "Error ocurred."
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
clean()
|
||||
{
|
||||
echo "Clean everything"
|
||||
|
||||
rm -rf ./android-armv7
|
||||
rm -rf ./android-aarch64
|
||||
rm -rf ./android-x86
|
||||
rm -rf ./android-x86_64
|
||||
rm -rf ./android/assets
|
||||
rm -rf ./android-output
|
||||
|
||||
cd android
|
||||
./make.sh clean
|
||||
cd -
|
||||
}
|
||||
|
||||
init_directories()
|
||||
{
|
||||
echo "Init directories"
|
||||
|
||||
if [ ! -d "./android-armv7" ]; then
|
||||
echo "Creating android-armv7 directory"
|
||||
|
||||
mkdir android-armv7
|
||||
cd android-armv7
|
||||
|
||||
ln -s ../android/Android.mk
|
||||
ln -s ../android/AndroidManifest.xml
|
||||
ln -s ../android/banner.png
|
||||
ln -s ../android/build.gradle
|
||||
ln -s ../android/icon.png
|
||||
ln -s ../android/icon-dbg.png
|
||||
ln -s ../android/make.sh
|
||||
ln -s ../android/android-ndk
|
||||
ln -s ../android/android-sdk
|
||||
ln -s ../android/assets
|
||||
|
||||
cd -
|
||||
fi
|
||||
|
||||
if [ ! -d "./android-aarch64" ]; then
|
||||
echo "Creating android-aarch64 directory"
|
||||
cp -a ./android-armv7 ./android-aarch64
|
||||
fi
|
||||
|
||||
if [ ! -d "./android-x86" ]; then
|
||||
echo "Creating android-x86 directory"
|
||||
cp -a ./android-armv7 ./android-x86
|
||||
fi
|
||||
|
||||
if [ ! -d "./android-x86_64" ]; then
|
||||
echo "Creating android-x86_64 directory"
|
||||
cp -a ./android-armv7 ./android-x86_64
|
||||
fi
|
||||
|
||||
if [ ! -d "./android-output" ]; then
|
||||
echo "Creating android-output directory"
|
||||
mkdir ./android-output
|
||||
fi
|
||||
}
|
||||
|
||||
generate_assets()
|
||||
{
|
||||
echo "Generate assets"
|
||||
|
||||
if [ -d "./android/assets" ]; then
|
||||
echo "Assets already found in ./android/assets"
|
||||
return
|
||||
fi
|
||||
|
||||
cd ./android
|
||||
./generate_assets.sh
|
||||
|
||||
if [ ! -f "./assets/directories.txt" ]; then
|
||||
echo "Error: Couldn't generate assets"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -f "./assets/data/supertuxkart.git" ]; then
|
||||
mv "./assets/data/supertuxkart.git" \
|
||||
"./assets/data/supertuxkart.$PROJECT_VERSION"
|
||||
fi
|
||||
|
||||
cd -
|
||||
}
|
||||
|
||||
build_package()
|
||||
{
|
||||
export ARCH1=$1
|
||||
export ARCH2=$2
|
||||
|
||||
echo "Build package for $ARCH1"
|
||||
|
||||
if [ -f "./android-output/SuperTuxKart-$PROJECT_VERSION-$ARCH1.apk" ]; then
|
||||
echo "Package for architecture $ARCH1 is already built"
|
||||
#return
|
||||
fi
|
||||
|
||||
export COMPILE_ARCH=$ARCH1
|
||||
|
||||
cd ./android-$ARCH1
|
||||
./make.sh -j5
|
||||
cd -
|
||||
|
||||
if [ ! -f ./android-$ARCH1/build/outputs/apk/android-$ARCH1-release-unsigned.apk ]; then
|
||||
echo "Error: Couldn't build apk for architecture $ARCH1"
|
||||
return
|
||||
fi
|
||||
|
||||
cp ./android-$ARCH1/build/outputs/apk/android-$ARCH1-release-unsigned.apk \
|
||||
./android-output/SuperTuxKart-$PROJECT_VERSION-$ARCH1-unaligned.apk
|
||||
|
||||
cp ./android-$ARCH1/obj/local/$ARCH2/libmain.so \
|
||||
./android-output/SuperTuxKart-$PROJECT_VERSION-$ARCH1-libmain.so
|
||||
|
||||
cd ./android-output
|
||||
|
||||
jarsigner -sigalg SHA1withRSA -digestalg SHA1 \
|
||||
-keystore "$KEYSTORE" \
|
||||
-storepass "$STOREPASS" \
|
||||
SuperTuxKart-$PROJECT_VERSION-$ARCH1-unaligned.apk \
|
||||
"$ALIAS"
|
||||
|
||||
check_error
|
||||
|
||||
zipalign -f 4 SuperTuxKart-$PROJECT_VERSION-$ARCH1-unaligned.apk \
|
||||
SuperTuxKart-$PROJECT_VERSION-$ARCH1.apk
|
||||
|
||||
check_error
|
||||
|
||||
rm SuperTuxKart-$PROJECT_VERSION-$ARCH1-unaligned.apk
|
||||
|
||||
cd -
|
||||
}
|
||||
|
||||
|
||||
# Handle clean command
|
||||
if [ ! -z "$1" ] && [ "$1" = "clean" ]; then
|
||||
clean
|
||||
exit
|
||||
fi
|
||||
|
||||
#Build packages
|
||||
init_directories
|
||||
|
||||
generate_assets
|
||||
|
||||
if [ -z "$1" ] || [ "$1" = "armv7" ]; then
|
||||
build_package armv7 armeabi-v7a
|
||||
fi
|
||||
|
||||
PROJECT_CODE=$(($PROJECT_CODE + 1))
|
||||
|
||||
if [ -z "$1" ] || [ "$1" = "aarch64" ]; then
|
||||
build_package aarch64 arm64-v8a
|
||||
fi
|
||||
|
||||
PROJECT_CODE=$(($PROJECT_CODE + 1))
|
||||
|
||||
if [ -z "$1" ] || [ "$1" = "x86" ]; then
|
||||
build_package x86 x86
|
||||
fi
|
||||
|
||||
PROJECT_CODE=$(($PROJECT_CODE + 1))
|
||||
|
||||
if [ -z "$1" ] || [ "$1" = "x86_64" ]; then
|
||||
build_package x86_64 x86_64
|
||||
fi
|
Loading…
Reference in New Issue
Block a user