Merge branch 'master' of github.com:supertuxkart/stk-code
This commit is contained in:
commit
7ff7e049ea
@ -53,9 +53,9 @@ public:
|
||||
Bowling(AbstractKart* kart);
|
||||
virtual ~Bowling();
|
||||
static void init(const XMLNode &node, scene::IMesh *bowling);
|
||||
virtual bool updateAndDelete(int ticks);
|
||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
||||
virtual HitEffect *getHitEffect() const;
|
||||
virtual bool updateAndDelete(int ticks) OVERRIDE;
|
||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL) OVERRIDE;
|
||||
virtual HitEffect *getHitEffect() const OVERRIDE;
|
||||
|
||||
|
||||
}; // Bowling
|
||||
|
@ -119,11 +119,7 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
|
||||
|
||||
//do not adjust height according to terrain
|
||||
setAdjustUpVelocity(false);
|
||||
|
||||
m_body->setActivationState(DISABLE_DEACTIVATION);
|
||||
|
||||
m_body->applyTorque( btVector3(5,-3,7) );
|
||||
|
||||
additionalPhysicsProperties();
|
||||
} // Cake
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -46,24 +46,36 @@ private:
|
||||
|
||||
/** Which kart is targeted by this projectile (NULL if none). */
|
||||
Moveable* m_target;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void additionalPhysicsProperties() OVERRIDE
|
||||
{
|
||||
m_body->setActivationState(DISABLE_DEACTIVATION);
|
||||
m_body->clearForces();
|
||||
m_body->applyTorque(btVector3(5.0f, -3.0f, 7.0f));
|
||||
}
|
||||
|
||||
public:
|
||||
Cake (AbstractKart *kart);
|
||||
static void init (const XMLNode &node, scene::IMesh *cake_model);
|
||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void hitTrack () { hit(NULL); }
|
||||
virtual void hitTrack () OVERRIDE { hit(NULL); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Kinematic objects are not allowed to have a velocity (assertion in
|
||||
* bullet), so we have to do our own velocity handling here. This
|
||||
* function returns the velocity of this object. */
|
||||
virtual const btVector3 &getVelocity() const {return m_initial_velocity;}
|
||||
virtual const btVector3 &getVelocity() const OVERRIDE
|
||||
{ return m_initial_velocity; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Kinematic objects are not allowed to have a velocity (assertion in
|
||||
* bullet), so we have to do our own velocity handling here. This
|
||||
* function sets the velocity of this object.
|
||||
* \param v Linear velocity of this object.
|
||||
*/
|
||||
virtual void setVelocity(const btVector3& v) {m_initial_velocity=v; }
|
||||
virtual void setVelocity(const btVector3& v) OVERRIDE
|
||||
{ m_initial_velocity = v; }
|
||||
|
||||
}; // Cake
|
||||
|
||||
#endif
|
||||
|
@ -37,6 +37,11 @@
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/compress_network_body.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewind_info.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -75,6 +80,10 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
||||
m_owner_has_temporary_immunity = true;
|
||||
m_do_terrain_info = true;
|
||||
m_max_lifespan = -1;
|
||||
m_undo_creation = false;
|
||||
m_has_undone_destruction = false;
|
||||
m_has_server_state = false;
|
||||
m_check_created_ticks = -1;
|
||||
|
||||
// Add the graphical model
|
||||
#ifndef SERVER_ONLY
|
||||
@ -160,6 +169,10 @@ void Flyable::createPhysics(float forw_offset, const Vec3 &velocity,
|
||||
m_body->setCollisionFlags(m_body->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
|
||||
m_saved_transform = getTrans();
|
||||
m_saved_lv = m_body->getLinearVelocity();
|
||||
m_saved_av = m_body->getAngularVelocity();
|
||||
m_saved_gravity = gravity;
|
||||
} // createPhysics
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -378,7 +391,7 @@ void Flyable::setAnimation(AbstractKartAnimation *animation)
|
||||
*/
|
||||
void Flyable::updateGraphics(float dt)
|
||||
{
|
||||
updateSmoothedGraphics(dt);
|
||||
Moveable::updateSmoothedGraphics(dt);
|
||||
Moveable::updateGraphics();
|
||||
} // updateGraphics
|
||||
|
||||
@ -390,6 +403,9 @@ void Flyable::updateGraphics(float dt)
|
||||
*/
|
||||
bool Flyable::updateAndDelete(int ticks)
|
||||
{
|
||||
if (m_undo_creation)
|
||||
return false;
|
||||
|
||||
if (hasAnimation())
|
||||
{
|
||||
m_animation->update(stk_config->ticks2Time(ticks));
|
||||
@ -502,6 +518,8 @@ bool Flyable::isOwnerImmunity(const AbstractKart* kart_hit) const
|
||||
*/
|
||||
bool Flyable::hit(AbstractKart *kart_hit, PhysicalObject* object)
|
||||
{
|
||||
if (m_undo_creation)
|
||||
return false;
|
||||
// the owner of this flyable should not be hit by his own flyable
|
||||
if(isOwnerImmunity(kart_hit)) return false;
|
||||
m_has_hit_something=true;
|
||||
@ -573,5 +591,140 @@ HitEffect* Flyable::getHitEffect() const
|
||||
unsigned int Flyable::getOwnerId()
|
||||
{
|
||||
return m_owner->getWorldKartId();
|
||||
}
|
||||
} // getOwnerId
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
BareNetworkString* Flyable::saveState(std::vector<std::string>* ru)
|
||||
{
|
||||
ru->push_back(getUniqueIdentity());
|
||||
BareNetworkString *buffer = new BareNetworkString();
|
||||
CompressNetworkBody::compress(m_body->getWorldTransform(),
|
||||
m_body->getLinearVelocity(), m_body->getAngularVelocity(), buffer);
|
||||
uint16_t hit_and_ticks = (m_has_hit_something ? 1 << 15 : 0) |
|
||||
m_ticks_since_thrown;
|
||||
buffer->addUInt16(hit_and_ticks);
|
||||
return buffer;
|
||||
} // saveState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Flyable::restoreState(BareNetworkString *buffer, int count)
|
||||
{
|
||||
btTransform t;
|
||||
Vec3 lv, av;
|
||||
CompressNetworkBody::decompress(buffer, &t, &lv, &av);
|
||||
|
||||
m_body->setWorldTransform(t);
|
||||
m_motion_state->setWorldTransform(t);
|
||||
m_body->setInterpolationWorldTransform(t);
|
||||
m_body->setLinearVelocity(lv);
|
||||
m_body->setAngularVelocity(av);
|
||||
m_body->setInterpolationLinearVelocity(lv);
|
||||
m_body->setInterpolationAngularVelocity(av);
|
||||
uint16_t hit_and_ticks = buffer->getUInt16();
|
||||
m_has_hit_something = (hit_and_ticks >> 15) == 1;
|
||||
m_ticks_since_thrown = hit_and_ticks & ~(1 << 15);
|
||||
if (!m_has_server_state)
|
||||
m_has_server_state = true;
|
||||
} // restoreState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Flyable::addForRewind(const std::string& uid)
|
||||
{
|
||||
SmoothNetworkBody::setEnable(true);
|
||||
SmoothNetworkBody::setSmoothRotation(false);
|
||||
SmoothNetworkBody::setAdjustVerticalOffset(false);
|
||||
Rewinder::setUniqueIdentity(uid);
|
||||
Rewinder::rewinderAdd();
|
||||
} // addForRewind
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Flyable::addRewindInfoEventFunctionAfterFiring()
|
||||
{
|
||||
if (!NetworkConfig::get()->isNetworking() ||
|
||||
NetworkConfig::get()->isServer())
|
||||
return;
|
||||
|
||||
std::shared_ptr<Flyable> f = getShared<Flyable>();
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(),
|
||||
/*undo_function*/[f]()
|
||||
{
|
||||
f->m_undo_creation = true;
|
||||
const Vec3 *min, *max;
|
||||
Track::getCurrentTrack()->getAABB(&min, &max);
|
||||
btTransform t = f->m_body->getWorldTransform();
|
||||
// Move it to (almost infinity), avoiding affecting current
|
||||
// rewinding
|
||||
t.setOrigin(*max * 2.0f);
|
||||
f->m_body->setWorldTransform(t);
|
||||
f->m_motion_state->setWorldTransform(t);
|
||||
f->m_body->setInterpolationWorldTransform(t);
|
||||
f->m_body->setGravity(Vec3(0.0f));
|
||||
},
|
||||
/*replay_function*/[f]()
|
||||
{
|
||||
f->m_undo_creation = false;
|
||||
f->m_body->setWorldTransform(f->m_saved_transform);
|
||||
f->m_motion_state->setWorldTransform(f->m_saved_transform);
|
||||
f->m_body->setInterpolationWorldTransform(f->m_saved_transform);
|
||||
f->m_body->setLinearVelocity(f->m_saved_lv);
|
||||
f->m_body->setAngularVelocity(f->m_saved_av);
|
||||
f->m_body->setInterpolationLinearVelocity(f->m_saved_lv);
|
||||
f->m_body->setInterpolationAngularVelocity(f->m_saved_av);
|
||||
f->m_body->setGravity(f->m_saved_gravity);
|
||||
f->m_ticks_since_thrown = 0;
|
||||
f->m_has_hit_something = false;
|
||||
f->additionalPhysicsProperties();
|
||||
},
|
||||
/*delete_function*/[f]()
|
||||
{
|
||||
f->m_check_created_ticks = World::getWorld()->getTicksSinceStart();
|
||||
}));
|
||||
} // addRewindInfoEventFunctionAfterFiring
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Flyable::handleUndoDestruction()
|
||||
{
|
||||
if (!NetworkConfig::get()->isNetworking() ||
|
||||
NetworkConfig::get()->isServer() ||
|
||||
m_has_undone_destruction)
|
||||
return;
|
||||
|
||||
m_has_undone_destruction = true;
|
||||
|
||||
// If destroyed during rewind, than in theroy it should be safe to delete
|
||||
// without undo
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return;
|
||||
|
||||
// We don't bother seeing the mesh during rewinding
|
||||
m_node->setVisible(false);
|
||||
std::shared_ptr<Flyable> f = getShared<Flyable>();
|
||||
std::string uid = f->getUniqueIdentity();
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(),
|
||||
/*undo_function*/[f, uid]()
|
||||
{
|
||||
projectile_manager->addByUID(uid, f);
|
||||
},
|
||||
/*replay_function*/[uid]()
|
||||
{
|
||||
projectile_manager->removeByUID(uid);
|
||||
}));
|
||||
} // handleUndoDestruction
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Flyable::computeError()
|
||||
{
|
||||
Moveable::checkSmoothing();
|
||||
if (!m_has_server_state && m_check_created_ticks != -1 &&
|
||||
World::getWorld()->getTicksSinceStart() > m_check_created_ticks)
|
||||
{
|
||||
const std::string& uid = getUniqueIdentity();
|
||||
Log::warn("Flyable", "Item %s failed to be created on server, "
|
||||
"remove it locally", uid.c_str());
|
||||
projectile_manager->removeByUID(uid);
|
||||
}
|
||||
} // computeError
|
||||
|
||||
/* EOF */
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "karts/moveable.hpp"
|
||||
#include "network/rewinder.hpp"
|
||||
#include "tracks/terrain_info.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
@ -43,7 +44,8 @@ class XMLNode;
|
||||
/**
|
||||
* \ingroup items
|
||||
*/
|
||||
class Flyable : public Moveable, public TerrainInfo
|
||||
class Flyable : public Moveable, public TerrainInfo,
|
||||
public Rewinder
|
||||
{
|
||||
public:
|
||||
private:
|
||||
@ -103,6 +105,11 @@ protected:
|
||||
/** Size of this flyable. */
|
||||
Vec3 m_extend;
|
||||
|
||||
bool m_undo_creation;
|
||||
bool m_has_undone_destruction;
|
||||
bool m_has_server_state;
|
||||
int m_check_created_ticks;
|
||||
|
||||
// The flyable class stores the values for each flyable type, e.g.
|
||||
// speed, min_height, max_height. These variables must be static,
|
||||
// so we need arrays of these variables to have different values
|
||||
@ -128,11 +135,11 @@ protected:
|
||||
|
||||
/** Time since thrown. used so a kart can't hit himself when trying
|
||||
* something, and also to put some time limit to some collectibles */
|
||||
int m_ticks_since_thrown;
|
||||
int16_t m_ticks_since_thrown;
|
||||
|
||||
/** Set to something > -1 if this flyable should auto-destrcut after
|
||||
* that may ticks. */
|
||||
int m_max_lifespan;
|
||||
int m_max_lifespan;
|
||||
|
||||
/** If set to true, the kart that throwns this flyable can't collide
|
||||
* with it for a short time. */
|
||||
@ -160,6 +167,13 @@ protected:
|
||||
const bool rotates=false,
|
||||
const bool turn_around=false,
|
||||
const btTransform* customDirection=NULL);
|
||||
|
||||
/** Used when undoing creation or destruction. */
|
||||
btTransform m_saved_transform;
|
||||
Vec3 m_saved_lv, m_saved_av, m_saved_gravity;
|
||||
|
||||
virtual void additionalPhysicsProperties() {}
|
||||
|
||||
public:
|
||||
|
||||
Flyable (AbstractKart* kart,
|
||||
@ -217,6 +231,31 @@ public:
|
||||
/** Returns the size (extend) of the mesh. */
|
||||
const Vec3 &getExtend() const { return m_extend; }
|
||||
// ------------------------------------------------------------------------
|
||||
void addForRewind(const std::string& uid);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void undoEvent(BareNetworkString *buffer) OVERRIDE {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void rewindToEvent(BareNetworkString *buffer) OVERRIDE {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void undoState(BareNetworkString *buffer) OVERRIDE {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void saveTransform() OVERRIDE { Moveable::prepareSmoothing(); }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void computeError() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void addRewindInfoEventFunctionAfterFiring();
|
||||
// ------------------------------------------------------------------------
|
||||
bool isUndoCreation() const { return m_undo_creation; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool hasUndoneDestruction() const { return m_has_undone_destruction; }
|
||||
// ------------------------------------------------------------------------
|
||||
void handleUndoDestruction();
|
||||
|
||||
}; // Flyable
|
||||
|
||||
#endif
|
||||
|
@ -43,19 +43,20 @@
|
||||
#include <string>
|
||||
|
||||
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_mesh;
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_lowres_mesh;
|
||||
std::vector<video::SColorf> ItemManager::m_glow_color;
|
||||
bool ItemManager::m_disable_item_collection = false;
|
||||
ItemManager * ItemManager::m_item_manager = NULL;
|
||||
std::mt19937 ItemManager::m_random_engine;
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_mesh;
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_lowres_mesh;
|
||||
std::vector<video::SColorf> ItemManager::m_glow_color;
|
||||
bool ItemManager::m_disable_item_collection = false;
|
||||
std::shared_ptr<ItemManager> ItemManager::m_item_manager;
|
||||
std::mt19937 ItemManager::m_random_engine;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Creates one instance of the item manager. */
|
||||
void ItemManager::create()
|
||||
{
|
||||
assert(!m_item_manager);
|
||||
m_item_manager = new ItemManager();
|
||||
// Due to protected constructor use new instead of make_shared
|
||||
m_item_manager = std::shared_ptr<ItemManager>(new ItemManager());
|
||||
} // create
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -63,8 +64,7 @@ void ItemManager::create()
|
||||
void ItemManager::destroy()
|
||||
{
|
||||
assert(m_item_manager);
|
||||
delete m_item_manager;
|
||||
m_item_manager = NULL;
|
||||
m_item_manager = nullptr;
|
||||
} // destroy
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -60,7 +60,7 @@ private:
|
||||
static std::mt19937 m_random_engine;
|
||||
protected:
|
||||
/** The instance of ItemManager while a race is on. */
|
||||
static ItemManager *m_item_manager;
|
||||
static std::shared_ptr<ItemManager> m_item_manager;
|
||||
public:
|
||||
static void loadDefaultItemMeshes();
|
||||
static void removeTextures();
|
||||
@ -90,9 +90,10 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return an instance of the item manager (it does not automatically
|
||||
* create one, call create for that). */
|
||||
static ItemManager *get() {
|
||||
static ItemManager *get()
|
||||
{
|
||||
assert(m_item_manager);
|
||||
return m_item_manager;
|
||||
return m_item_manager.get();
|
||||
} // get
|
||||
|
||||
// ========================================================================
|
||||
@ -119,9 +120,9 @@ protected:
|
||||
virtual unsigned int insertItem(Item *item);
|
||||
void setSwitchItems(const std::vector<int> &switch_items);
|
||||
ItemManager();
|
||||
public:
|
||||
virtual ~ItemManager();
|
||||
|
||||
public:
|
||||
virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal);
|
||||
virtual Item* dropNewItem (ItemState::ItemType type,
|
||||
|
@ -31,16 +31,16 @@
|
||||
void NetworkItemManager::create()
|
||||
{
|
||||
assert(!m_item_manager);
|
||||
m_item_manager = new NetworkItemManager();
|
||||
auto nim = std::shared_ptr<NetworkItemManager>(new NetworkItemManager());
|
||||
nim->rewinderAdd();
|
||||
m_item_manager = nim;
|
||||
} // create
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** Creates a new instance of the item manager. This is done at startup
|
||||
* of each race. */
|
||||
NetworkItemManager::NetworkItemManager()
|
||||
: Rewinder("N", /*can be deleted*/false),
|
||||
ItemManager()
|
||||
: Rewinder("N"), ItemManager()
|
||||
{
|
||||
m_last_confirmed_item_ticks.clear();
|
||||
|
||||
|
@ -61,10 +61,10 @@ private:
|
||||
void forwardTime(int ticks);
|
||||
|
||||
NetworkItemManager();
|
||||
virtual ~NetworkItemManager();
|
||||
|
||||
public:
|
||||
static void create();
|
||||
virtual ~NetworkItemManager();
|
||||
|
||||
void setSwitchItems(const std::vector<int> &switch_items);
|
||||
void sendItemUpdate();
|
||||
|
@ -100,7 +100,7 @@ Plunger::Plunger(AbstractKart *kart)
|
||||
{
|
||||
m_rubber_band = new RubberBand(this, kart);
|
||||
}
|
||||
m_keep_alive = -1;
|
||||
additionalPhysicsProperties();
|
||||
} // Plunger
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -47,13 +47,17 @@ private:
|
||||
btVector3 m_initial_velocity;
|
||||
|
||||
bool m_reverse_mode;
|
||||
|
||||
virtual void additionalPhysicsProperties() OVERRIDE { m_keep_alive = -1; }
|
||||
|
||||
public:
|
||||
Plunger(AbstractKart *kart);
|
||||
~Plunger();
|
||||
static void init(const XMLNode &node, scene::IMesh* missile);
|
||||
virtual bool updateAndDelete(int ticks);
|
||||
virtual void hitTrack ();
|
||||
virtual bool hit (AbstractKart *kart, PhysicalObject *obj=NULL);
|
||||
virtual bool updateAndDelete(int ticks) OVERRIDE;
|
||||
virtual void hitTrack () OVERRIDE;
|
||||
virtual bool hit (AbstractKart *kart, PhysicalObject *obj=NULL)
|
||||
OVERRIDE;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the keep-alive value. Setting it to 0 will remove the plunger
|
||||
@ -62,7 +66,7 @@ public:
|
||||
void setKeepAlive(int ticks) {m_keep_alive = ticks;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** No hit effect when it ends. */
|
||||
virtual HitEffect *getHitEffect() const {return NULL; }
|
||||
virtual HitEffect *getHitEffect() const OVERRIDE { return NULL; }
|
||||
// ------------------------------------------------------------------------
|
||||
}; // Plunger
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
@ -211,6 +212,13 @@ void Powerup::adjustSound()
|
||||
}
|
||||
} // adjustSound
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Powerup::playSound()
|
||||
{
|
||||
if (!RewindManager::get()->isRewinding())
|
||||
m_sound_use->play();
|
||||
} // playSound
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Use (fire) this powerup.
|
||||
*/
|
||||
@ -248,7 +256,7 @@ void Powerup::use()
|
||||
{
|
||||
ItemManager::get()->switchItems();
|
||||
m_sound_use->setPosition(m_kart->getXYZ());
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
break;
|
||||
}
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
@ -258,7 +266,7 @@ void Powerup::use()
|
||||
if(stk_config->m_shield_restrict_weapons)
|
||||
m_kart->setShieldTime(0.0f); // make weapon usage destroy the shield
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
|
||||
projectile_manager->newProjectile(m_kart, m_type);
|
||||
break ;
|
||||
@ -280,7 +288,7 @@ void Powerup::use()
|
||||
if(!new_item) return;
|
||||
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
}
|
||||
else // if the kart is looking forward, use the bubblegum as a shield
|
||||
{
|
||||
@ -330,7 +338,7 @@ void Powerup::use()
|
||||
//In this case this is a workaround, since the bubblegum item has two different sounds.
|
||||
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
|
||||
} // end of PowerupManager::POWERUP_BUBBLEGUM
|
||||
break;
|
||||
@ -359,7 +367,7 @@ void Powerup::use()
|
||||
else
|
||||
m_sound_use->setPosition(m_kart->getXYZ());
|
||||
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -418,7 +426,7 @@ void Powerup::use()
|
||||
m_sound_use->setPosition(m_kart->getXYZ());
|
||||
else if(player_kart)
|
||||
m_sound_use->setPosition(player_kart->getXYZ());
|
||||
m_sound_use->play();
|
||||
playSound();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -36,9 +36,6 @@ class SFXBase;
|
||||
class Powerup : public NoCopy
|
||||
{
|
||||
private:
|
||||
/** A synchronised random number generator for network games. */
|
||||
RandomGenerator m_random;
|
||||
|
||||
/** Sound effect that is being played. */
|
||||
SFXBase *m_sound_use;
|
||||
|
||||
@ -51,6 +48,7 @@ private:
|
||||
/** The owner (kart) of this powerup. */
|
||||
AbstractKart* m_kart;
|
||||
|
||||
void playSound();
|
||||
public:
|
||||
Powerup (AbstractKart* kart_);
|
||||
~Powerup ();
|
||||
|
@ -298,7 +298,7 @@ void PowerupManager::WeightsData::convertRankToSection(int rank, int *prev,
|
||||
}
|
||||
|
||||
// The last kart always uses the data for the last section
|
||||
if (rank == m_num_karts)
|
||||
if (rank == (int)m_num_karts)
|
||||
{
|
||||
*prev = *next = m_weights_for_section.size() - 1;
|
||||
*weight = 1.0f;
|
||||
@ -600,9 +600,11 @@ void PowerupManager::unitTesting()
|
||||
int num_weights = wd.m_summed_weights_for_rank[0].back();
|
||||
for(int i=0; i<num_weights; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned int n;
|
||||
assert( powerup_manager->getRandomPowerup(1, &n, i)==POWERUP_BOWLING );
|
||||
assert(n==3);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test 2: Test all possible random numbers for 5 karts and rank 5
|
||||
|
@ -139,7 +139,6 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
const int RAND_CLASS_RANGE = 1000;
|
||||
|
||||
/** The icon for each powerup. */
|
||||
Material* m_all_icons [POWERUP_MAX];
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "items/powerup.hpp"
|
||||
#include "items/rubber_ball.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
|
||||
ProjectileManager *projectile_manager=0;
|
||||
|
||||
@ -45,12 +47,6 @@ void ProjectileManager::removeTextures()
|
||||
//-----------------------------------------------------------------------------
|
||||
void ProjectileManager::cleanup()
|
||||
{
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); ++i)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
|
||||
m_active_projectiles.clear();
|
||||
for(HitEffects::iterator i = m_active_hit_effects.begin();
|
||||
i != m_active_hit_effects.end(); ++i)
|
||||
@ -68,12 +64,8 @@ void ProjectileManager::cleanup()
|
||||
*/
|
||||
void ProjectileManager::updateGraphics(float dt)
|
||||
{
|
||||
for (auto p = m_active_projectiles.begin();
|
||||
p != m_active_projectiles.end(); ++p)
|
||||
{
|
||||
(*p)->updateGraphics(dt);
|
||||
}
|
||||
|
||||
for (auto& p : m_active_projectiles)
|
||||
p.second->updateGraphics(dt);
|
||||
} // updateGraphics
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -82,6 +74,8 @@ void ProjectileManager::update(int ticks)
|
||||
{
|
||||
updateServer(ticks);
|
||||
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return;
|
||||
HitEffects::iterator he = m_active_hit_effects.begin();
|
||||
while(he!=m_active_hit_effects.end())
|
||||
{
|
||||
@ -107,24 +101,30 @@ void ProjectileManager::update(int ticks)
|
||||
/** Updates all rockets on the server (or no networking). */
|
||||
void ProjectileManager::updateServer(int ticks)
|
||||
{
|
||||
Projectiles::iterator p = m_active_projectiles.begin();
|
||||
while(p!=m_active_projectiles.end())
|
||||
auto p = m_active_projectiles.begin();
|
||||
while (p != m_active_projectiles.end())
|
||||
{
|
||||
bool can_be_deleted = (*p)->updateAndDelete(ticks);
|
||||
if(can_be_deleted)
|
||||
if (p->second->isUndoCreation())
|
||||
{
|
||||
HitEffect *he = (*p)->getHitEffect();
|
||||
if(he)
|
||||
addHitEffect(he);
|
||||
Flyable *f=*p;
|
||||
Projectiles::iterator p_next=m_active_projectiles.erase(p);
|
||||
delete f;
|
||||
p=p_next;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
bool can_be_deleted = p->second->updateAndDelete(ticks);
|
||||
if (can_be_deleted)
|
||||
{
|
||||
if (!p->second->hasUndoneDestruction())
|
||||
{
|
||||
HitEffect *he = p->second->getHitEffect();
|
||||
if (he)
|
||||
addHitEffect(he);
|
||||
}
|
||||
p->second->handleUndoDestruction();
|
||||
p = m_active_projectiles.erase(p);
|
||||
}
|
||||
else
|
||||
p++;
|
||||
} // while p!=m_active_projectiles.end()
|
||||
|
||||
|
||||
} // updateServer
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -132,20 +132,40 @@ void ProjectileManager::updateServer(int ticks)
|
||||
* \param kart The kart which shoots the projectile.
|
||||
* \param type Type of projectile.
|
||||
*/
|
||||
Flyable *ProjectileManager::newProjectile(AbstractKart *kart,
|
||||
PowerupManager::PowerupType type)
|
||||
std::shared_ptr<Flyable>
|
||||
ProjectileManager::newProjectile(AbstractKart *kart,
|
||||
PowerupManager::PowerupType type)
|
||||
{
|
||||
Flyable *f;
|
||||
const std::string& uid = getUniqueIdentity(kart, type);
|
||||
auto it = m_active_projectiles.find(uid);
|
||||
// Flyable already created during rewind
|
||||
if (it != m_active_projectiles.end())
|
||||
return it->second;
|
||||
|
||||
std::shared_ptr<Flyable> f;
|
||||
switch(type)
|
||||
{
|
||||
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
|
||||
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
|
||||
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
|
||||
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart);
|
||||
break;
|
||||
default: return NULL;
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
f = std::make_shared<Bowling>(kart);
|
||||
break;
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
f = std::make_shared<Plunger>(kart);
|
||||
break;
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
f = std::make_shared<Cake>(kart);
|
||||
break;
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
f = std::make_shared<RubberBall>(kart);
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
m_active_projectiles[uid] = f;
|
||||
if (RewindManager::get()->isEnabled())
|
||||
{
|
||||
f->addForRewind(uid);
|
||||
f->addRewindInfoEventFunctionAfterFiring();
|
||||
}
|
||||
m_active_projectiles.push_back(f);
|
||||
return f;
|
||||
} // newProjectile
|
||||
|
||||
@ -158,13 +178,15 @@ Flyable *ProjectileManager::newProjectile(AbstractKart *kart,
|
||||
bool ProjectileManager::projectileIsClose(const AbstractKart * const kart,
|
||||
float radius)
|
||||
{
|
||||
float r2 = radius*radius;
|
||||
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); i++)
|
||||
float r2 = radius * radius;
|
||||
for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end();
|
||||
i++)
|
||||
{
|
||||
float dist2 = (*i)->getXYZ().distance2(kart->getXYZ());
|
||||
if(dist2<r2) return true;
|
||||
if (i->second->isUndoCreation())
|
||||
continue;
|
||||
float dist2 = i->second->getXYZ().distance2(kart->getXYZ());
|
||||
if (dist2 < r2)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // projectileIsClose
|
||||
@ -179,21 +201,101 @@ bool ProjectileManager::projectileIsClose(const AbstractKart * const kart,
|
||||
int ProjectileManager::getNearbyProjectileCount(const AbstractKart * const kart,
|
||||
float radius, PowerupManager::PowerupType type)
|
||||
{
|
||||
float r2 = radius*radius;
|
||||
int projectileCount = 0;
|
||||
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); i++)
|
||||
float r2 = radius * radius;
|
||||
int projectile_count = 0;
|
||||
for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end();
|
||||
i++)
|
||||
{
|
||||
if ((*i)->getType() == type)
|
||||
if (i->second->isUndoCreation())
|
||||
continue;
|
||||
if (i->second->getType() == type)
|
||||
{
|
||||
float dist2 = (*i)->getXYZ().distance2(kart->getXYZ());
|
||||
if(dist2<r2)
|
||||
float dist2 = i->second->getXYZ().distance2(kart->getXYZ());
|
||||
if (dist2 < r2)
|
||||
{
|
||||
|
||||
projectileCount++;
|
||||
projectile_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return projectileCount;
|
||||
return projectile_count;
|
||||
} // getNearbyProjectileCount
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
std::string ProjectileManager::getUniqueIdentity(AbstractKart* kart,
|
||||
PowerupManager::PowerupType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
return std::string("B_") +
|
||||
StringUtils::toString(kart->getWorldKartId()) + "_" +
|
||||
StringUtils::toString(World::getWorld()->getTicksSinceStart());
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
return std::string("P_") +
|
||||
StringUtils::toString(kart->getWorldKartId()) + "_" +
|
||||
StringUtils::toString(World::getWorld()->getTicksSinceStart());
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
return std::string("C_") +
|
||||
StringUtils::toString(kart->getWorldKartId()) + "_" +
|
||||
StringUtils::toString(World::getWorld()->getTicksSinceStart());
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
return std::string("R_") +
|
||||
StringUtils::toString(kart->getWorldKartId()) + "_" +
|
||||
StringUtils::toString(World::getWorld()->getTicksSinceStart());
|
||||
default:
|
||||
assert(false);
|
||||
return "";
|
||||
}
|
||||
} // getUniqueIdentity
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
std::shared_ptr<Rewinder>
|
||||
ProjectileManager::addRewinderFromNetworkState(const std::string& uid)
|
||||
{
|
||||
std::vector<std::string> id = StringUtils::split(uid, '_');
|
||||
if (id.size() != 3)
|
||||
return nullptr;
|
||||
if (!(id[0] == "B" || id[0] == "P" || id[0] == "C" || id[0] == "R"))
|
||||
return nullptr;
|
||||
int world_id = -1;
|
||||
if (!StringUtils::fromString(id[1], world_id))
|
||||
return nullptr;
|
||||
AbstractKart* kart = World::getWorld()->getKart(world_id);
|
||||
char first_id = id[0][0];
|
||||
Log::debug("ProjectileManager", "Missed a firing event or locally deleted,"
|
||||
" add the flyable %s manually", uid.c_str());
|
||||
switch (first_id)
|
||||
{
|
||||
case 'B':
|
||||
{
|
||||
auto f = std::make_shared<Bowling>(kart);
|
||||
f->addForRewind(uid);
|
||||
m_active_projectiles[uid] = f;
|
||||
return f;
|
||||
}
|
||||
case 'P':
|
||||
{
|
||||
auto f = std::make_shared<Plunger>(kart);
|
||||
f->addForRewind(uid);
|
||||
m_active_projectiles[uid] = f;
|
||||
return f;
|
||||
}
|
||||
case 'C':
|
||||
{
|
||||
auto f = std::make_shared<Cake>(kart);
|
||||
f->addForRewind(uid);
|
||||
m_active_projectiles[uid] = f;
|
||||
return f;
|
||||
}
|
||||
case 'R':
|
||||
{
|
||||
auto f = std::make_shared<RubberBall>(kart);
|
||||
f->addForRewind(uid);
|
||||
m_active_projectiles[uid] = f;
|
||||
return f;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
} // addProjectileFromNetworkState
|
||||
|
@ -19,6 +19,8 @@
|
||||
#ifndef HEADER_PROJECTILEMANAGER_HPP
|
||||
#define HEADER_PROJECTILEMANAGER_HPP
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace irr
|
||||
@ -32,6 +34,7 @@ namespace irr
|
||||
class AbstractKart;
|
||||
class Flyable;
|
||||
class HitEffect;
|
||||
class Rewinder;
|
||||
class Track;
|
||||
class Vec3;
|
||||
|
||||
@ -41,17 +44,18 @@ class Vec3;
|
||||
class ProjectileManager : public NoCopy
|
||||
{
|
||||
private:
|
||||
typedef std::vector<Flyable*> Projectiles;
|
||||
typedef std::vector<HitEffect*> HitEffects;
|
||||
|
||||
/** The list of all active projectiles, i.e. projectiles which are
|
||||
* currently moving on the track. */
|
||||
Projectiles m_active_projectiles;
|
||||
std::map<std::string, std::shared_ptr<Flyable> > m_active_projectiles;
|
||||
|
||||
/** All active hit effects, i.e. hit effects which are currently
|
||||
* being shown or have a sfx playing. */
|
||||
HitEffects m_active_hit_effects;
|
||||
|
||||
std::string getUniqueIdentity(AbstractKart* kart,
|
||||
PowerupManager::PowerupType type);
|
||||
void updateServer(int ticks);
|
||||
public:
|
||||
ProjectileManager() {}
|
||||
@ -60,9 +64,6 @@ public:
|
||||
void cleanup ();
|
||||
void update (int ticks);
|
||||
void updateGraphics (float dt);
|
||||
Flyable* newProjectile (AbstractKart *kart,
|
||||
PowerupManager::PowerupType type);
|
||||
void Deactivate (Flyable *p) {}
|
||||
void removeTextures ();
|
||||
bool projectileIsClose(const AbstractKart * const kart,
|
||||
float radius);
|
||||
@ -74,6 +75,19 @@ public:
|
||||
* \param hit_effect The hit effect to be added. */
|
||||
void addHitEffect(HitEffect *hit_effect)
|
||||
{ m_active_hit_effects.push_back(hit_effect); }
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<Rewinder>
|
||||
addRewinderFromNetworkState(const std::string& uid);
|
||||
// ------------------------------------------------------------------------
|
||||
std::shared_ptr<Flyable> newProjectile(AbstractKart *kart,
|
||||
PowerupManager::PowerupType type);
|
||||
// ------------------------------------------------------------------------
|
||||
void addByUID(const std::string& uid, std::shared_ptr<Flyable> f)
|
||||
{ m_active_projectiles[uid] = f; }
|
||||
// ------------------------------------------------------------------------
|
||||
void removeByUID(const std::string& uid)
|
||||
{ m_active_projectiles.erase(uid); }
|
||||
|
||||
};
|
||||
|
||||
extern ProjectileManager *projectile_manager;
|
||||
|
@ -89,7 +89,7 @@ AbstractKartAnimation::~AbstractKartAnimation()
|
||||
Vec3 linear_velocity = kart->getBody()->getLinearVelocity();
|
||||
Vec3 angular_velocity = kart->getBody()->getAngularVelocity();
|
||||
btTransform transform = kart->getBody()->getWorldTransform();
|
||||
RewindManager::get()->getRewindQueue().insertRewindInfo(new
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(
|
||||
World::getWorld()->getTicksSinceStart(),
|
||||
[kart]()
|
||||
|
@ -91,6 +91,7 @@
|
||||
|
||||
#include <algorithm> // for min and max
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
@ -129,7 +130,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
|
||||
m_bubblegum_ticks = 0;
|
||||
m_bubblegum_torque = 0.0f;
|
||||
m_invulnerable_ticks = 0;
|
||||
m_squash_ticks = 0;
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
|
||||
m_shadow = NULL;
|
||||
m_wheel_box = NULL;
|
||||
@ -366,7 +367,7 @@ void Kart::reset()
|
||||
m_bubblegum_ticks = 0;
|
||||
m_bubblegum_torque = 0.0f;
|
||||
m_invulnerable_ticks = 0;
|
||||
m_squash_ticks = 0;
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
m_collected_energy = 0;
|
||||
m_has_started = false;
|
||||
@ -1275,34 +1276,12 @@ void Kart::update(int ticks)
|
||||
// Reset any instand speed increase in the bullet kart
|
||||
m_vehicle->setMinSpeed(0);
|
||||
|
||||
if(m_squash_ticks>=0)
|
||||
{
|
||||
m_squash_ticks-=ticks;
|
||||
// If squasing time ends, reset the model
|
||||
if(m_squash_ticks<=0)
|
||||
{
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
scene::ISceneNode* node =
|
||||
m_kart_model->getAnimatedNode() ?
|
||||
m_kart_model->getAnimatedNode() : m_node;
|
||||
if (m_vehicle->getNumWheels() > 0)
|
||||
{
|
||||
scene::ISceneNode **wheels = m_kart_model->getWheelNodes();
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); ++i)
|
||||
{
|
||||
if (wheels[i])
|
||||
wheels[i]->setParent(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if squashed
|
||||
|
||||
if (m_bubblegum_ticks > 0.0f)
|
||||
if (m_bubblegum_ticks > 0)
|
||||
{
|
||||
m_bubblegum_ticks -= ticks;
|
||||
if (m_bubblegum_ticks <= 0.0f)
|
||||
if (m_bubblegum_ticks <= 0)
|
||||
{
|
||||
m_bubblegum_torque = 0.0f;
|
||||
m_bubblegum_torque = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1752,23 +1731,42 @@ void Kart::setSquash(float time, float slowdown)
|
||||
ExplosionAnimation::create(this);
|
||||
return;
|
||||
}
|
||||
m_node->setScale(core::vector3df(1.0f, 0.5f, 1.0f));
|
||||
|
||||
m_max_speed->setSlowdown(MaxSpeed::MS_DECREASE_SQUASH, slowdown,
|
||||
stk_config->time2Ticks(0.1f),
|
||||
stk_config->time2Ticks(time));
|
||||
if (m_vehicle->getNumWheels() > 0)
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_squash_time == std::numeric_limits<float>::max())
|
||||
{
|
||||
if (!m_wheel_box)
|
||||
m_wheel_box = irr_driver->getSceneManager()->addDummyTransformationSceneNode(m_node);
|
||||
scene::ISceneNode **wheels = m_kart_model->getWheelNodes();
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); ++i)
|
||||
m_node->setScale(core::vector3df(1.0f, 0.5f, 1.0f));
|
||||
if (m_vehicle->getNumWheels() > 0)
|
||||
{
|
||||
if (wheels[i])
|
||||
wheels[i]->setParent(m_wheel_box);
|
||||
if (!m_wheel_box)
|
||||
{
|
||||
m_wheel_box = irr_driver->getSceneManager()
|
||||
->addDummyTransformationSceneNode(m_node);
|
||||
}
|
||||
scene::ISceneNode **wheels = m_kart_model->getWheelNodes();
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); i++)
|
||||
{
|
||||
if (wheels[i])
|
||||
wheels[i]->setParent(m_wheel_box);
|
||||
}
|
||||
m_wheel_box->getRelativeTransformationMatrix()
|
||||
.setScale(core::vector3df(1.0f, 2.0f, 1.0f));
|
||||
}
|
||||
m_wheel_box->getRelativeTransformationMatrix().setScale(core::vector3df(1.0f, 2.0f, 1.0f));
|
||||
m_squash_time = time;
|
||||
}
|
||||
m_squash_ticks = stk_config->time2Ticks(time);
|
||||
#endif
|
||||
} // setSquash
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns if the kart is currently being squashed
|
||||
*/
|
||||
bool Kart::isSquashed() const
|
||||
{
|
||||
return m_max_speed->isSpeedDecreaseActive(MaxSpeed::MS_DECREASE_SQUASH);
|
||||
} // setSquash
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2941,6 +2939,30 @@ void Kart::updateGraphics(float dt)
|
||||
if (m_custom_sounds[n] != NULL) m_custom_sounds[n]->position(getXYZ());
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_squash_time != std::numeric_limits<float>::max())
|
||||
{
|
||||
m_squash_time -= dt;
|
||||
// If squasing time ends, reset the model
|
||||
if (m_squash_time <= 0.0f)
|
||||
{
|
||||
m_squash_time = std::numeric_limits<float>::max();
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
scene::ISceneNode* node =
|
||||
m_kart_model->getAnimatedNode() ?
|
||||
m_kart_model->getAnimatedNode() : m_node;
|
||||
if (m_vehicle->getNumWheels() > 0)
|
||||
{
|
||||
scene::ISceneNode **wheels = m_kart_model->getWheelNodes();
|
||||
for (int i = 0; i < 4 && i < m_vehicle->getNumWheels(); ++i)
|
||||
{
|
||||
if (wheels[i])
|
||||
wheels[i]->setParent(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if squashed
|
||||
|
||||
for (int i = 0; i < EMITTER_COUNT; i++)
|
||||
m_emitters[i]->setPosition(getXYZ());
|
||||
m_skid_sound->setPosition(getXYZ());
|
||||
|
@ -160,17 +160,17 @@ protected:
|
||||
int m_bounce_back_ticks;
|
||||
|
||||
/** Time a kart is invulnerable. */
|
||||
int m_invulnerable_ticks;
|
||||
int16_t m_invulnerable_ticks;
|
||||
|
||||
/** How long a kart is being squashed. If this is >0
|
||||
* the kart is squashed. */
|
||||
int m_squash_ticks;
|
||||
float m_squash_time;
|
||||
|
||||
/** Current leaning of the kart. */
|
||||
float m_current_lean;
|
||||
|
||||
/** If > 0 then bubble gum effect is on. This is the sliding when hitting a gum on the floor, not the shield. */
|
||||
int m_bubblegum_ticks;
|
||||
int16_t m_bubblegum_ticks;
|
||||
|
||||
/** The torque to apply after hitting a bubble gum. */
|
||||
float m_bubblegum_torque;
|
||||
@ -218,13 +218,10 @@ 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. */
|
||||
int m_view_blocked_by_plunger;
|
||||
int16_t m_view_blocked_by_plunger;
|
||||
/** The current speed (i.e. length of velocity vector) of this kart. */
|
||||
float m_speed;
|
||||
/** For camera handling an exponentially smoothened value is used, which
|
||||
* reduces stuttering of the camera. */
|
||||
float m_smoothed_speed;
|
||||
|
||||
|
||||
/** For smoothing engine sound**/
|
||||
float m_last_factor_engine_sound;
|
||||
|
||||
@ -499,7 +496,7 @@ public:
|
||||
virtual bool isOnMinNitroTime() const OVERRIDE { return m_min_nitro_ticks > 0; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the kart is currently being squashed. */
|
||||
virtual bool isSquashed() const OVERRIDE { return m_squash_ticks >0; }
|
||||
virtual bool isSquashed() const OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Shows the star effect for a certain time. */
|
||||
virtual void showStarEffect(float t) OVERRIDE;
|
||||
|
@ -38,8 +38,7 @@ KartRewinder::KartRewinder(const std::string& ident,
|
||||
const btTransform& init_transform,
|
||||
PerPlayerDifficulty difficulty,
|
||||
std::shared_ptr<RenderInfo> ri)
|
||||
: Rewinder(std::string("K") + StringUtils::toString(world_kart_id),
|
||||
/*can_be_destroyed*/ false)
|
||||
: Rewinder(std::string("K") + StringUtils::toString(world_kart_id))
|
||||
, Kart(ident, world_kart_id, position, init_transform, difficulty,
|
||||
ri)
|
||||
{
|
||||
@ -144,6 +143,15 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
// -----------
|
||||
m_skidding->saveState(buffer);
|
||||
|
||||
// 6) Firing and related handling
|
||||
// -----------
|
||||
buffer->addUInt16(m_bubblegum_ticks);
|
||||
buffer->addUInt16(m_view_blocked_by_plunger);
|
||||
// m_invulnerable_ticks will not be negative
|
||||
uint16_t fire_and_invulnerable = (m_fire_clicked ? 1 << 15 : 0) |
|
||||
m_invulnerable_ticks;
|
||||
buffer->addUInt16(fire_and_invulnerable);
|
||||
|
||||
return buffer;
|
||||
} // saveState
|
||||
|
||||
@ -203,15 +211,21 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
float nitro = buffer->getFloat();
|
||||
setEnergy(nitro);
|
||||
|
||||
// 5) Max speed info
|
||||
// 4) Max speed info
|
||||
// ------------------
|
||||
m_max_speed->rewindTo(buffer);
|
||||
|
||||
// 6) Skidding
|
||||
// 5) Skidding
|
||||
// -----------
|
||||
m_skidding->rewindTo(buffer);
|
||||
|
||||
return;
|
||||
// 6) Firing and related handling
|
||||
// -----------
|
||||
m_bubblegum_ticks = buffer->getUInt16();
|
||||
m_view_blocked_by_plunger = buffer->getUInt16();
|
||||
uint16_t fire_and_invulnerable = buffer->getUInt16();
|
||||
m_fire_clicked = (fire_and_invulnerable >> 15) == 1;
|
||||
m_invulnerable_ticks = fire_and_invulnerable & ~(1 << 15);
|
||||
} // restoreState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -223,25 +237,16 @@ void KartRewinder::update(int ticks)
|
||||
Kart::update(ticks);
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void KartRewinder::rewindToEvent(BareNetworkString *buffer)
|
||||
{
|
||||
} // rewindToEvent
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::function<void()> KartRewinder::getLocalStateRestoreFunction()
|
||||
{
|
||||
if (m_eliminated)
|
||||
return nullptr;
|
||||
|
||||
// In theory all ticks / boolean related stuff can be saved locally
|
||||
// Variable can be saved locally if its adjustment only depends on the kart
|
||||
// itself
|
||||
bool has_started = m_has_started;
|
||||
int bubblegum_ticks = m_bubblegum_ticks;
|
||||
int bounce_back_ticks = m_bounce_back_ticks;
|
||||
int invulnerable_ticks = m_invulnerable_ticks;
|
||||
int squash_ticks = m_squash_ticks;
|
||||
bool fire_clicked = m_fire_clicked;
|
||||
int view_blocked_by_plunger = m_view_blocked_by_plunger;
|
||||
int brake_ticks = m_brake_ticks;
|
||||
int8_t min_nitro_ticks = m_min_nitro_ticks;
|
||||
|
||||
@ -259,18 +264,11 @@ std::function<void()> KartRewinder::getLocalStateRestoreFunction()
|
||||
steer_val_r = pc->m_steer_val_r;
|
||||
}
|
||||
|
||||
return [has_started, bubblegum_ticks, bounce_back_ticks,
|
||||
invulnerable_ticks, squash_ticks, fire_clicked,
|
||||
view_blocked_by_plunger, brake_ticks, min_nitro_ticks, initial_speed,
|
||||
node_scale, steer_val_l, steer_val_r, this]()
|
||||
return [has_started, bounce_back_ticks, brake_ticks, min_nitro_ticks,
|
||||
initial_speed, node_scale, steer_val_l, steer_val_r, this]()
|
||||
{
|
||||
m_has_started = has_started;
|
||||
m_bubblegum_ticks = bubblegum_ticks;
|
||||
m_bounce_back_ticks = bounce_back_ticks;
|
||||
m_invulnerable_ticks = invulnerable_ticks;
|
||||
m_squash_ticks = squash_ticks;
|
||||
m_fire_clicked = fire_clicked;
|
||||
m_view_blocked_by_plunger = view_blocked_by_plunger;
|
||||
m_brake_ticks = brake_ticks;
|
||||
m_min_nitro_ticks = min_nitro_ticks;
|
||||
getAttachment()->setInitialSpeed(initial_speed);
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
OVERRIDE;
|
||||
void reset() OVERRIDE;
|
||||
virtual void restoreState(BareNetworkString *p, int count) OVERRIDE;
|
||||
virtual void rewindToEvent(BareNetworkString *p) OVERRIDE;
|
||||
virtual void rewindToEvent(BareNetworkString *p) OVERRIDE {}
|
||||
virtual void update(int ticks) OVERRIDE;
|
||||
// -------------------------------------------------------------------------
|
||||
virtual float getSteerPercent() const OVERRIDE
|
||||
|
@ -280,6 +280,15 @@ int MaxSpeed::getSpeedIncreaseTicksLeft(unsigned int category)
|
||||
return m_speed_increase[category].getTimeLeft();
|
||||
} // getSpeedIncreaseTimeLeft
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns if decreased speed is active in the given category.
|
||||
* \param category Which category to report on.
|
||||
*/
|
||||
int MaxSpeed::isSpeedDecreaseActive(unsigned int category)
|
||||
{
|
||||
return m_speed_decrease[category].isActive();
|
||||
} // isSpeedDecreaseActive
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates all speed increase and decrease objects, and determines the
|
||||
* current maximum speed. Note that the function can be called with
|
||||
|
@ -158,11 +158,13 @@ private:
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns the current slowdown fracftion, taking a 'fade in'
|
||||
* into account. */
|
||||
float getSlowdownFraction() const {return m_current_fraction;}
|
||||
float getSlowdownFraction() const { return m_current_fraction; }
|
||||
// --------------------------------------------------------------------
|
||||
int getTimeLeft() const { return m_duration; }
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns if this speed decrease is active atm. A duration of
|
||||
* -1 indicates an ongoing effect. */
|
||||
bool isActive() const { return m_duration > 0 || m_duration <= -1.0f; }
|
||||
bool isActive() const { return m_duration > 0 || m_duration <= -1; }
|
||||
}; // SpeedDecrease
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -188,6 +190,7 @@ public:
|
||||
void setSlowdown(unsigned int category, float max_speed_fraction,
|
||||
int fade_in_time, int duration=-1);
|
||||
int getSpeedIncreaseTicksLeft(unsigned int category);
|
||||
int isSpeedDecreaseActive(unsigned int category);
|
||||
void update(int ticks);
|
||||
void reset();
|
||||
void saveState(BareNetworkString *buffer) const;
|
||||
|
@ -176,7 +176,7 @@ void LinearWorld::update(int ticks)
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
KartInfo& kart_info = m_kart_info[n];
|
||||
AbstractKart* kart = m_karts[n];
|
||||
AbstractKart* kart = m_karts[n].get();
|
||||
|
||||
// Nothing to do for karts that are currently being
|
||||
// rescued or eliminated
|
||||
@ -218,7 +218,7 @@ void LinearWorld::update(int ticks)
|
||||
// Update the estimated finish time.
|
||||
// This is used by the AI
|
||||
m_kart_info[i].m_estimated_finish =
|
||||
estimateFinishTimeForKart(m_karts[i]);
|
||||
estimateFinishTimeForKart(m_karts[i].get());
|
||||
}
|
||||
// If one player and a ghost, or two compared ghosts,
|
||||
// compute the live time difference
|
||||
@ -328,7 +328,7 @@ void LinearWorld::updateLiveDifference()
|
||||
void LinearWorld::newLap(unsigned int kart_index)
|
||||
{
|
||||
KartInfo &kart_info = m_kart_info[kart_index];
|
||||
AbstractKart *kart = m_karts[kart_index];
|
||||
AbstractKart *kart = m_karts[kart_index].get();
|
||||
|
||||
// Reset reset-after-lap achievements
|
||||
PlayerProfile *p = PlayerManager::getCurrentPlayer();
|
||||
@ -556,7 +556,7 @@ void LinearWorld::getKartsDisplayInfo(
|
||||
for(unsigned int i = 0; i < kart_amount ; i++)
|
||||
{
|
||||
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];
|
||||
AbstractKart* kart = m_karts[i];
|
||||
AbstractKart* kart = m_karts[i].get();
|
||||
|
||||
// reset color
|
||||
rank_info.m_color = video::SColor(255, 255, 255, 255);
|
||||
@ -585,7 +585,7 @@ void LinearWorld::getKartsDisplayInfo(
|
||||
{
|
||||
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];
|
||||
KartInfo& kart_info = m_kart_info[i];
|
||||
AbstractKart* kart = m_karts[i];
|
||||
AbstractKart* kart = m_karts[i].get();
|
||||
|
||||
const int position = kart->getPosition();
|
||||
|
||||
@ -799,7 +799,7 @@ void LinearWorld::updateRacePosition()
|
||||
// so that debug output is still correct!!!!!!!!!!!
|
||||
for (unsigned int i=0; i<kart_amount; i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
AbstractKart* kart = m_karts[i].get();
|
||||
// Karts that are either eliminated or have finished the
|
||||
// race already have their (final) position assigned. If
|
||||
// these karts would get their rank updated, it could happen
|
||||
@ -898,7 +898,7 @@ void LinearWorld::updateRacePosition()
|
||||
Log::debug("[LinearWorld]", "Counting laps at %u seconds.", getTime());
|
||||
for (unsigned int i=0; i<kart_amount; i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
AbstractKart* kart = m_karts[i].get();
|
||||
Log::debug("[LinearWorld]", "counting karts ahead of %s (laps %u,"
|
||||
" progress %u, finished %d, eliminated %d, initial position %u.",
|
||||
kart->getIdent().c_str(),
|
||||
@ -973,7 +973,7 @@ void LinearWorld::checkForWrongDirection(unsigned int i, float dt)
|
||||
|
||||
KartInfo &ki = m_kart_info[i];
|
||||
|
||||
const AbstractKart *kart=m_karts[i];
|
||||
const AbstractKart *kart=m_karts[i].get();
|
||||
// If the kart can go in more than one directions from the current track
|
||||
// don't do any reverse message handling, since it is likely that there
|
||||
// will be one direction in which it isn't going backwards anyway.
|
||||
|
@ -103,19 +103,18 @@ void ProfileWorld::setProfileModeLaps(int laps)
|
||||
* this player globally (i.e. including network players).
|
||||
* \param init_pos The start XYZ coordinates.
|
||||
*/
|
||||
AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
std::shared_ptr<AbstractKart> ProfileWorld::createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType kart_type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
{
|
||||
btTransform init_pos = getStartTransform(index);
|
||||
|
||||
Kart *new_kart = new KartWithStats(kart_ident,
|
||||
/*world kart id*/ index,
|
||||
/*position*/ index+1,
|
||||
init_pos, difficulty);
|
||||
std::shared_ptr<KartWithStats> new_kart =
|
||||
std::make_shared<KartWithStats>(kart_ident, /*world kart id*/ index,
|
||||
/*position*/ index + 1, init_pos, difficulty);
|
||||
new_kart->init(RaceManager::KT_AI);
|
||||
Controller *controller = loadAIController(new_kart);
|
||||
Controller *controller = loadAIController(new_kart.get());
|
||||
new_kart->setController(controller);
|
||||
|
||||
// Create a camera for the last kart (since this way more of the
|
||||
@ -123,7 +122,7 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index,
|
||||
if (index == (int)race_manager->getNumberOfKarts()-1)
|
||||
{
|
||||
// The camera keeps track of all cameras and will free them
|
||||
Camera::createCamera(new_kart, local_player_id);
|
||||
Camera::createCamera(new_kart.get(), local_player_id);
|
||||
}
|
||||
return new_kart;
|
||||
} // createKart
|
||||
@ -197,7 +196,7 @@ void ProfileWorld::enterRaceOverState()
|
||||
// ---------- update rank ------
|
||||
if (m_karts[i]->hasFinishedRace() || m_karts[i]->isEliminated())
|
||||
continue;
|
||||
m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i]));
|
||||
m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i].get()));
|
||||
}
|
||||
|
||||
// Print framerate statistics
|
||||
@ -229,9 +228,9 @@ void ProfileWorld::enterRaceOverState()
|
||||
|
||||
std::set<std::string> all_groups;
|
||||
|
||||
for ( KartList::size_type i = 0; i < m_karts.size(); ++i)
|
||||
for (KartList::size_type i = 0; i < m_karts.size(); ++i)
|
||||
{
|
||||
KartWithStats* kart = dynamic_cast<KartWithStats*>(m_karts[i]);
|
||||
auto kart = std::dynamic_pointer_cast<KartWithStats>(m_karts[i]);
|
||||
|
||||
max_t = std::max(max_t, kart->getFinishTime());
|
||||
min_t = std::min(min_t, kart->getFinishTime());
|
||||
@ -285,7 +284,7 @@ void ProfileWorld::enterRaceOverState()
|
||||
float av_time = 0.0f, energy = 0;
|
||||
for ( unsigned int i = 0; i < (unsigned int)m_karts.size(); ++i)
|
||||
{
|
||||
KartWithStats* kart = dynamic_cast<KartWithStats*>(m_karts[i]);
|
||||
auto kart = std::dynamic_pointer_cast<KartWithStats>(m_karts[i]);
|
||||
const std::string &name=kart->getController()->getControllerName();
|
||||
if(name!=*it)
|
||||
continue;
|
||||
|
@ -72,10 +72,10 @@ protected:
|
||||
* used by DemoWorld. */
|
||||
static int m_num_laps;
|
||||
|
||||
virtual AbstractKart *createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty);
|
||||
virtual std::shared_ptr<AbstractKart> createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty);
|
||||
|
||||
public:
|
||||
ProfileWorld();
|
||||
|
@ -228,7 +228,7 @@ void SoccerWorld::update(int ticks)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
auto& kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
kart->getBody()->setLinearVelocity(Vec3(0.0f));
|
||||
@ -335,7 +335,7 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
|
||||
}
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
auto& kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
kart->getBody()->setLinearVelocity(Vec3(0.0f));
|
||||
@ -356,7 +356,7 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns)
|
||||
"%d when reset player", ticks_back_to_own_goal, ticks_now);
|
||||
return;
|
||||
}
|
||||
RewindManager::get()->getRewindQueue().insertRewindInfo(new
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(ticks_back_to_own_goal,
|
||||
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
|
||||
|
||||
@ -406,7 +406,7 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
|
||||
m_ball->setEnabled(false);
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
auto& kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
btTransform transform_now = kart->getBody()->getWorldTransform();
|
||||
@ -416,7 +416,7 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns)
|
||||
kart->setTrans(transform_now);
|
||||
m_goal_transforms[i] = transform_now;
|
||||
}
|
||||
RewindManager::get()->getRewindQueue().insertRewindInfo(new
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(ticks_back_to_own_goal,
|
||||
[](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this)));
|
||||
|
||||
@ -431,7 +431,7 @@ void SoccerWorld::resetKartsToSelfGoals()
|
||||
setPhase(WorldStatus::RACE_PHASE);
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
auto& kart = m_karts[i];
|
||||
if (kart->isEliminated())
|
||||
continue;
|
||||
|
||||
@ -439,7 +439,7 @@ void SoccerWorld::resetKartsToSelfGoals()
|
||||
kart->getBody()->setAngularVelocity(Vec3(0.0f));
|
||||
unsigned index = m_kart_position_map.at(kart->getWorldKartId());
|
||||
btTransform t = Track::getCurrentTrack()->getStartTransform(index);
|
||||
moveKartTo(kart, t);
|
||||
moveKartTo(kart.get(), t);
|
||||
}
|
||||
} // resetKartsToSelfGoals
|
||||
|
||||
@ -532,10 +532,10 @@ bool SoccerWorld::getKartSoccerResult(unsigned int kart_id) const
|
||||
} // getKartSoccerResult
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType kart_type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
std::shared_ptr<AbstractKart> SoccerWorld::createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType kart_type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
{
|
||||
int cur_red = getTeamNum(SOCCER_TEAM_RED);
|
||||
int cur_blue = getTeamNum(SOCCER_TEAM_BLUE);
|
||||
@ -590,16 +590,19 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
|
||||
std::shared_ptr<RenderInfo> ri = std::make_shared<RenderInfo>();
|
||||
ri = (team == SOCCER_TEAM_BLUE ? std::make_shared<RenderInfo>(0.66f) :
|
||||
std::make_shared<RenderInfo>(1.0f));
|
||||
AbstractKart* new_kart;
|
||||
|
||||
std::shared_ptr<AbstractKart> new_kart;
|
||||
if (RewindManager::get()->isEnabled())
|
||||
{
|
||||
new_kart = new KartRewinder(kart_ident, index, position, init_pos,
|
||||
difficulty, ri);
|
||||
auto kr = std::make_shared<KartRewinder>(kart_ident, index, position,
|
||||
init_pos, difficulty, ri);
|
||||
kr->rewinderAdd();
|
||||
new_kart = kr;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_kart = new Kart(kart_ident, index, position, init_pos, difficulty,
|
||||
ri);
|
||||
new_kart = std::make_shared<Kart>(kart_ident, index, position,
|
||||
init_pos, difficulty, ri);
|
||||
}
|
||||
|
||||
new_kart->init(race_manager->getKartType(index));
|
||||
@ -608,18 +611,18 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
|
||||
switch(kart_type)
|
||||
{
|
||||
case RaceManager::KT_PLAYER:
|
||||
controller = new LocalPlayerController(new_kart, local_player_id,
|
||||
controller = new LocalPlayerController(new_kart.get(), local_player_id,
|
||||
difficulty);
|
||||
m_num_players ++;
|
||||
break;
|
||||
case RaceManager::KT_NETWORK_PLAYER:
|
||||
controller = new NetworkPlayerController(new_kart);
|
||||
controller = new NetworkPlayerController(new_kart.get());
|
||||
if (!online_name.empty())
|
||||
new_kart->setOnScreenText(online_name.c_str());
|
||||
m_num_players++;
|
||||
break;
|
||||
case RaceManager::KT_AI:
|
||||
controller = loadAIController(new_kart);
|
||||
controller = loadAIController(new_kart.get());
|
||||
break;
|
||||
case RaceManager::KT_GHOST:
|
||||
break;
|
||||
|
@ -51,10 +51,10 @@ public:
|
||||
}; // ScorerData
|
||||
|
||||
protected:
|
||||
virtual AbstractKart *createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty) OVERRIDE;
|
||||
virtual std::shared_ptr<AbstractKart> createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty) OVERRIDE;
|
||||
|
||||
private:
|
||||
class KartDistanceMap
|
||||
|
@ -103,7 +103,7 @@ void StandardRace::endRaceEarly()
|
||||
for (unsigned int i = 1; i <= kart_amount; i++)
|
||||
{
|
||||
int kartid = m_position_index[i-1];
|
||||
AbstractKart* kart = m_karts[kartid];
|
||||
AbstractKart* kart = m_karts[kartid].get();
|
||||
|
||||
if (kart->hasFinishedRace())
|
||||
{
|
||||
@ -140,7 +140,7 @@ void StandardRace::endRaceEarly()
|
||||
int kartid = active_players[i];
|
||||
int position = getNumKarts() - (int) active_players.size() + 1 + i;
|
||||
setKartPosition(kartid, position);
|
||||
float punished_time = estimateFinishTimeForKart(m_karts[kartid])
|
||||
float punished_time = estimateFinishTimeForKart(m_karts[kartid].get())
|
||||
+ worse_finish_time - WorldStatus::getTime();
|
||||
m_karts[kartid]->finishedRace(punished_time);
|
||||
|
||||
|
@ -722,18 +722,18 @@ void ThreeStrikesBattle::loadCustomModels()
|
||||
// Now add them
|
||||
for (unsigned int i = 0; i < pos.size(); i++)
|
||||
{
|
||||
AbstractKart* sta = new Kart(sta_list[i], (int)m_karts.size(),
|
||||
auto sta = std::make_shared<Kart>(sta_list[i], (int)m_karts.size(),
|
||||
(int)m_karts.size() + 1, pos[i], PLAYER_DIFFICULTY_NORMAL,
|
||||
std::make_shared<RenderInfo>(1.0f));
|
||||
sta->init(RaceManager::KartType::KT_SPARE_TIRE);
|
||||
sta->setController(new SpareTireAI(sta));
|
||||
sta->setController(new SpareTireAI(sta.get()));
|
||||
|
||||
m_karts.push_back(sta);
|
||||
race_manager->addSpareTireKart(sta_list[i]);
|
||||
|
||||
// Copy STA pointer to m_spare_tire_karts array, allowing them
|
||||
// to respawn easily
|
||||
m_spare_tire_karts.push_back(sta);
|
||||
m_spare_tire_karts.push_back(sta.get());
|
||||
}
|
||||
unsigned int sta_num = race_manager->getNumSpareTireKarts();
|
||||
assert(m_spare_tire_karts.size() == sta_num);
|
||||
|
@ -212,10 +212,9 @@ void World::init()
|
||||
: race_manager->getKartIdent(i);
|
||||
int local_player_id = race_manager->getKartLocalPlayerId(i);
|
||||
int global_player_id = race_manager->getKartGlobalPlayerId(i);
|
||||
AbstractKart* newkart = createKart(kart_ident, i, local_player_id,
|
||||
global_player_id,
|
||||
race_manager->getKartType(i),
|
||||
race_manager->getPlayerDifficulty(i));
|
||||
auto newkart = createKart(kart_ident, i, local_player_id,
|
||||
global_player_id, race_manager->getKartType(i),
|
||||
race_manager->getPlayerDifficulty(i));
|
||||
m_karts.push_back(newkart);
|
||||
|
||||
} // for i
|
||||
@ -301,6 +300,7 @@ void World::reset()
|
||||
SFXManager::get()->resumeAll();
|
||||
|
||||
projectile_manager->cleanup();
|
||||
RewindManager::get()->reset();
|
||||
race_manager->reset();
|
||||
// Make sure to overwrite the data from the previous race.
|
||||
if(!history->replayHistory()) history->initRecording();
|
||||
@ -334,10 +334,10 @@ void World::createRaceGUI()
|
||||
* \param global_player_id If the kart is a player kart this is the index of
|
||||
* this player globally (i.e. including network players).
|
||||
*/
|
||||
AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType kart_type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
std::shared_ptr<AbstractKart> World::createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType kart_type,
|
||||
PerPlayerDifficulty difficulty)
|
||||
{
|
||||
unsigned int gk = 0;
|
||||
if (race_manager->hasGhostKarts())
|
||||
@ -355,13 +355,19 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
|
||||
int position = index+1;
|
||||
btTransform init_pos = getStartTransform(index - gk);
|
||||
AbstractKart *new_kart;
|
||||
std::shared_ptr<AbstractKart> new_kart;
|
||||
if (RewindManager::get()->isEnabled())
|
||||
new_kart = new KartRewinder(kart_ident, index, position, init_pos,
|
||||
difficulty, ri);
|
||||
{
|
||||
auto kr = std::make_shared<KartRewinder>(kart_ident, index, position,
|
||||
init_pos, difficulty, ri);
|
||||
kr->rewinderAdd();
|
||||
new_kart = kr;
|
||||
}
|
||||
else
|
||||
new_kart = new Kart(kart_ident, index, position, init_pos, difficulty,
|
||||
ri);
|
||||
{
|
||||
new_kart = std::make_shared<Kart>(kart_ident, index, position,
|
||||
init_pos, difficulty, ri);
|
||||
}
|
||||
|
||||
new_kart->init(race_manager->getKartType(index));
|
||||
Controller *controller = NULL;
|
||||
@ -369,7 +375,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
{
|
||||
case RaceManager::KT_PLAYER:
|
||||
{
|
||||
controller = new LocalPlayerController(new_kart, local_player_id,
|
||||
controller = new LocalPlayerController(new_kart.get(), local_player_id,
|
||||
difficulty);
|
||||
const PlayerProfile* p = StateManager::get()
|
||||
->getActivePlayer(local_player_id)->getConstProfile();
|
||||
@ -383,7 +389,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
}
|
||||
case RaceManager::KT_NETWORK_PLAYER:
|
||||
{
|
||||
controller = new NetworkPlayerController(new_kart);
|
||||
controller = new NetworkPlayerController(new_kart.get());
|
||||
if (!online_name.empty())
|
||||
new_kart->setOnScreenText(online_name.c_str());
|
||||
m_num_players++;
|
||||
@ -391,7 +397,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
|
||||
}
|
||||
case RaceManager::KT_AI:
|
||||
{
|
||||
controller = loadAIController(new_kart);
|
||||
controller = loadAIController(new_kart.get());
|
||||
break;
|
||||
}
|
||||
case RaceManager::KT_GHOST:
|
||||
@ -417,7 +423,7 @@ const btTransform &World::getStartTransform(int index)
|
||||
/** Creates an AI controller for the kart.
|
||||
* \param kart The kart to be controlled by an AI.
|
||||
*/
|
||||
Controller* World::loadAIController(AbstractKart *kart)
|
||||
Controller* World::loadAIController(AbstractKart* kart)
|
||||
{
|
||||
Controller *controller;
|
||||
int turn=0;
|
||||
@ -485,13 +491,7 @@ World::~World()
|
||||
|
||||
Weather::kill();
|
||||
|
||||
for ( unsigned int i = 0 ; i < m_karts.size() ; i++ )
|
||||
{
|
||||
// Let ReplayPlay destroy the ghost karts
|
||||
if (m_karts[i]->isGhostKart()) continue;
|
||||
delete m_karts[i];
|
||||
}
|
||||
|
||||
m_karts.clear();
|
||||
if(race_manager->hasGhostKarts() || race_manager->isRecordingRace())
|
||||
{
|
||||
// Destroy the old replay object, which also stored the ghost
|
||||
@ -502,7 +502,6 @@ World::~World()
|
||||
ReplayPlay::destroy();
|
||||
ReplayPlay::create();
|
||||
}
|
||||
m_karts.clear();
|
||||
if(race_manager->isRecordingRace())
|
||||
ReplayRecorder::get()->reset();
|
||||
race_manager->setRaceGhostKarts(false);
|
||||
@ -567,7 +566,8 @@ void World::terminateRace()
|
||||
{
|
||||
if(!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated())
|
||||
{
|
||||
m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i]));
|
||||
m_karts[i]->finishedRace(
|
||||
estimateFinishTimeForKart(m_karts[i].get()));
|
||||
|
||||
}
|
||||
} // i<kart_amount
|
||||
@ -699,7 +699,7 @@ void World::resetAllKarts()
|
||||
btTransform t = getRescueTransform(rescue_pos);
|
||||
// This will print out warnings if there is no terrain under
|
||||
// the kart, or the kart is being dropped on a reset texture
|
||||
moveKartTo(m_karts[kart_id], t);
|
||||
moveKartTo(m_karts[kart_id].get(), t);
|
||||
|
||||
} // rescue_pos<getNumberOfRescuePositions
|
||||
|
||||
@ -725,7 +725,7 @@ void World::resetAllKarts()
|
||||
Vec3 up_offset = (*i)->getNormal() * (0.5f * ((*i)->getKartHeight()));
|
||||
(*i)->setXYZ(xyz+up_offset);
|
||||
|
||||
bool kart_over_ground = Track::getCurrentTrack()->findGround(*i);
|
||||
bool kart_over_ground = Track::getCurrentTrack()->findGround(i->get());
|
||||
|
||||
if (!kart_over_ground)
|
||||
{
|
||||
@ -1055,14 +1055,16 @@ void World::update(int ticks)
|
||||
m_karts[i]->update(ticks);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(ticks);
|
||||
Physics::getInstance()->update(ticks);
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00);
|
||||
projectile_manager->update(ticks);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (physics)", 0xa0, 0x7F, 0x00);
|
||||
Physics::getInstance()->update(ticks);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1165,7 +1167,7 @@ void World::updateHighscores(int* best_highscore_rank)
|
||||
if (!m_karts[index[pos]]->hasFinishedRace()) continue;
|
||||
|
||||
assert(index[pos] < m_karts.size());
|
||||
Kart *k = (Kart*)m_karts[index[pos]];
|
||||
Kart *k = (Kart*)m_karts[index[pos]].get();
|
||||
|
||||
Highscores* highscores = getHighscores();
|
||||
|
||||
@ -1197,14 +1199,17 @@ void World::updateHighscores(int* best_highscore_rank)
|
||||
*/
|
||||
AbstractKart *World::getPlayerKart(unsigned int n) const
|
||||
{
|
||||
unsigned int count=-1;
|
||||
unsigned int count = -1;
|
||||
|
||||
for(unsigned int i=0; i<m_karts.size(); i++)
|
||||
if(m_karts[i]->getController()->isPlayerController())
|
||||
for(unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
if (m_karts[i]->getController()->isPlayerController())
|
||||
{
|
||||
count++;
|
||||
if(count==n) return m_karts[i];
|
||||
if (count == n)
|
||||
return m_karts[i].get();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} // getPlayerKart
|
||||
|
||||
@ -1225,7 +1230,7 @@ AbstractKart *World::getLocalPlayerKart(unsigned int n) const
|
||||
void World::eliminateKart(int kart_id, bool notify_of_elimination)
|
||||
{
|
||||
assert(kart_id < (int)m_karts.size());
|
||||
AbstractKart *kart = m_karts[kart_id];
|
||||
AbstractKart *kart = m_karts[kart_id].get();
|
||||
if (kart->isGhostKart()) return;
|
||||
|
||||
// Display a message about the eliminated kart in the race guia
|
||||
|
@ -25,6 +25,7 @@
|
||||
* battle, etc.)
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
@ -80,7 +81,7 @@ public:
|
||||
class World : public WorldStatus
|
||||
{
|
||||
public:
|
||||
typedef std::vector<AbstractKart*> KartList;
|
||||
typedef std::vector<std::shared_ptr<AbstractKart> > KartList;
|
||||
private:
|
||||
/** A pointer to the global world object for a race. */
|
||||
static World *m_world;
|
||||
@ -117,10 +118,10 @@ protected:
|
||||
Controller*
|
||||
loadAIController (AbstractKart *kart);
|
||||
|
||||
virtual AbstractKart *createKart(const std::string &kart_ident, int index,
|
||||
int local_player_id, int global_player_id,
|
||||
RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty);
|
||||
virtual std::shared_ptr<AbstractKart> createKart
|
||||
(const std::string &kart_ident, int index, int local_player_id,
|
||||
int global_player_id, RaceManager::KartType type,
|
||||
PerPlayerDifficulty difficulty);
|
||||
|
||||
/** Pointer to the race GUI. The race GUI is handled by world. */
|
||||
RaceGUIBase *m_race_gui;
|
||||
@ -293,7 +294,7 @@ public:
|
||||
/** Returns the kart with a given world id. */
|
||||
AbstractKart *getKart(int kartId) const {
|
||||
assert(kartId >= 0 && kartId < int(m_karts.size()));
|
||||
return m_karts[kartId]; }
|
||||
return m_karts[kartId].get(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns all karts. */
|
||||
const KartList & getKarts() const { return m_karts; }
|
||||
|
@ -82,7 +82,7 @@ AbstractKart* WorldWithRank::getKartAtPosition(unsigned int p) const
|
||||
if(p<1 || p>m_position_index.size())
|
||||
return NULL;
|
||||
|
||||
return m_karts[m_position_index[p-1]];
|
||||
return m_karts[m_position_index[p-1]].get();
|
||||
} // getKartAtPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -199,7 +199,8 @@ public:
|
||||
{
|
||||
return (char*)(m_buffer.data()+m_current_offset);
|
||||
} // getCurrentData
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
int getCurrentOffset() const { return m_current_offset; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the remaining length of the network string. */
|
||||
unsigned int size() const { return (int)m_buffer.size()-m_current_offset; }
|
||||
|
@ -19,8 +19,9 @@
|
||||
#include "network/rewind_info.hpp"
|
||||
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/rewinder.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
|
||||
/** Constructor for a state: it only takes the size, and allocates a buffer
|
||||
* for all state info.
|
||||
@ -63,16 +64,44 @@ void RewindInfoState::restore()
|
||||
m_buffer->reset();
|
||||
for (const std::string& name : m_rewinder_using)
|
||||
{
|
||||
uint16_t count = m_buffer->getUInt16();
|
||||
Rewinder* r = RewindManager::get()->getRewinder(name);
|
||||
if (r == NULL)
|
||||
const uint16_t data_size = m_buffer->getUInt16();
|
||||
const unsigned current_offset_now = m_buffer->getCurrentOffset();
|
||||
std::shared_ptr<Rewinder> r =
|
||||
RewindManager::get()->getRewinder(name);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
// For now we only need to get missing rewinder from
|
||||
// projectile_manager
|
||||
r = projectile_manager->addRewinderFromNetworkState(name);
|
||||
}
|
||||
if (!r)
|
||||
{
|
||||
Log::error("RewindInfoState", "Missing rewinder %s",
|
||||
name.c_str());
|
||||
m_buffer->skip(count);
|
||||
m_buffer->skip(data_size);
|
||||
continue;
|
||||
}
|
||||
r->restoreState(m_buffer, count);
|
||||
try
|
||||
{
|
||||
r->restoreState(m_buffer, data_size);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Log::error("RewindInfoState", "Restore state error: %s",
|
||||
e.what());
|
||||
m_buffer->reset();
|
||||
m_buffer->skip(current_offset_now + data_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_buffer->getCurrentOffset() - current_offset_now != data_size)
|
||||
{
|
||||
Log::error("RewindInfoState", "Wrong size read when restore "
|
||||
"state, incompatible binary?");
|
||||
m_buffer->reset();
|
||||
m_buffer->skip(current_offset_now + data_size);
|
||||
}
|
||||
} // for all rewinder
|
||||
} // restore
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "network/event_rewinder.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewinder.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
@ -173,14 +172,18 @@ public:
|
||||
class RewindInfoEventFunction : public RewindInfo
|
||||
{
|
||||
private:
|
||||
const std::function<void()> m_undo_function, m_replay_function;
|
||||
const std::function<void()> m_undo_function, m_replay_function,
|
||||
m_destroy_function;
|
||||
public:
|
||||
RewindInfoEventFunction(int ticks,
|
||||
std::function<void()> undo_function = [](){},
|
||||
std::function<void()> replay_function = [](){},
|
||||
bool is_confirmed = true)
|
||||
: RewindInfo(ticks, is_confirmed),
|
||||
m_undo_function(undo_function), m_replay_function(replay_function) {}
|
||||
std::function<void()> destroy_function = [](){})
|
||||
: RewindInfo(ticks, true/*is_confirmed*/),
|
||||
m_undo_function(undo_function), m_replay_function(replay_function),
|
||||
m_destroy_function(destroy_function) {}
|
||||
// ------------------------------------------------------------------------
|
||||
~RewindInfoEventFunction() { m_destroy_function(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** An event is never 'restored', it is only rewound. */
|
||||
void restore() {}
|
||||
|
@ -82,18 +82,7 @@ void RewindManager::reset()
|
||||
|
||||
if (!m_enable_rewind_manager) return;
|
||||
|
||||
for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();)
|
||||
{
|
||||
if (!it->second->canBeDestroyed())
|
||||
{
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
Rewinder* rewinder = it->second;
|
||||
it = m_all_rewinder.erase(it);
|
||||
delete rewinder;
|
||||
}
|
||||
|
||||
clearExpiredRewinder();
|
||||
m_rewind_queue.reset();
|
||||
} // reset
|
||||
|
||||
@ -166,7 +155,9 @@ void RewindManager::saveState()
|
||||
{
|
||||
// TODO: check if it's worth passing in a sufficiently large buffer from
|
||||
// GameProtocol - this would save the copy operation.
|
||||
BareNetworkString* buffer = p.second->saveState(&rewinder_using);
|
||||
BareNetworkString* buffer = NULL;
|
||||
if (auto r = p.second.lock())
|
||||
buffer = r->saveState(&rewinder_using);
|
||||
if (buffer != NULL)
|
||||
{
|
||||
m_overall_state_size += buffer->size();
|
||||
@ -197,12 +188,16 @@ void RewindManager::update(int ticks_not_used)
|
||||
if (ticks - m_last_saved_state < m_state_frequency)
|
||||
return;
|
||||
|
||||
// Save state
|
||||
// Save state, remove expired rewinder first
|
||||
clearExpiredRewinder();
|
||||
if (NetworkConfig::get()->isClient())
|
||||
{
|
||||
auto& ret = m_local_state[ticks];
|
||||
for (auto& p : m_all_rewinder)
|
||||
ret.push_back(p.second->getLocalStateRestoreFunction());
|
||||
{
|
||||
if (auto r = p.second.lock())
|
||||
ret.push_back(r->getLocalStateRestoreFunction());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -222,6 +217,10 @@ void RewindManager::update(int ticks_not_used)
|
||||
*/
|
||||
void RewindManager::playEventsTill(int world_ticks, int *ticks)
|
||||
{
|
||||
// We add the RewindInfoEventFunction to rewind queue before and after
|
||||
// possible rewind, some RewindInfoEventFunction can be created during
|
||||
// rewind
|
||||
mergeRewindInfoEventFunction();
|
||||
bool needs_rewind;
|
||||
int rewind_ticks;
|
||||
|
||||
@ -255,6 +254,20 @@ void RewindManager::playEventsTill(int world_ticks, int *ticks)
|
||||
m_is_rewinding = false;
|
||||
} // playEventsTill
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a Rewinder to the list of all rewinders.
|
||||
* \return true If successfully added, false otherwise.
|
||||
*/
|
||||
bool RewindManager::addRewinder(std::shared_ptr<Rewinder> rewinder)
|
||||
{
|
||||
if (!m_enable_rewind_manager) return false;
|
||||
// Maximum 1 bit to store no of rewinder used
|
||||
if (m_all_rewinder.size() == 255)
|
||||
return false;
|
||||
m_all_rewinder[rewinder->getUniqueIdentity()] = rewinder;
|
||||
return true;
|
||||
} // addRewinder
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Rewinds to the specified time, then goes forward till the current
|
||||
* World::getTime() is reached again: it will replay everything before
|
||||
@ -274,7 +287,10 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
// can be computed between the transforms before and after
|
||||
// the rewind.
|
||||
for (auto& p : m_all_rewinder)
|
||||
p.second->saveTransform();
|
||||
{
|
||||
if (auto r = p.second.lock())
|
||||
r->saveTransform();
|
||||
}
|
||||
|
||||
// Then undo the rewind infos going backwards in time
|
||||
// --------------------------------------------------
|
||||
@ -348,10 +364,14 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
|
||||
// Now compute the errors which need to be visually smoothed
|
||||
for (auto& p : m_all_rewinder)
|
||||
p.second->computeError();
|
||||
{
|
||||
if (auto r = p.second.lock())
|
||||
r->computeError();
|
||||
}
|
||||
|
||||
history->setReplayHistory(is_history);
|
||||
m_is_rewinding = false;
|
||||
mergeRewindInfoEventFunction();
|
||||
} // rewindTo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -360,3 +380,11 @@ bool RewindManager::useLocalEvent() const
|
||||
return NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient() && !m_is_rewinding;
|
||||
} // useLocalEvent
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RewindManager::mergeRewindInfoEventFunction()
|
||||
{
|
||||
for (RewindInfoEventFunction* rief : m_pending_rief)
|
||||
m_rewind_queue.insertRewindInfo(rief);
|
||||
m_pending_rief.clear();
|
||||
} // mergeRewindInfoEventFunction
|
||||
|
@ -19,7 +19,6 @@
|
||||
#ifndef HEADER_REWIND_MANAGER_HPP
|
||||
#define HEADER_REWIND_MANAGER_HPP
|
||||
|
||||
#include "network/rewinder.hpp"
|
||||
#include "network/rewind_queue.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
@ -27,10 +26,15 @@
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Rewinder;
|
||||
class RewindInfo;
|
||||
class RewindInfoEventFunction;
|
||||
class EventRewinder;
|
||||
|
||||
/** \ingroup network
|
||||
@ -93,7 +97,7 @@ private:
|
||||
std::map<int, std::vector<std::function<void()> > > m_local_state;
|
||||
|
||||
/** A list of all objects that can be rewound. */
|
||||
std::map<std::string, Rewinder*> m_all_rewinder;
|
||||
std::map<std::string, std::weak_ptr<Rewinder> > m_all_rewinder;
|
||||
|
||||
/** The queue that stores all rewind infos. */
|
||||
RewindQueue m_rewind_queue;
|
||||
@ -115,8 +119,25 @@ private:
|
||||
* rewinds. */
|
||||
std::atomic<int> m_not_rewound_ticks;
|
||||
|
||||
std::vector<RewindInfoEventFunction*> m_pending_rief;
|
||||
|
||||
RewindManager();
|
||||
~RewindManager();
|
||||
// ------------------------------------------------------------------------
|
||||
void clearExpiredRewinder()
|
||||
{
|
||||
for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();)
|
||||
{
|
||||
if (it->second.expired())
|
||||
{
|
||||
it = m_all_rewinder.erase(it);
|
||||
continue;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void mergeRewindInfoEventFunction();
|
||||
|
||||
public:
|
||||
// First static functions to manage rewinding.
|
||||
@ -151,27 +172,18 @@ public:
|
||||
void addNetworkState(BareNetworkString *buffer, int ticks);
|
||||
void saveState();
|
||||
// ------------------------------------------------------------------------
|
||||
Rewinder* getRewinder(const std::string& name)
|
||||
std::shared_ptr<Rewinder> getRewinder(const std::string& name)
|
||||
{
|
||||
auto it = m_all_rewinder.find(name);
|
||||
if (it == m_all_rewinder.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
if (it != m_all_rewinder.end())
|
||||
{
|
||||
if (auto r = it->second.lock())
|
||||
return r;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a Rewinder to the list of all rewinders.
|
||||
* \return true If rewinding is enabled, false otherwise.
|
||||
*/
|
||||
bool addRewinder(Rewinder *rewinder)
|
||||
{
|
||||
if (!m_enable_rewind_manager) return false;
|
||||
// Maximum 1 bit to store no of rewinder used
|
||||
if (m_all_rewinder.size() == 255)
|
||||
return false;
|
||||
m_all_rewinder[rewinder->getUniqueIdentity()] = rewinder;
|
||||
return true;
|
||||
} // addRewinder
|
||||
|
||||
bool addRewinder(std::shared_ptr<Rewinder> rewinder);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if currently a rewind is happening. */
|
||||
bool isRewinding() const { return m_is_rewinding; }
|
||||
@ -182,8 +194,6 @@ public:
|
||||
return m_not_rewound_ticks.load(std::memory_order_relaxed);
|
||||
} // getNotRewoundWorldTicks
|
||||
// ------------------------------------------------------------------------
|
||||
RewindQueue& getRewindQueue() { return m_rewind_queue; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the time of the latest confirmed state. */
|
||||
int getLatestConfirmedState() const
|
||||
{
|
||||
@ -200,6 +210,9 @@ public:
|
||||
{ return m_current_rewinder_using; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool useLocalEvent() const;
|
||||
// ------------------------------------------------------------------------
|
||||
void addRewindInfoEventFunction(RewindInfoEventFunction* rief)
|
||||
{ m_pending_rief.push_back(rief); }
|
||||
|
||||
}; // RewindManager
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "config/stk_config.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/rewinder.hpp"
|
||||
#include "network/rewind_info.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
|
||||
@ -353,8 +354,10 @@ int RewindQueue::undoUntil(int undo_ticks)
|
||||
{
|
||||
// A rewind is done after a state in the past is inserted. This function
|
||||
// makes sure that m_current is not end()
|
||||
assert(m_current != m_all_rewind_info.end());
|
||||
|
||||
//assert(m_current != m_all_rewind_info.end());
|
||||
assert(!m_all_rewind_info.empty());
|
||||
m_current = m_all_rewind_info.end();
|
||||
m_current--;
|
||||
while((*m_current)->getTicks() > undo_ticks ||
|
||||
(*m_current)->isEvent() || !(*m_current)->isConfirmed())
|
||||
{
|
||||
@ -418,9 +421,9 @@ void RewindQueue::unitTesting()
|
||||
virtual void rewind(BareNetworkString *s) {}
|
||||
virtual void saveTransform() {}
|
||||
virtual void computeError() {}
|
||||
DummyRewinder() : Rewinder("dummy_rewinder", true) {}
|
||||
DummyRewinder() : Rewinder() {}
|
||||
};
|
||||
DummyRewinder *dummy_rewinder = new DummyRewinder();
|
||||
auto dummy_rewinder = std::make_shared<DummyRewinder>();
|
||||
|
||||
// First tests: add a state first, then an event, and make
|
||||
// sure the state stays first
|
||||
@ -434,7 +437,7 @@ void RewindQueue::unitTesting()
|
||||
assert(q0.hasMoreRewindInfo());
|
||||
assert(q0.undoUntil(0) == 0);
|
||||
|
||||
q0.addNetworkEvent(dummy_rewinder, NULL, 0);
|
||||
q0.addNetworkEvent(dummy_rewinder.get(), NULL, 0);
|
||||
// Network events are not immediately merged
|
||||
assert(q0.m_all_rewind_info.size() == 1);
|
||||
|
||||
@ -462,9 +465,9 @@ void RewindQueue::unitTesting()
|
||||
assert((*rii)->isEvent());
|
||||
|
||||
// Test time base comparisons: adding an event to the end
|
||||
q0.addLocalEvent(dummy_rewinder, NULL, true, 4);
|
||||
q0.addLocalEvent(dummy_rewinder.get(), NULL, true, 4);
|
||||
// Then adding an earlier event
|
||||
q0.addLocalEvent(dummy_rewinder, NULL, false, 1);
|
||||
q0.addLocalEvent(dummy_rewinder.get(), NULL, false, 1);
|
||||
// rii points to the 3rd element, the ones added just now
|
||||
// should be elements4 and 5:
|
||||
rii++;
|
||||
|
@ -19,14 +19,13 @@
|
||||
#ifndef HEADER_REWIND_QUEUE_HPP
|
||||
#define HEADER_REWIND_QUEUE_HPP
|
||||
|
||||
#include "network/rewinder.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
class BareNetworkString;
|
||||
class EventRewinder;
|
||||
class RewindInfo;
|
||||
class TimeStepInfo;
|
||||
|
@ -20,27 +20,11 @@
|
||||
|
||||
#include "network/rewind_manager.hpp"
|
||||
|
||||
/** Constructor. It will add this object to the list of all rewindable
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Add this object to the list of all rewindable
|
||||
* objects in the rewind manager.
|
||||
*/
|
||||
Rewinder::Rewinder(const std::string& ui, bool can_be_destroyed, bool auto_add)
|
||||
: m_unique_identity(ui)
|
||||
bool Rewinder::rewinderAdd()
|
||||
{
|
||||
assert(!m_unique_identity.empty() && m_unique_identity.size() < 255);
|
||||
m_can_be_destroyed = can_be_destroyed;
|
||||
if (auto_add)
|
||||
add();
|
||||
} // Rewinder
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor.
|
||||
*/
|
||||
Rewinder::~Rewinder()
|
||||
{
|
||||
} // ~Rewinder
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Rewinder::add()
|
||||
{
|
||||
RewindManager::get()->addRewinder(this);
|
||||
} // Rewinder
|
||||
return RewindManager::get()->addRewinder(shared_from_this());
|
||||
} // rewinderAdd
|
||||
|
@ -19,33 +19,25 @@
|
||||
#ifndef HEADER_REWINDER_HPP
|
||||
#define HEADER_REWINDER_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class BareNetworkString;
|
||||
|
||||
class Rewinder
|
||||
class Rewinder : public std::enable_shared_from_this<Rewinder>
|
||||
{
|
||||
protected:
|
||||
void add();
|
||||
// -------------------------------------------------------------------------
|
||||
void setUniqueIdentity(const std::string& uid) { m_unique_identity = uid; }
|
||||
|
||||
private:
|
||||
std::string m_unique_identity;
|
||||
|
||||
/** True if this object can be destroyed, i.e. if this object is a 'stand
|
||||
* alone' (i.e. not used in inheritance). If the object is used in
|
||||
* inheritance (e.g. KartRewinder, which is a Rewinder and Kart), then
|
||||
* freeing the kart will free this rewinder instance as well.
|
||||
*/
|
||||
bool m_can_be_destroyed;
|
||||
|
||||
public:
|
||||
Rewinder(const std::string& ui, bool can_be_destroyed,
|
||||
bool auto_add = true);
|
||||
virtual ~Rewinder();
|
||||
Rewinder(const std::string& ui = "") { m_unique_identity = ui; }
|
||||
|
||||
virtual ~Rewinder() {}
|
||||
|
||||
/** Called before a rewind. Is used to save the previous position of an
|
||||
* object before a rewind, so that the error due to a rewind can be
|
||||
@ -89,14 +81,20 @@ public:
|
||||
/** Nothing to do here. */
|
||||
virtual void reset() {}
|
||||
// -------------------------------------------------------------------------
|
||||
/** True if this rewinder can be destroyed. Karts can not be destroyed,
|
||||
* cakes can. This is used by the RewindManager in reset. */
|
||||
bool canBeDestroyed() const { return m_can_be_destroyed; }
|
||||
// -------------------------------------------------------------------------
|
||||
virtual std::function<void()> getLocalStateRestoreFunction()
|
||||
{ return nullptr; }
|
||||
// -------------------------------------------------------------------------
|
||||
const std::string& getUniqueIdentity() const { return m_unique_identity; }
|
||||
const std::string& getUniqueIdentity() const
|
||||
{
|
||||
assert(!m_unique_identity.empty() && m_unique_identity.size() < 255);
|
||||
return m_unique_identity;
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
bool rewinderAdd();
|
||||
// -------------------------------------------------------------------------
|
||||
template<typename T> std::shared_ptr<T> getShared()
|
||||
{ return std::dynamic_pointer_cast<T>(shared_from_this()); }
|
||||
|
||||
}; // Rewinder
|
||||
#endif
|
||||
|
||||
|
@ -71,8 +71,6 @@ void* btKartRaycaster::castRay(const btVector3& from, const btVector3& to,
|
||||
result.m_hitNormalInWorld.normalize();
|
||||
result.m_distFraction = rayCallback.m_closestHitFraction;
|
||||
result.m_triangle_index = -1;
|
||||
const TriangleMesh &tm =
|
||||
Track::getCurrentTrack()->getTriangleMesh();
|
||||
// FIXME: this code assumes atm that the object the kart is
|
||||
// driving on is the main track (and not e.g. a physical object).
|
||||
// If this should not be the case (i.e. the object hit by the
|
||||
|
@ -123,12 +123,11 @@ void PhysicalObject::Settings::init()
|
||||
} // Settings
|
||||
|
||||
// ============================================================================
|
||||
PhysicalObject* PhysicalObject::fromXML(bool is_dynamic,
|
||||
const XMLNode &xml_node,
|
||||
TrackObject* object)
|
||||
std::shared_ptr<PhysicalObject> PhysicalObject::fromXML
|
||||
(bool is_dynamic, const XMLNode &xml_node, TrackObject* object)
|
||||
{
|
||||
PhysicalObject::Settings settings(xml_node);
|
||||
return new PhysicalObject(is_dynamic, settings, object);
|
||||
return std::make_shared<PhysicalObject>(is_dynamic, settings, object);
|
||||
} // fromXML
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -136,7 +135,6 @@ PhysicalObject* PhysicalObject::fromXML(bool is_dynamic,
|
||||
PhysicalObject::PhysicalObject(bool is_dynamic,
|
||||
const PhysicalObject::Settings& settings,
|
||||
TrackObject* object)
|
||||
: Rewinder("P", false/*can_be_destroyed*/, false/*auto_add*/)
|
||||
{
|
||||
m_shape = NULL;
|
||||
m_body = NULL;
|
||||
@ -793,7 +791,7 @@ void PhysicalObject::addForRewind()
|
||||
SmoothNetworkBody::setAdjustVerticalOffset(false);
|
||||
Rewinder::setUniqueIdentity(std::string("P") + StringUtils::toString
|
||||
(Track::getCurrentTrack()->getPhysicalObjectUID()));
|
||||
Rewinder::add();
|
||||
Rewinder::rewinderAdd();
|
||||
} // addForRewind
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -197,8 +197,8 @@ public:
|
||||
PhysicalObject(bool is_dynamic, const Settings& settings,
|
||||
TrackObject* object);
|
||||
|
||||
static PhysicalObject* fromXML(bool is_dynamic, const XMLNode &node,
|
||||
TrackObject* object);
|
||||
static std::shared_ptr<PhysicalObject> fromXML
|
||||
(bool is_dynamic, const XMLNode &node, TrackObject* object);
|
||||
|
||||
virtual ~PhysicalObject ();
|
||||
virtual void reset ();
|
||||
|
@ -296,11 +296,13 @@ void History::Load()
|
||||
{
|
||||
fgets(s, 1023, fd);
|
||||
InputEvent &ie = m_all_input_events[i];
|
||||
int action = 0;
|
||||
if (sscanf(s, "%d %d %d %d\n", &ie.m_world_ticks, &ie.m_kart_index,
|
||||
&ie.m_action, &ie.m_value) != 4 )
|
||||
&action, &ie.m_value) != 4)
|
||||
{
|
||||
Log::warn("History", "Problems reading event: '%s'", s);
|
||||
}
|
||||
ie.m_action = (PlayerAction)action;
|
||||
} // for i
|
||||
RewindManager::setEnable(rewind_manager_was_enabled);
|
||||
|
||||
|
@ -58,7 +58,7 @@ void ReplayPlay::reset()
|
||||
{
|
||||
for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++)
|
||||
{
|
||||
m_ghost_karts[i].reset();
|
||||
m_ghost_karts[i]->reset();
|
||||
}
|
||||
} // reset
|
||||
|
||||
@ -297,7 +297,7 @@ bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay, int ca
|
||||
//-----------------------------------------------------------------------------
|
||||
void ReplayPlay::load()
|
||||
{
|
||||
m_ghost_karts.clearAndDeleteAll();
|
||||
m_ghost_karts.clear();
|
||||
|
||||
if (m_second_replay_enabled)
|
||||
loadFile(/* second replay */ true);
|
||||
@ -365,11 +365,11 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay)
|
||||
first_loaded_f_num = m_replay_file_list.at(m_second_replay_file).m_kart_list.size();
|
||||
|
||||
ReplayData &rd = m_replay_file_list[replay_index];
|
||||
m_ghost_karts.push_back(new GhostKart(rd.m_kart_list.at(kart_num-first_loaded_f_num),
|
||||
kart_num, kart_num + 1,
|
||||
rd.m_kart_color.at(kart_num-first_loaded_f_num)));
|
||||
m_ghost_karts[kart_num].init(RaceManager::KT_GHOST);
|
||||
Controller* controller = new GhostController(getGhostKart(kart_num),
|
||||
m_ghost_karts.push_back(std::make_shared<GhostKart>
|
||||
(rd.m_kart_list.at(kart_num-first_loaded_f_num), kart_num, kart_num + 1,
|
||||
rd.m_kart_color.at(kart_num-first_loaded_f_num)));
|
||||
m_ghost_karts[kart_num]->init(RaceManager::KT_GHOST);
|
||||
Controller* controller = new GhostController(getGhostKart(kart_num).get(),
|
||||
rd.m_name_list[kart_num-first_loaded_f_num]);
|
||||
getGhostKart(kart_num)->setController(controller);
|
||||
|
||||
@ -423,7 +423,7 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay)
|
||||
kre.m_skidding_effect = skidding;
|
||||
kre.m_red_skidding = red_skidding!=0;
|
||||
kre.m_jumping = jumping != 0;
|
||||
m_ghost_karts[kart_num].addReplayEvent(time,
|
||||
m_ghost_karts[kart_num]->addReplayEvent(time,
|
||||
btTransform(q, xyz), pi, bi, kre);
|
||||
}
|
||||
else
|
||||
@ -472,7 +472,7 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay)
|
||||
kre.m_skidding_effect = skidding;
|
||||
kre.m_red_skidding = red_skidding!=0;
|
||||
kre.m_jumping = jumping != 0;
|
||||
m_ghost_karts[kart_num].addReplayEvent(time,
|
||||
m_ghost_karts[kart_num]->addReplayEvent(time,
|
||||
btTransform(q, xyz), pi, bi, kre);
|
||||
}
|
||||
else
|
||||
|
@ -20,10 +20,10 @@
|
||||
#define HEADER_REPLAY__PLAY_HPP
|
||||
|
||||
#include "replay/replay_base.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#include "irrString.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -118,7 +118,7 @@ private:
|
||||
std::vector<ReplayData> m_replay_file_list;
|
||||
|
||||
/** All ghost karts. */
|
||||
PtrVector<GhostKart> m_ghost_karts;
|
||||
std::vector<std::shared_ptr<GhostKart> > m_ghost_karts;
|
||||
|
||||
ReplayPlay();
|
||||
~ReplayPlay();
|
||||
@ -162,7 +162,7 @@ public:
|
||||
const unsigned int getNumReplayFile() const
|
||||
{ return (unsigned int)m_replay_file_list.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
GhostKart* getGhostKart(int n) { return m_ghost_karts.get(n); }
|
||||
std::shared_ptr<GhostKart> getGhostKart(int n) { return m_ghost_karts[n]; }
|
||||
// ------------------------------------------------------------------------
|
||||
const unsigned int getNumGhostKart() const
|
||||
{
|
||||
|
@ -1029,7 +1029,7 @@ void RaceGUIBase::drawPlungerInFace(const Camera *camera, float dt)
|
||||
if(m_plunger_move_time < dt && m_plunger_state!=PLUNGER_STATE_FAST)
|
||||
{
|
||||
const float fast_time = 0.3f;
|
||||
if(kart->getBlockedByPlungerTicks()<fast_time)
|
||||
if(kart->getBlockedByPlungerTicks()<stk_config->time2Ticks(fast_time))
|
||||
{
|
||||
// First time we reach faste state: select random target point
|
||||
// at top of screen and set speed accordingly
|
||||
|
@ -74,7 +74,6 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
m_enabled = true;
|
||||
m_presentation = NULL;
|
||||
m_animator = NULL;
|
||||
m_physical_object = NULL;
|
||||
m_parent_library = NULL;
|
||||
m_interaction = interaction;
|
||||
m_presentation = presentation;
|
||||
@ -86,9 +85,8 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
if (m_interaction != "ghost" && m_interaction != "none" &&
|
||||
physics_settings )
|
||||
{
|
||||
m_physical_object = new PhysicalObject(is_dynamic,
|
||||
*physics_settings,
|
||||
this);
|
||||
m_physical_object = std::make_shared<PhysicalObject>
|
||||
(is_dynamic, *physics_settings, this);
|
||||
}
|
||||
|
||||
reset();
|
||||
@ -112,7 +110,6 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||
m_presentation = NULL;
|
||||
m_animator = NULL;
|
||||
m_parent_library = parent_library;
|
||||
m_physical_object = NULL;
|
||||
|
||||
xml_node.get("id", &m_id );
|
||||
xml_node.get("model", &m_name );
|
||||
@ -455,7 +452,6 @@ TrackObject::~TrackObject()
|
||||
{
|
||||
delete m_presentation;
|
||||
delete m_animator;
|
||||
delete m_physical_object;
|
||||
} // ~TrackObject
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -482,7 +478,7 @@ void TrackObject::setEnabled(bool enabled)
|
||||
|
||||
if (getType() == "mesh")
|
||||
{
|
||||
if (m_physical_object != NULL)
|
||||
if (m_physical_object)
|
||||
{
|
||||
if (enabled)
|
||||
m_physical_object->addBody();
|
||||
@ -508,7 +504,7 @@ void TrackObject::resetEnabled()
|
||||
|
||||
if (getType() == "mesh")
|
||||
{
|
||||
if (m_physical_object != NULL)
|
||||
if (m_physical_object)
|
||||
{
|
||||
if (m_initially_visible)
|
||||
m_physical_object->addBody();
|
||||
@ -581,7 +577,7 @@ void TrackObject::move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||
if (m_presentation != NULL)
|
||||
m_presentation->move(xyz, hpr, scale, isAbsoluteCoord);
|
||||
|
||||
if (update_rigid_body && m_physical_object != NULL)
|
||||
if (update_rigid_body && m_physical_object)
|
||||
{
|
||||
movePhysicalBodyToGraphicalNode(xyz, hpr);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ protected:
|
||||
/** True if a kart can drive on this object. This will */
|
||||
bool m_is_driveable;
|
||||
|
||||
PhysicalObject* m_physical_object;
|
||||
std::shared_ptr<PhysicalObject> m_physical_object;
|
||||
|
||||
ThreeDAnimation* m_animator;
|
||||
|
||||
@ -164,9 +164,10 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
bool isSoccerBall() const { return m_soccer_ball; }
|
||||
// ------------------------------------------------------------------------
|
||||
const PhysicalObject* getPhysicalObject() const { return m_physical_object; }
|
||||
const PhysicalObject* getPhysicalObject() const
|
||||
{ return m_physical_object.get(); }
|
||||
// ------------------------------------------------------------------------
|
||||
PhysicalObject* getPhysicalObject() { return m_physical_object; }
|
||||
PhysicalObject* getPhysicalObject() { return m_physical_object.get(); }
|
||||
// ------------------------------------------------------------------------
|
||||
const core::vector3df getInitXYZ() const { return m_init_xyz; }
|
||||
// ------------------------------------------------------------------------
|
||||
@ -214,7 +215,7 @@ public:
|
||||
/** Get the physics representation of an object.
|
||||
* On the script side, the returned object is of type : @ref Scripting_PhysicalObject
|
||||
*/
|
||||
PhysicalObject* getPhysics() { return m_physical_object; }
|
||||
PhysicalObject* getPhysics() { return m_physical_object.get(); }
|
||||
/** Hide or show the object */
|
||||
void setEnabled(bool mode);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user