Merge branch 'dev' of github.com:supertuxkart/stk-code into dev
This commit is contained in:
commit
f4b02c096a
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4.8 KiB |
@ -15,21 +15,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="2%"/>
|
||||
<div x="2%" width="96%" height="fit" layout="horizontal-row">
|
||||
<box proportion="4" height="fit" layout="vertical-row">
|
||||
<div x="2%" width="96%" height="18%" layout="horizontal-row">
|
||||
<box proportion="4" height="100%" layout="vertical-row">
|
||||
<textbox id="chat" width="100%"/>
|
||||
<spacer height="10"/>
|
||||
<spacer height="20%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row">
|
||||
<button id="send" width="20%" height="fit" I18N="In the network lobby" text="Send" />
|
||||
<spacer width="1%"/>
|
||||
<label id="timeout-message" width="79%" height="fit"/>
|
||||
<button id="send" width="20%" height="fit" I18N="In the network lobby" text="Send"/>
|
||||
<spacer width="3%"/>
|
||||
<label id="timeout-message" width="79%" height="fit" text="" word_wrap="true" align="center"/>
|
||||
</div>
|
||||
</box>
|
||||
<spacer width="3%"/>
|
||||
<icon-button id="start" proportion="1" width="64" height="64" icon="gui/icons/green_check.png" align="top"
|
||||
I18N="In the network lobby" text="Start race"/>
|
||||
<icon-button id="exit" proportion="1" width="64" height="64" icon="gui/icons/main_quit.png" align="top"
|
||||
I18N="In the network lobby" text="Exit"/>
|
||||
<icon-button id="config" proportion="1" width="64" height="64" icon="gui/icons/main_options.png" align="top"
|
||||
I18N="In the network lobby" text="Server Configuration"/>
|
||||
</div>
|
||||
<spacer height="1%"/>
|
||||
</div>
|
||||
|
@ -8,7 +8,7 @@
|
||||
isn't an item, it is internally
|
||||
handled as one, so list it here -->
|
||||
<bubblegum model="bubblegum.spm" lowmodel="bubblegum-low.spm" glow="246 150 209"/>
|
||||
<bubblegum-nolok model="bubblegum-nolok.spm" lowmodel="bubblegum-nolok-low.spm"/>
|
||||
<bubblegum-nolok model="bubblegum-nolok.spm" lowmodel="bubblegum-nolok-low.spm" glow="20 190 0"/>
|
||||
<easter-egg model="easter_egg.spm" glow="0 60 120" />
|
||||
</items>
|
||||
|
||||
|
@ -350,9 +350,9 @@ void FontWithFace::dumpGlyphPage()
|
||||
*/
|
||||
void FontWithFace::setDPI()
|
||||
{
|
||||
const int screen_width = irr_driver->getFrameSize().Width;
|
||||
const int screen_height = irr_driver->getFrameSize().Height;
|
||||
|
||||
const int screen_width = irr_driver->getActualScreenSize().Width;
|
||||
const int screen_height = irr_driver->getActualScreenSize().Height;
|
||||
|
||||
if (UserConfigParams::m_hidpi_enabled)
|
||||
{
|
||||
float scale = screen_height / 480.0f;
|
||||
|
@ -120,7 +120,8 @@ using namespace gui;
|
||||
virtual void setDrawBackground(bool) { }
|
||||
|
||||
void openScreenKeyboard();
|
||||
|
||||
s32 getCursorPosInBox() const { return CursorPos; }
|
||||
s32 getTextCount() const { return (s32)Text.size(); }
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
|
@ -434,8 +434,3 @@ void IconButtonWidget::setVisible(bool visible)
|
||||
m_label->setVisible(visible);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setText(const wchar_t *s)
|
||||
{
|
||||
m_label->setText(s);
|
||||
}
|
||||
|
@ -170,8 +170,6 @@ namespace GUIEngine
|
||||
Widget::elementRemoved();
|
||||
m_label = NULL;
|
||||
}
|
||||
// --------------------------------------------------------------------
|
||||
virtual void setText(const wchar_t *s) OVERRIDE;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -209,3 +209,22 @@ EventPropagation TextBoxWidget::onActivationInput(const int playerID)
|
||||
// event to avoid breaking something
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation TextBoxWidget::rightPressed(const int playerID)
|
||||
{
|
||||
if (((MyCGUIEditBox*)m_element)->getTextCount() ==
|
||||
((MyCGUIEditBox*)m_element)->getCursorPosInBox())
|
||||
return EVENT_BLOCK;
|
||||
|
||||
return EVENT_LET;
|
||||
} // rightPressed
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation TextBoxWidget::leftPressed (const int playerID)
|
||||
{
|
||||
if (((MyCGUIEditBox*)m_element)->getCursorPosInBox() == 0)
|
||||
return EVENT_BLOCK;
|
||||
|
||||
return EVENT_LET;
|
||||
} // leftPressed
|
||||
|
@ -77,6 +77,9 @@ namespace GUIEngine
|
||||
virtual void setActive(bool active=true);
|
||||
|
||||
virtual EventPropagation onActivationInput(const int playerID);
|
||||
virtual EventPropagation rightPressed(const int playerID);
|
||||
virtual EventPropagation leftPressed (const int playerID);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -653,9 +653,7 @@ void Flyable::restoreState(BareNetworkString *buffer, int count)
|
||||
m_body->setInterpolationAngularVelocity(av);
|
||||
setTrans(t);
|
||||
}
|
||||
uint16_t hit_and_ticks = buffer->getUInt16();
|
||||
// Next network version remove ~(1 << 15)
|
||||
m_ticks_since_thrown = hit_and_ticks & ~(1 << 15);
|
||||
m_ticks_since_thrown = buffer->getUInt16();
|
||||
m_has_server_state = true;
|
||||
} // restoreState
|
||||
|
||||
|
@ -74,10 +74,13 @@ void ItemState::setDisappearCounter()
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
* \param type Type for this item.
|
||||
* \param xyz The position for this item.
|
||||
* \param normal The normal for this item.
|
||||
*/
|
||||
void ItemState::initItem(ItemType type, const Vec3& xyz)
|
||||
void ItemState::initItem(ItemType type, const Vec3& xyz, const Vec3& normal)
|
||||
{
|
||||
m_xyz = xyz;
|
||||
m_normal = normal;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_ticks_till_return = 0;
|
||||
setDisappearCounter();
|
||||
@ -133,6 +136,16 @@ void ItemState::collected(const AbstractKart *kart)
|
||||
}
|
||||
} // collected
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the graphical type of this item should be using (takes nolok into
|
||||
* account). */
|
||||
Item::ItemType ItemState::getGrahpicalType() const
|
||||
{
|
||||
return m_previous_owner && m_previous_owner->getIdent() == "nolok" &&
|
||||
getType() == ITEM_BUBBLEGUM ?
|
||||
ITEM_BUBBLEGUM_NOLOK : getType();
|
||||
} // getGrahpicalType
|
||||
|
||||
// ============================================================================
|
||||
/** Constructor for an item.
|
||||
* \param type Type of the item.
|
||||
@ -156,7 +169,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
|
||||
m_was_available_previously = true;
|
||||
m_distance_2 = 1.2f;
|
||||
initItem(type, xyz);
|
||||
initItem(type, xyz, normal);
|
||||
m_graphical_type = type;
|
||||
m_original_rotation = shortestArcQuat(Vec3(0, 1, 0), normal);
|
||||
m_listener = NULL;
|
||||
@ -181,7 +194,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
}
|
||||
m_node = lodnode;
|
||||
setType(type);
|
||||
handleNewMesh(getType());
|
||||
handleNewMesh(getGrahpicalType());
|
||||
|
||||
#ifdef DEBUG
|
||||
std::string debug_name("item: ");
|
||||
@ -206,7 +219,7 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
: ItemState(ITEM_TRIGGER)
|
||||
{
|
||||
m_distance_2 = distance*distance;
|
||||
initItem(ITEM_TRIGGER, xyz);
|
||||
initItem(ITEM_TRIGGER, xyz, /*normal not required*/Vec3(0,0,0));
|
||||
m_graphical_type = ITEM_TRIGGER;
|
||||
m_original_rotation = btQuaternion(0, 0, 0, 1);
|
||||
m_node = NULL;
|
||||
@ -218,10 +231,12 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
/** Initialises the item. Note that m_distance_2 must be defined before calling
|
||||
* this function, since it pre-computes some values based on this.
|
||||
* \param type Type of the item.
|
||||
* \param xyz Position of this item.
|
||||
* \param normal Normal for this item.
|
||||
*/
|
||||
void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
void Item::initItem(ItemType type, const Vec3 &xyz, const Vec3&normal)
|
||||
{
|
||||
ItemState::initItem(type, xyz);
|
||||
ItemState::initItem(type, xyz, normal);
|
||||
// Now determine in which quad this item is, and its distance
|
||||
// from the center within this quad.
|
||||
m_graph_node = Graph::UNKNOWN_SECTOR;
|
||||
@ -345,7 +360,7 @@ void Item::updateGraphics(float dt)
|
||||
|
||||
if (m_graphical_type != getType())
|
||||
{
|
||||
handleNewMesh(getType());
|
||||
handleNewMesh(getGrahpicalType());
|
||||
m_graphical_type = getType();
|
||||
}
|
||||
|
||||
|
@ -119,10 +119,17 @@ private:
|
||||
* will always reappear after a while. */
|
||||
int m_used_up_counter;
|
||||
|
||||
/** The original position - saves calls to m_node->getPosition()
|
||||
* and then converting this value to a Vec3. */
|
||||
/** The position of this ItemState. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** The original rotation of the item. While this is technically a visual
|
||||
* only value (atm, it could be used for collision detection), it is
|
||||
* required to make sure a client can display items with the right normal
|
||||
* (in case that a client would get a different (or no) normal from a
|
||||
* raycast).
|
||||
*/
|
||||
Vec3 m_normal;
|
||||
|
||||
/** The 'owner' of the item, i.e. the kart that dropped this item.
|
||||
* Is NULL if the item is part of the track. */
|
||||
const AbstractKart *m_previous_owner;
|
||||
@ -154,7 +161,7 @@ protected:
|
||||
|
||||
public:
|
||||
ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1);
|
||||
void initItem(ItemType type, const Vec3& xyz);
|
||||
void initItem(ItemType type, const Vec3& xyz, const Vec3& normal);
|
||||
void update(int ticks);
|
||||
void setDisappearCounter();
|
||||
virtual void collected(const AbstractKart *kart);
|
||||
@ -273,6 +280,8 @@ public:
|
||||
/** Returns the type of this item. */
|
||||
ItemType getType() const { return m_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
ItemType getGrahpicalType() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the original type of this item. */
|
||||
ItemType getOriginalType() const { return m_original_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
@ -305,6 +314,12 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the XYZ position of the item. */
|
||||
const Vec3& getXYZ() const { return m_xyz; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the normal of the ItemState. */
|
||||
const Vec3 getNormal() const
|
||||
{
|
||||
return m_normal;
|
||||
}
|
||||
}; // class ItemState
|
||||
|
||||
// ============================================================================
|
||||
@ -350,7 +365,7 @@ private:
|
||||
* would not be collected. Used by the AI to avoid items. */
|
||||
Vec3 *m_avoidance_points[2];
|
||||
|
||||
void initItem(ItemType type, const Vec3 &xyz);
|
||||
void initItem(ItemType type, const Vec3 &xyz, const Vec3 &normal);
|
||||
void setMesh(scene::IMesh* mesh, scene::IMesh* lowres_mesh);
|
||||
void handleNewMesh(ItemType type);
|
||||
|
||||
@ -432,6 +447,12 @@ public:
|
||||
return m_avoidance_points[1];
|
||||
} // getAvoidancePoint
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the normal of the item. */
|
||||
const Vec3 getNormal() const
|
||||
{
|
||||
return quatRotate(m_original_rotation, Vec3(0,1,0));
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
scene::ISceneNode *getSceneNode()
|
||||
{
|
||||
|
@ -43,7 +43,8 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
|
||||
if (m_type == IEI_NEW)
|
||||
{
|
||||
m_xyz = buffer->getVec3();
|
||||
*count -= 12;
|
||||
m_normal = buffer->getVec3();
|
||||
*count -= 24;
|
||||
}
|
||||
else // IEI_COLLECT
|
||||
{
|
||||
@ -71,7 +72,10 @@ void ItemEventInfo::saveState(BareNetworkString *buffer)
|
||||
// Only new item and collecting items need the index and kart id:
|
||||
buffer->addUInt8(m_kart_id).addUInt16(m_index);
|
||||
if (m_type == IEI_NEW)
|
||||
{
|
||||
buffer->add(m_xyz);
|
||||
buffer->add(m_normal);
|
||||
}
|
||||
else if (m_type == IEI_COLLECT)
|
||||
buffer->addUInt16(m_ticks_till_return);
|
||||
}
|
||||
|
@ -52,6 +52,9 @@ private:
|
||||
/** In case of new items the position of the new item. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** The normal of an item. */
|
||||
Vec3 m_normal;
|
||||
|
||||
/** 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;
|
||||
@ -76,9 +79,9 @@ public:
|
||||
* need to encode the new item type.
|
||||
*/
|
||||
ItemEventInfo(int ticks, ItemState::ItemType type, int index,
|
||||
int kart_id, const Vec3 &xyz)
|
||||
int kart_id, const Vec3 &xyz, const Vec3 &normal)
|
||||
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz),
|
||||
m_ticks_till_return(0)
|
||||
m_normal(normal), m_ticks_till_return(0)
|
||||
{
|
||||
m_type = IEI_NEW;
|
||||
} // ItemEventInfo(new item)
|
||||
@ -125,6 +128,13 @@ public:
|
||||
return m_xyz;
|
||||
} // getXYZ
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the normal of a new item only. */
|
||||
const Vec3& getNormal() const
|
||||
{
|
||||
assert(isNewItem());
|
||||
return m_normal;
|
||||
} // getNormal
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the ticks till return, used only by collection events. */
|
||||
int getTicksTillReturn() const { return m_ticks_till_return; }
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -257,42 +257,44 @@ unsigned int ItemManager::insertItem(Item *item)
|
||||
* bubblegum).
|
||||
* \param type Type of the item.
|
||||
* \param kart The kart that drops the new item.
|
||||
* \param xyz Can be used to overwrite the item location (used in networking).
|
||||
* \param server_xyz Can be used to overwrite the item location.
|
||||
* \param server_normal The normal as seen on the server.
|
||||
*/
|
||||
Item* ItemManager::dropNewItem(ItemState::ItemType type,
|
||||
const AbstractKart *kart, const Vec3 *xyz)
|
||||
const AbstractKart *kart,
|
||||
const Vec3 *server_xyz,
|
||||
const Vec3 *server_normal)
|
||||
{
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient() && !server_xyz) return NULL;
|
||||
Vec3 normal, pos;
|
||||
const Material* material_hit;
|
||||
Vec3 pos = xyz ? *xyz : kart->getXYZ();
|
||||
Vec3 to = pos + kart->getTrans().getBasis() * Vec3(0, -10000, 0);
|
||||
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
|
||||
&hit_point,
|
||||
&material_hit,
|
||||
&normal);
|
||||
|
||||
// We will get no material if the kart is 'over nothing' when dropping
|
||||
// the bubble gum. In most cases this means that the item does not need
|
||||
// to be created (and we just return NULL). Only exception: if the server
|
||||
// has sent a 'new item' event (which means its raycast found terrain),
|
||||
// but the client does not have found a terrain (e.g. differences in
|
||||
// position or more likely floating point differences). In this case, we
|
||||
// must use the server position. In this and only this case xyz is not
|
||||
// NULL (and then contains the server's position for the item).
|
||||
if (!material_hit && !xyz) return NULL;
|
||||
|
||||
if (!material_hit)
|
||||
if (!server_xyz)
|
||||
{
|
||||
// We are on a client which has received a new item event. Still
|
||||
// create this item
|
||||
normal.setValue(0, 1, 0); // Arbitrary, we don't have a normal
|
||||
pos = *xyz;
|
||||
// We are doing a new drop locally, i.e. not based on
|
||||
// server data. So we need a raycast to find the correct
|
||||
// location and normal of the item:
|
||||
pos = server_xyz ? *server_xyz : kart->getXYZ();
|
||||
Vec3 to = pos + kart->getTrans().getBasis() * Vec3(0, -10000, 0);
|
||||
Vec3 hit_point;
|
||||
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
|
||||
&hit_point,
|
||||
&material_hit,
|
||||
&normal);
|
||||
|
||||
// We will get no material if the kart is 'over nothing' when dropping
|
||||
// the bubble gum. In most cases this means that the item does not need
|
||||
// to be created (and we just return NULL).
|
||||
if (!material_hit) return NULL;
|
||||
normal.normalize();
|
||||
pos = hit_point + kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
normal.normalize();
|
||||
pos = hit_point + kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
|
||||
// We are on a client which has received a new item event from the
|
||||
// server. So use the server's data for the new item:
|
||||
normal = *server_normal;
|
||||
pos = *server_xyz;
|
||||
}
|
||||
|
||||
ItemState::ItemType mesh_type = type;
|
||||
|
@ -133,7 +133,9 @@ public:
|
||||
virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal);
|
||||
virtual Item* dropNewItem (ItemState::ItemType type,
|
||||
const AbstractKart* parent, const Vec3 *xyz=NULL);
|
||||
const AbstractKart* parent,
|
||||
const Vec3 *server_xyz = NULL,
|
||||
const Vec3 *normal = NULL);
|
||||
virtual Item* placeTrigger (const Vec3& xyz, float distance,
|
||||
TriggerItemListener* listener);
|
||||
void update (int ticks);
|
||||
|
@ -148,23 +148,29 @@ void NetworkItemManager::switchItems()
|
||||
* \param type Type of the item.
|
||||
* \param kart In case of a dropped item used to avoid that a kart
|
||||
* is affected by its own items.
|
||||
* \param server_xyz In case of rewind the server's position of this item.
|
||||
* \param server_normal In case of rewind the server's normal of this item.
|
||||
*/
|
||||
Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
|
||||
const AbstractKart *kart, const Vec3 *xyz)
|
||||
const AbstractKart *kart,
|
||||
const Vec3 *server_xyz,
|
||||
const Vec3 *server_normal)
|
||||
{
|
||||
Item *item = ItemManager::dropNewItem(type, kart, xyz);
|
||||
Item *item = ItemManager::dropNewItem(type, kart, server_xyz, server_normal);
|
||||
|
||||
if(!item) return NULL;
|
||||
|
||||
// Nothing else to do for client
|
||||
if (NetworkConfig::get()->isClient()) return item;
|
||||
|
||||
assert(!server_xyz);
|
||||
// Server: store the data for this event:
|
||||
m_item_events.lock();
|
||||
m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
|
||||
type, item->getItemId(),
|
||||
kart->getWorldKartId(),
|
||||
xyz ? *xyz : kart->getXYZ() );
|
||||
item->getXYZ(),
|
||||
item->getNormal());
|
||||
m_item_events.unlock();
|
||||
return item;
|
||||
} // dropNewItem
|
||||
@ -409,7 +415,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
AbstractKart *kart = world->getKart(iei.getKartId());
|
||||
ItemState *is = new ItemState(iei.getNewItemType(), kart,
|
||||
iei.getIndex() );
|
||||
is->initItem(iei.getNewItemType(), iei.getXYZ());
|
||||
is->initItem(iei.getNewItemType(), iei.getXYZ(), iei.getNormal());
|
||||
if (m_switch_ticks >= 0)
|
||||
{
|
||||
ItemState::ItemType new_type = m_switch_to[is->getType()];
|
||||
@ -491,8 +497,9 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// A new item was dropped according to the server that is not
|
||||
// yet part of the current state --> create new item
|
||||
Vec3 xyz = is->getXYZ();
|
||||
Vec3 normal = is->getNormal();
|
||||
Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
|
||||
&xyz);
|
||||
&xyz, &normal );
|
||||
if (i != item_new->getItemId())
|
||||
{
|
||||
// The newly created item on the client has been given a
|
||||
|
@ -80,8 +80,10 @@ public:
|
||||
int ticks) OVERRIDE;
|
||||
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual void switchItems() OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
|
||||
const Vec3 *xyz=NULL) OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type,
|
||||
const AbstractKart *kart,
|
||||
const Vec3 *server_xyz = NULL,
|
||||
const Vec3 *server_normal = NULL) OVERRIDE;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
OVERRIDE;
|
||||
virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE;
|
||||
|
@ -2672,7 +2672,7 @@ float Kart::applyAirFriction(float engine_power)
|
||||
//Instead of making increasing gears have enormous power gaps, apply friction
|
||||
|
||||
float mass_factor = m_kart_properties->getMass()/350.0f;
|
||||
float compense_linear_slowdown = 39.33f*getSpeed()*mass_factor;
|
||||
float compense_linear_slowdown = 39.33f*fabsf(getSpeed())*mass_factor;
|
||||
|
||||
engine_power += compense_linear_slowdown;
|
||||
|
||||
|
@ -155,7 +155,7 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
buffer->add(body->getLinearVelocity());
|
||||
buffer->add(body->getAngularVelocity());
|
||||
buffer->addUInt16(m_vehicle->getTimedRotationTicks());
|
||||
buffer->add(m_vehicle->getTimedRotation());
|
||||
buffer->addFloat(m_vehicle->getTimedRotation());
|
||||
|
||||
// For collision rewind
|
||||
buffer->addUInt16(m_bounce_back_ticks);
|
||||
@ -262,10 +262,10 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
}
|
||||
|
||||
uint16_t time_rot = buffer->getUInt16();
|
||||
float timed_rotation_y = buffer->getFloat();
|
||||
// Set timed rotation divides by time_rot
|
||||
m_vehicle->setTimedRotation(time_rot,
|
||||
stk_config->ticks2Time(time_rot)
|
||||
* buffer->getVec3());
|
||||
stk_config->ticks2Time(time_rot) * timed_rotation_y);
|
||||
|
||||
// Collision rewind
|
||||
m_bounce_back_ticks = buffer->getUInt16();
|
||||
|
@ -87,7 +87,7 @@ void Skidding::reset()
|
||||
btVector3 rot(0, 0, 0);
|
||||
// Only access the vehicle if the kart is not a ghost
|
||||
if (!m_kart->isGhostKart())
|
||||
m_kart->getVehicle()->setTimedRotation(0, rot);
|
||||
m_kart->getVehicle()->setTimedRotation(0, 0);
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -535,9 +535,9 @@ void Skidding::update(int ticks, bool is_on_ground,
|
||||
float t = std::min(skid_time_float, kp->getSkidVisualTime());
|
||||
t = std::min(t, kp->getSkidRevertVisualTime());
|
||||
|
||||
btVector3 rot(0, m_visual_rotation * kp->getSkidPostSkidRotateFactor(), 0);
|
||||
m_kart->getVehicle()->setTimedRotation(
|
||||
(uint16_t)stk_config->time2Ticks(t), rot);
|
||||
(uint16_t)stk_config->time2Ticks(t),
|
||||
m_visual_rotation * kp->getSkidPostSkidRotateFactor());
|
||||
// skid_time is used to count backwards for the GFX
|
||||
m_skid_time = stk_config->time2Ticks(t);
|
||||
if(bonus_time>0)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
const Vec3 g_kart_flag_offset(0.0, 0.2f, -0.5f);
|
||||
const float g_capture_length = 2.0f;
|
||||
const float g_capture_length = 3.0f;
|
||||
const int g_captured_score = 10;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -627,6 +627,10 @@ void LinearWorld::getKartsDisplayInfo(
|
||||
}
|
||||
rank_info.m_text = irr::core::stringw(str.c_str());
|
||||
}
|
||||
else if (kart->hasFinishedRace())
|
||||
{
|
||||
rank_info.m_text = kart->getController()->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
rank_info.m_text = "";
|
||||
|
@ -75,7 +75,7 @@ ClientLobby::ClientLobby(const TransportAddress& a, std::shared_ptr<Server> s)
|
||||
: LobbyProtocol(NULL)
|
||||
{
|
||||
m_waiting_for_game = false;
|
||||
m_server_auto_lap = false;
|
||||
m_server_auto_game_time = false;
|
||||
m_received_server_result = false;
|
||||
m_state.store(NONE);
|
||||
m_server_address = a;
|
||||
@ -697,6 +697,9 @@ void ClientLobby::updatePlayerList(Event* event)
|
||||
if (d == PLAYER_DIFFICULTY_HANDICAP)
|
||||
std::get<3>(pl) = _("%s (handicapped)", std::get<3>(pl));
|
||||
std::get<5>(pl) = (KartTeam)data.getUInt8();
|
||||
bool ready = data.getUInt8() == 1;
|
||||
if (ready)
|
||||
std::get<4>(pl) = 4;
|
||||
players.push_back(pl);
|
||||
}
|
||||
|
||||
@ -841,7 +844,7 @@ void ClientLobby::startSelection(Event* event)
|
||||
SFXManager::get()->quickSound("wee");
|
||||
const NetworkString& data = event->data();
|
||||
bool skip_kart_screen = data.getUInt8() == 1;
|
||||
m_server_auto_lap = data.getUInt8() == 1;
|
||||
m_server_auto_game_time = data.getUInt8() == 1;
|
||||
const unsigned kart_num = data.getUInt16();
|
||||
const unsigned track_num = data.getUInt16();
|
||||
m_available_karts.clear();
|
||||
|
@ -71,7 +71,7 @@ private:
|
||||
|
||||
bool m_waiting_for_game;
|
||||
|
||||
bool m_server_auto_lap;
|
||||
bool m_server_auto_game_time;
|
||||
|
||||
bool m_received_server_result;
|
||||
|
||||
@ -111,7 +111,7 @@ public:
|
||||
{ return m_state.load() == REQUESTING_CONNECTION; }
|
||||
bool isLobbyReady() const { return m_state.load() == CONNECTED; }
|
||||
bool isWaitingForGame() const { return m_waiting_for_game; }
|
||||
bool isServerAutoLap() const { return m_server_auto_lap; }
|
||||
bool isServerAutoGameTime() const { return m_server_auto_game_time; }
|
||||
virtual bool isRacing() const OVERRIDE { return m_state.load() == RACING; }
|
||||
void clearPlayers();
|
||||
};
|
||||
|
@ -460,6 +460,8 @@ void ServerLobby::asynchronousUpdate()
|
||||
!m_game_setup->isGrandPrixStarted())
|
||||
{
|
||||
resetPeersReady();
|
||||
if (m_timeout.load() != std::numeric_limits<int64_t>::max())
|
||||
updatePlayerList();
|
||||
m_timeout.store(std::numeric_limits<int64_t>::max());
|
||||
}
|
||||
if (m_timeout.load() < (int64_t)StkTime::getRealTimeMs() ||
|
||||
@ -833,7 +835,9 @@ void ServerLobby::startSelection(const Event *event)
|
||||
}
|
||||
if (ServerConfig::m_owner_less)
|
||||
{
|
||||
m_peers_ready.at(event->getPeerSP()) = true;
|
||||
m_peers_ready.at(event->getPeerSP()) =
|
||||
!m_peers_ready.at(event->getPeerSP());
|
||||
updatePlayerList();
|
||||
return;
|
||||
}
|
||||
if (event->getPeerSP() != m_server_owner.lock())
|
||||
@ -879,7 +883,7 @@ void ServerLobby::startSelection(const Event *event)
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(LE_START_SELECTION).addUInt8(
|
||||
m_game_setup->isGrandPrixStarted() ? 1 : 0)
|
||||
.addUInt8(ServerConfig::m_auto_lap_ratio > 0.0f ? 1 : 0);
|
||||
.addUInt8(ServerConfig::m_auto_game_time_ratio > 0.0f ? 1 : 0);
|
||||
|
||||
// Remove karts / tracks from server that are not supported on all clients
|
||||
std::set<std::string> karts_erase, tracks_erase;
|
||||
@ -1744,6 +1748,11 @@ void ServerLobby::updatePlayerList(bool update_when_reset_server)
|
||||
pl->addUInt8(profile->getTeam());
|
||||
else
|
||||
pl->addUInt8(KART_TEAM_NONE);
|
||||
std::shared_ptr<STKPeer> p = profile->getPeer();
|
||||
uint8_t ready = (!game_started &&
|
||||
m_peers_ready.find(p) != m_peers_ready.end() &&
|
||||
m_peers_ready.at(p)) ? 1 : 0;
|
||||
pl->addUInt8(ready);
|
||||
}
|
||||
|
||||
// Don't send this message to in-game players
|
||||
@ -1876,14 +1885,14 @@ void ServerLobby::playerVote(Event* event)
|
||||
|
||||
if (race_manager->modeHasLaps())
|
||||
{
|
||||
if (ServerConfig::m_auto_lap_ratio > 0.0f)
|
||||
if (ServerConfig::m_auto_game_time_ratio > 0.0f)
|
||||
{
|
||||
Track* t = track_manager->getTrack(track_name);
|
||||
if (t)
|
||||
{
|
||||
lap = (uint8_t)(fmaxf(1.0f,
|
||||
(float)t->getDefaultNumberOfLaps() *
|
||||
ServerConfig::m_auto_lap_ratio));
|
||||
ServerConfig::m_auto_game_time_ratio));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1895,6 +1904,20 @@ void ServerLobby::playerVote(Event* event)
|
||||
else if (lap == 0)
|
||||
lap = (uint8_t)3;
|
||||
}
|
||||
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER &&
|
||||
ServerConfig::m_auto_game_time_ratio > 0.0f)
|
||||
{
|
||||
if (m_game_setup->isSoccerGoalTarget())
|
||||
{
|
||||
lap = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
|
||||
UserConfigParams::m_num_goals);
|
||||
}
|
||||
else
|
||||
{
|
||||
lap = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
|
||||
UserConfigParams::m_soccer_time_limit);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
|
||||
std::string name = StringUtils::wideToUtf8(event->getPeer()
|
||||
@ -2445,6 +2468,7 @@ void ServerLobby::addWaitingPlayersToGame()
|
||||
void ServerLobby::resetServer()
|
||||
{
|
||||
addWaitingPlayersToGame();
|
||||
resetPeersReady();
|
||||
m_state = NetworkConfig::get()->isLAN() ?
|
||||
WAITING_FOR_START_GAME : REGISTER_SELF_ADDRESS;
|
||||
updatePlayerList(true/*update_when_reset_server*/);
|
||||
|
@ -238,12 +238,17 @@ namespace ServerConfig
|
||||
"(time-limit-threshold-ctf + flag-return-timemout / 60.0)) * 60.0,"
|
||||
" negative value to disable time limit."));
|
||||
|
||||
SERVER_CFG_PREFIX FloatServerConfigParam m_auto_lap_ratio
|
||||
SERVER_CFG_DEFAULT(FloatServerConfigParam(-1.0f, "auto-lap-ratio",
|
||||
"Value used by server to automatically calculate "
|
||||
"lap of each race in network game, if more than 0.0f, the number of "
|
||||
"lap of each track vote in linear race will be determined by "
|
||||
"max(1.0f, auto-lap-ratio * default lap of that track)."));
|
||||
SERVER_CFG_PREFIX FloatServerConfigParam m_auto_game_time_ratio
|
||||
SERVER_CFG_DEFAULT(FloatServerConfigParam(-1.0f, "auto-game-time-ratio",
|
||||
"Value used by server to automatically estimate each game time. "
|
||||
"For races, it decides the lap of each race in network game, "
|
||||
"if more than 0.0f, the number of lap of each track vote in "
|
||||
"linear race will be determined by "
|
||||
"max(1.0f, auto-game-time-ratio * default lap of that track). "
|
||||
"For soccer if more than 0.0f, for time limit game it will be "
|
||||
"auto-game-time-ratio * soccer-time-limit in UserConfig, for goal "
|
||||
"limit game it will be auto-game-time-ratio * numgoals "
|
||||
"in UserConfig, -1 to disable for all."));
|
||||
|
||||
SERVER_CFG_PREFIX IntServerConfigParam m_max_ping
|
||||
SERVER_CFG_DEFAULT(IntServerConfigParam(300, "max-ping",
|
||||
|
@ -121,7 +121,7 @@ void btKart::reset()
|
||||
m_num_wheels_on_ground = 0;
|
||||
m_additional_impulse = btVector3(0,0,0);
|
||||
m_ticks_additional_impulse = 0;
|
||||
m_additional_rotation = btVector3(0,0,0);
|
||||
m_additional_rotation = 0;
|
||||
m_ticks_additional_rotation = 0;
|
||||
m_max_speed = -1.0f;
|
||||
m_min_speed = 0.0f;
|
||||
@ -522,9 +522,9 @@ void btKart::updateVehicle( btScalar step )
|
||||
btTransform &t = m_chassisBody->getWorldTransform();
|
||||
// We have fixed timestep
|
||||
float dt = stk_config->ticks2Time(1);
|
||||
btQuaternion add_rot(m_additional_rotation.getY()*dt,
|
||||
m_additional_rotation.getX()*dt,
|
||||
m_additional_rotation.getZ()*dt);
|
||||
btQuaternion add_rot(m_additional_rotation * dt,
|
||||
0.0f,
|
||||
0.0f);
|
||||
t.setRotation(t.getRotation()*add_rot);
|
||||
m_chassisBody->setWorldTransform(t);
|
||||
// Also apply the rotation to the interpolated world transform.
|
||||
|
@ -83,8 +83,8 @@ private:
|
||||
/** The time the additional impulse should be applied. */
|
||||
uint16_t m_ticks_additional_impulse;
|
||||
|
||||
/** Additional rotation that is applied over a certain amount of time. */
|
||||
btVector3 m_additional_rotation;
|
||||
/** Additional rotation in y-axis that is applied over a certain amount of time. */
|
||||
float m_additional_rotation;
|
||||
|
||||
/** Duration over which the additional rotation is applied. */
|
||||
uint16_t m_ticks_additional_rotation;
|
||||
@ -236,21 +236,26 @@ public:
|
||||
{ return m_ticks_additional_impulse; }
|
||||
// ------------------------------------------------------------------------
|
||||
const btVector3& getAdditionalImpulse() const
|
||||
{ return m_additional_impulse; }
|
||||
{ return m_additional_impulse; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets a rotation that is applied over a certain amount of time (to avoid
|
||||
* a too rapid changes in the kart).
|
||||
* \param t Ticks for the rotation to be applied.
|
||||
* \param torque The rotation to apply. */
|
||||
void setTimedRotation(uint16_t t, const btVector3 &rot)
|
||||
* \param rot_in_y_axis The rotation in y-axis to apply. */
|
||||
void setTimedRotation(uint16_t t, float rot_in_y_axis)
|
||||
{
|
||||
if(t>0) m_additional_rotation = rot / (stk_config->ticks2Time(t));
|
||||
if (t > 0)
|
||||
{
|
||||
m_additional_rotation =
|
||||
rot_in_y_axis / (stk_config->ticks2Time(t));
|
||||
}
|
||||
m_ticks_additional_rotation = t;
|
||||
} // setTimedTorque
|
||||
// ------------------------------------------------------------------------
|
||||
const btVector3& getTimedRotation() const { return m_additional_rotation; }
|
||||
float getTimedRotation() const { return m_additional_rotation; }
|
||||
// ------------------------------------------------------------------------
|
||||
uint16_t getTimedRotationTicks() const { return m_ticks_additional_rotation; }
|
||||
uint16_t getTimedRotationTicks() const
|
||||
{ return m_ticks_additional_rotation; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the maximum speed for this kart. */
|
||||
void setMaxSpeed(float new_max_speed)
|
||||
|
@ -70,7 +70,6 @@ NetworkingLobby::NetworkingLobby() : Screen("online/networking_lobby.stkgui")
|
||||
m_header = NULL;
|
||||
m_text_bubble = NULL;
|
||||
m_timeout_message = NULL;
|
||||
m_exit_widget = NULL;
|
||||
m_start_button = NULL;
|
||||
m_player_list = NULL;
|
||||
m_chat_box = NULL;
|
||||
@ -106,9 +105,6 @@ void NetworkingLobby::loadedFromFile()
|
||||
m_player_list = getWidget<ListWidget>("players");
|
||||
assert(m_player_list!= NULL);
|
||||
|
||||
m_exit_widget = getWidget<IconButtonWidget>("exit");
|
||||
assert(m_exit_widget != NULL);
|
||||
|
||||
m_icon_bank = new irr::gui::STKModifiedSpriteBank(GUIEngine::getGUIEnv());
|
||||
video::ITexture* icon_1 = irr_driver->getTexture
|
||||
(file_manager->getAsset(FileManager::GUI_ICON, "crown.png"));
|
||||
@ -118,10 +114,13 @@ void NetworkingLobby::loadedFromFile()
|
||||
(file_manager->getAsset(FileManager::GUI_ICON, "main_help.png"));
|
||||
video::ITexture* icon_4 = irr_driver->getTexture
|
||||
(file_manager->getAsset(FileManager::GUI_ICON, "hourglass.png"));
|
||||
video::ITexture* icon_5 = irr_driver->getTexture
|
||||
(file_manager->getAsset(FileManager::GUI_ICON, "green_check.png"));
|
||||
m_icon_bank->addTextureAsSprite(icon_1);
|
||||
m_icon_bank->addTextureAsSprite(icon_2);
|
||||
m_icon_bank->addTextureAsSprite(icon_3);
|
||||
m_icon_bank->addTextureAsSprite(icon_4);
|
||||
m_icon_bank->addTextureAsSprite(icon_5);
|
||||
const int screen_width = irr_driver->getFrameSize().Width;
|
||||
m_icon_bank->setScale(screen_width > 1280 ? 0.4f : 0.25f);
|
||||
} // loadedFromFile
|
||||
@ -140,6 +139,7 @@ void NetworkingLobby::init()
|
||||
{
|
||||
Screen::init();
|
||||
|
||||
getWidget("config")->setVisible(false);
|
||||
m_player_names.clear();
|
||||
m_allow_change_team = false;
|
||||
m_has_auto_start_in_server = false;
|
||||
@ -152,7 +152,7 @@ void NetworkingLobby::init()
|
||||
//I18N: In the networking lobby
|
||||
m_header->setText(_("Lobby"), false);
|
||||
m_server_info_height = GUIEngine::getFont()->getDimension(L"X").Height;
|
||||
m_start_button->setText(_("Start race"));
|
||||
m_start_button->setLabel(_("Start race"));
|
||||
m_start_button->setVisible(false);
|
||||
m_state = LS_CONNECTING;
|
||||
getWidget("chat")->setVisible(false);
|
||||
@ -245,12 +245,11 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
if (cl && cl->isWaitingForGame())
|
||||
{
|
||||
m_start_button->setVisible(false);
|
||||
m_exit_widget->setVisible(true);
|
||||
m_timeout_message->setVisible(true);
|
||||
//I18N: In the networking lobby, show when player is required to wait
|
||||
//before the current game finish
|
||||
core::stringw msg = _("Please wait for current game to end.");
|
||||
m_timeout_message->setText(msg, true);
|
||||
m_timeout_message->setText(msg, false);
|
||||
core::stringw total_msg;
|
||||
for (auto& string : m_server_info)
|
||||
{
|
||||
@ -281,7 +280,7 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
_P("Game will start if there is more than %d player.",
|
||||
"Game will start if there are more than %d players.",
|
||||
(int)(m_min_start_game_players - 1));
|
||||
m_timeout_message->setText(msg, true);
|
||||
m_timeout_message->setText(msg, false);
|
||||
}
|
||||
|
||||
if (m_cur_starting_timer != std::numeric_limits<int64_t>::max())
|
||||
@ -292,11 +291,12 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
remain = 0;
|
||||
//I18N: In the networking lobby, display the starting timeout
|
||||
//for owner-less server to begin a game
|
||||
core::stringw msg = _P("Starting after %d second "
|
||||
"or everyone pressed 'Ready' button.",
|
||||
"Starting after %d seconds "
|
||||
"or everyone pressed 'Ready' button.", (int)remain);
|
||||
m_timeout_message->setText(msg, true);
|
||||
core::stringw msg = _P("Starting after %d second, "
|
||||
"or once everyone has pressed the 'Ready' button.",
|
||||
"Starting after %d seconds, "
|
||||
"or once everyone has pressed the 'Ready' button.",
|
||||
(int)remain);
|
||||
m_timeout_message->setText(msg, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -307,9 +307,8 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
if (m_state == LS_ADD_PLAYERS)
|
||||
{
|
||||
m_text_bubble->setText(_("Everyone:\nPress the 'Select' button to "
|
||||
"join the game"), true);
|
||||
"join the game"), false);
|
||||
m_start_button->setVisible(false);
|
||||
m_exit_widget->setVisible(false);
|
||||
if (!GUIEngine::ModalDialog::isADialogActive())
|
||||
{
|
||||
input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
|
||||
@ -319,7 +318,6 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
}
|
||||
|
||||
m_start_button->setVisible(false);
|
||||
m_exit_widget->setVisible(true);
|
||||
if (!cl || !cl->isLobbyReady())
|
||||
{
|
||||
core::stringw connect_msg;
|
||||
@ -333,7 +331,7 @@ void NetworkingLobby::onUpdate(float delta)
|
||||
connect_msg =
|
||||
StringUtils::loadingDots(_("Finding a quick play server"));
|
||||
}
|
||||
m_text_bubble->setText(connect_msg, true);
|
||||
m_text_bubble->setText(connect_msg, false);
|
||||
m_start_button->setVisible(false);
|
||||
}
|
||||
else
|
||||
@ -436,10 +434,6 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
|
||||
sendChat(m_chat_box->getText());
|
||||
m_chat_box->setText("");
|
||||
} // send chat message
|
||||
else if (name == m_exit_widget->m_properties[PROP_ID])
|
||||
{
|
||||
StateManager::get()->escapePressed();
|
||||
}
|
||||
else if (name == m_start_button->m_properties[PROP_ID])
|
||||
{
|
||||
// Send a message to the server to start
|
||||
@ -578,7 +572,7 @@ void NetworkingLobby::initAutoStartTimer(bool grand_prix_started,
|
||||
|
||||
//I18N: In the networking lobby, ready button is to allow player to tell
|
||||
//server that he is ready for next game for owner less server
|
||||
m_start_button->setText(_("Ready"));
|
||||
m_start_button->setLabel(_("Ready"));
|
||||
m_has_auto_start_in_server = true;
|
||||
m_min_start_game_players = grand_prix_started ? 0 : min_players;
|
||||
m_start_timeout = start_timeout;
|
||||
|
@ -82,7 +82,6 @@ private:
|
||||
GUIEngine::LabelWidget* m_header;
|
||||
GUIEngine::LabelWidget* m_text_bubble;
|
||||
GUIEngine::LabelWidget* m_timeout_message;
|
||||
GUIEngine::IconButtonWidget* m_exit_widget;
|
||||
GUIEngine::IconButtonWidget* m_start_button;
|
||||
GUIEngine::ListWidget* m_player_list;
|
||||
GUIEngine::TextBoxWidget* m_chat_box;
|
||||
|
@ -273,6 +273,8 @@ void TracksScreen::init()
|
||||
{
|
||||
// Notice: for arena (battle / soccer) lap and reverse will be mapped to
|
||||
// goals / time limit and random item location
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
assert(cl);
|
||||
if (UserConfigParams::m_num_laps == 0 ||
|
||||
UserConfigParams::m_num_laps > 20)
|
||||
UserConfigParams::m_num_laps = 1;
|
||||
@ -297,25 +299,34 @@ void TracksScreen::init()
|
||||
}
|
||||
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
m_laps->setVisible(true);
|
||||
getWidget("lap-text")->setVisible(true);
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
assert(cl);
|
||||
if (cl->getGameSetup()->isSoccerGoalTarget())
|
||||
if (cl->isServerAutoGameTime())
|
||||
{
|
||||
//I18N: In track screen
|
||||
getWidget<LabelWidget>("lap-text")->setText(_("Number of goals to win"), false);
|
||||
m_laps->setValue(UserConfigParams::m_num_goals);
|
||||
m_laps->setMin(1);
|
||||
m_laps->setMax(10);
|
||||
getWidget("lap-text")->setVisible(false);
|
||||
m_laps->setVisible(false);
|
||||
m_laps->setValue(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//I18N: In track screen
|
||||
getWidget<LabelWidget>("lap-text")->setText(_("Maximum time (min.)"), false);
|
||||
m_laps->setValue(UserConfigParams::m_soccer_time_limit);
|
||||
m_laps->setMin(1);
|
||||
m_laps->setMax(15);
|
||||
m_laps->setVisible(true);
|
||||
getWidget("lap-text")->setVisible(true);
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
assert(cl);
|
||||
if (cl->getGameSetup()->isSoccerGoalTarget())
|
||||
{
|
||||
//I18N: In track screen
|
||||
getWidget<LabelWidget>("lap-text")->setText(_("Number of goals to win"), false);
|
||||
m_laps->setValue(UserConfigParams::m_num_goals);
|
||||
m_laps->setMin(1);
|
||||
m_laps->setMax(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
//I18N: In track screen
|
||||
getWidget<LabelWidget>("lap-text")->setText(_("Maximum time (min.)"), false);
|
||||
m_laps->setValue(UserConfigParams::m_soccer_time_limit);
|
||||
m_laps->setMin(1);
|
||||
m_laps->setMax(15);
|
||||
}
|
||||
}
|
||||
getWidget("reverse-text")->setVisible(true);
|
||||
//I18N: In track screen
|
||||
@ -325,9 +336,7 @@ void TracksScreen::init()
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cl = LobbyProtocol::get<ClientLobby>();
|
||||
assert(cl);
|
||||
if (cl->isServerAutoLap())
|
||||
if (cl->isServerAutoGameTime())
|
||||
{
|
||||
getWidget("lap-text")->setVisible(false);
|
||||
m_laps->setVisible(false);
|
||||
|
@ -197,6 +197,7 @@ RaceGUI::RaceGUI()
|
||||
m_blue_flag = irr_driver->getTexture(FileManager::GUI_ICON, "blue_flag.png");
|
||||
m_soccer_ball = irr_driver->getTexture(FileManager::GUI_ICON, "soccer_ball_normal.png");
|
||||
m_heart_icon = irr_driver->getTexture(FileManager::GUI_ICON, "heart.png");
|
||||
m_champion = irr_driver->getTexture(FileManager::GUI_ICON, "gp_new.png");
|
||||
} // RaceGUI
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -307,8 +308,6 @@ void RaceGUI::renderGlobal(float dt)
|
||||
drawGlobalPlayerIcons(0);
|
||||
}
|
||||
}
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
drawScores();
|
||||
#endif
|
||||
} // renderGlobal
|
||||
|
||||
@ -354,55 +353,6 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt)
|
||||
drawLap(kart, viewport, scaling);
|
||||
} // renderPlayerView
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Shows the current soccer result.
|
||||
*/
|
||||
void RaceGUI::drawScores()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
int offset_y = 5;
|
||||
int offset_x = 5;
|
||||
gui::ScalableFont* font = GUIEngine::getTitleFont();
|
||||
static video::SColor color = video::SColor(255,255,255,255);
|
||||
|
||||
//Draw two teams score
|
||||
irr::video::ITexture *team_icon = m_red_team;
|
||||
|
||||
for(unsigned int i=0; i<2; i++)
|
||||
{
|
||||
core::recti position(offset_x, offset_y,
|
||||
offset_x + 2*m_minimap_player_size, offset_y + 2*m_minimap_player_size);
|
||||
|
||||
core::stringw score = StringUtils::toWString(sw->getScore((KartTeam)i));
|
||||
int string_height =
|
||||
GUIEngine::getFont()->getDimension(score.c_str()).Height;
|
||||
core::recti pos(position.UpperLeftCorner.X + 5,
|
||||
position.LowerRightCorner.Y + offset_y,
|
||||
position.LowerRightCorner.X,
|
||||
position.LowerRightCorner.Y + string_height);
|
||||
|
||||
font->setBlackBorder(true);
|
||||
font->draw(score.c_str(),pos,color);
|
||||
font->setBlackBorder(false);
|
||||
|
||||
if (i == 1)
|
||||
{
|
||||
team_icon = m_blue_team;
|
||||
}
|
||||
core::rect<s32> indicator_pos(offset_x, offset_y,
|
||||
offset_x + (int)(m_minimap_player_size*2),
|
||||
offset_y + (int)(m_minimap_player_size*2));
|
||||
core::rect<s32> source_rect(core::position2d<s32>(0,0),
|
||||
team_icon->getSize());
|
||||
draw2DImage(team_icon,indicator_pos,source_rect,
|
||||
NULL,NULL,true);
|
||||
offset_x += position.LowerRightCorner.X + 30;
|
||||
}
|
||||
#endif
|
||||
} // drawScores
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Displays the racing time on the screen.
|
||||
*/
|
||||
@ -843,29 +793,6 @@ void RaceGUI::drawRank(const AbstractKart *kart,
|
||||
int meter_height, float dt)
|
||||
{
|
||||
static video::SColor color = video::SColor(255, 255, 255, 255);
|
||||
// Draw hit or capture limit in network game
|
||||
if ((race_manager->getMajorMode() == RaceManager::MAJOR_MODE_FREE_FOR_ALL ||
|
||||
race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG) &&
|
||||
race_manager->getHitCaptureLimit() != std::numeric_limits<int>::max())
|
||||
{
|
||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||
font->setScale(min_ratio * 1.0f);
|
||||
font->setShadow(video::SColor(255, 128, 0, 0));
|
||||
std::ostringstream oss;
|
||||
oss << race_manager->getHitCaptureLimit();
|
||||
|
||||
core::recti pos;
|
||||
pos.LowerRightCorner = core::vector2di(int(offset.X + 0.64f*meter_width),
|
||||
int(offset.Y - 0.49f*meter_height));
|
||||
pos.UpperLeftCorner = core::vector2di(int(offset.X + 0.64f*meter_width),
|
||||
int(offset.Y - 0.49f*meter_height));
|
||||
|
||||
font->setBlackBorder(true);
|
||||
font->draw(oss.str().c_str(), pos, color, true, true);
|
||||
font->setBlackBorder(false);
|
||||
font->setScale(1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw rank
|
||||
WorldWithRank *world = dynamic_cast<WorldWithRank*>(World::getWorld());
|
||||
@ -1223,14 +1150,50 @@ void RaceGUI::drawLap(const AbstractKart* kart,
|
||||
- m_lap_width - 10;
|
||||
pos.LowerRightCorner.X = viewport.LowerRightCorner.X;
|
||||
|
||||
// Draw CTF scores with red score - blue score
|
||||
// Draw CTF / soccer scores with red score - blue score (score limit)
|
||||
CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>(World::getWorld());
|
||||
if (ctf)
|
||||
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
|
||||
|
||||
static video::SColor color = video::SColor(255, 255, 255, 255);
|
||||
int hit_capture_limit =
|
||||
race_manager->getHitCaptureLimit() != std::numeric_limits<int>::max()
|
||||
? race_manager->getHitCaptureLimit() : -1;
|
||||
int score_limit = sw && !race_manager->hasTimeTarget() ?
|
||||
race_manager->getMaxGoal() : ctf ? hit_capture_limit : -1;
|
||||
if (!ctf && ffa && hit_capture_limit != -1)
|
||||
{
|
||||
int icon_width = irr_driver->getActualScreenSize().Height/19;
|
||||
core::rect<s32> indicator_pos(viewport.LowerRightCorner.X - (icon_width+10),
|
||||
pos.UpperLeftCorner.Y,
|
||||
viewport.LowerRightCorner.X - 10,
|
||||
pos.UpperLeftCorner.Y + icon_width);
|
||||
core::rect<s32> source_rect(core::position2d<s32>(0,0),
|
||||
m_champion->getSize());
|
||||
draw2DImage(m_champion, indicator_pos, source_rect,
|
||||
NULL, NULL, true);
|
||||
|
||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||
font->setBlackBorder(true);
|
||||
pos.UpperLeftCorner.X += 30;
|
||||
font->draw(StringUtils::toWString(hit_capture_limit).c_str(), pos, color);
|
||||
font->setBlackBorder(false);
|
||||
font->setScale(1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctf || sw)
|
||||
{
|
||||
if (score_limit != -1)
|
||||
pos.UpperLeftCorner.X -= 80;
|
||||
|
||||
int red_score = ctf ? ctf->getRedScore() : sw->getScore(KART_TEAM_RED);
|
||||
int blue_score = ctf ? ctf->getBlueScore() : sw->getScore(KART_TEAM_BLUE);
|
||||
|
||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||
font->setBlackBorder(true);
|
||||
font->setScale(scaling.Y < 1.0f ? 0.5f: 1.0f);
|
||||
core::stringw text = StringUtils::toWString(ctf->getRedScore());
|
||||
core::stringw text = StringUtils::toWString(red_score);
|
||||
font->draw(text, pos, video::SColor(255, 255, 0, 0));
|
||||
core::dimension2du d = font->getDimension(text.c_str());
|
||||
pos += core::position2di(d.Width, 0);
|
||||
@ -1238,9 +1201,17 @@ void RaceGUI::drawLap(const AbstractKart* kart,
|
||||
font->draw(text, pos, video::SColor(255, 255, 255, 255));
|
||||
d = font->getDimension(text.c_str());
|
||||
pos += core::position2di(d.Width, 0);
|
||||
text = StringUtils::toWString(ctf->getBlueScore());
|
||||
text = StringUtils::toWString(blue_score);
|
||||
font->draw(text, pos, video::SColor(255, 0, 0, 255));
|
||||
font->setScale(1.0f);
|
||||
pos += core::position2di(d.Width, 0);
|
||||
if (score_limit != -1)
|
||||
{
|
||||
text = L" (";
|
||||
text += StringUtils::toWString(score_limit);
|
||||
text += L")";
|
||||
font->draw(text, pos, video::SColor(255, 255, 255, 255));
|
||||
}
|
||||
font->setBlackBorder(false);
|
||||
return;
|
||||
}
|
||||
@ -1267,7 +1238,6 @@ void RaceGUI::drawLap(const AbstractKart* kart,
|
||||
pos.UpperLeftCorner.X -= icon_width;
|
||||
pos.LowerRightCorner.X -= icon_width;
|
||||
|
||||
static video::SColor color = video::SColor(255, 255, 255, 255);
|
||||
std::ostringstream out;
|
||||
out << lap + 1 << "/" << race_manager->getNumLaps();
|
||||
|
||||
|
@ -99,6 +99,8 @@ private:
|
||||
irr::video::ITexture *m_blue_flag;
|
||||
irr::video::ITexture *m_soccer_ball;
|
||||
irr::video::ITexture *m_heart_icon;
|
||||
/** Texture for the hit limit icon*/
|
||||
irr::video::ITexture* m_champion;
|
||||
|
||||
/** Animation state: none, getting smaller (old value),
|
||||
* getting bigger (new number). */
|
||||
@ -140,8 +142,6 @@ private:
|
||||
void drawGlobalMiniMap ();
|
||||
void drawGlobalTimer ();
|
||||
void drawLiveDifference ();
|
||||
void drawScores();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user