Add initial kart local state saving with correct attachment rewind

This commit is contained in:
Benau 2018-07-12 07:08:02 +08:00
parent 8515805d52
commit 11d9090039
10 changed files with 113 additions and 57 deletions

View File

@ -148,11 +148,6 @@ void Attachment::set(AttachmentType type, int ticks,
case ATTACH_BOMB:
m_node->setMesh(attachment_manager->getMesh(type));
m_node->setAnimationSpeed(0);
if (m_bomb_sound) m_bomb_sound->deleteSFX();
m_bomb_sound = SFXManager::get()->createSoundSource("clock");
m_bomb_sound->setLoop(true);
m_bomb_sound->setPosition(m_kart->getXYZ());
m_bomb_sound->play();
break;
default:
m_node->setMesh(attachment_manager->getMesh(type));
@ -229,23 +224,12 @@ void Attachment::clear()
m_plugin = NULL;
}
if (m_bomb_sound)
{
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
m_type=ATTACH_NOTHING;
m_ticks_left = 0;
m_node->setVisible(false);
m_node->setPosition(core::vector3df());
m_node->setRotation(core::vector3df());
// Resets the weight of the kart if the previous attachment affected it
// (e.g. anvil). This must be done *after* setting m_type to
// ATTACH_NOTHING in order to reset the physics parameters.
m_kart->updateWeight();
} // clear
// -----------------------------------------------------------------------------
@ -300,14 +284,19 @@ void Attachment::rewindTo(BareNetworkString *buffer)
// Attaching an object can be expensive (loading new models, ...)
// so avoid doing this if there is no change in attachment type
if(new_type == m_type)
// Don't use set to reset a model on local player if it's already cleared
// (or m_initial_speed is redone / model is re-shown again when rewinding)
if (m_type == new_type || m_type == ATTACH_NOTHING)
{
setTicksLeft(ticks_left);
if (m_type != new_type)
m_type = new_type;
return;
}
set(new_type, ticks_left, m_previous_owner);
} // rewindTo
// -----------------------------------------------------------------------------
/** Called when going forwards in time during a rewind.
* \param buffer Buffer with the rewind information.
@ -421,7 +410,6 @@ void Attachment::hitBanana(ItemState *item_state)
// Reduce speed once (see description above), all other changes are
// handled in Kart::updatePhysics
m_kart->adjustSpeed(kp->getAnvilSpeedFactor());
m_kart->updateWeight();
break;
case ATTACH_BOMB:
set( ATTACH_BOMB, stk_config->time2Ticks(stk_config->m_bomb_time)
@ -511,12 +499,10 @@ void Attachment::update(int ticks)
m_ticks_left -= ticks;
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD;
float m_wanted_node_scale = is_shield
? std::max(1.0f, m_kart->getHighestPoint()*1.1f)
: 1.0f;
float wanted_node_scale = is_shield ?
std::max(1.0f, m_kart->getHighestPoint() * 1.1f) : 1.0f;
int slow_flashes = stk_config->time2Ticks(3.0f);
if (is_shield && m_ticks_left < slow_flashes)
{
@ -533,11 +519,11 @@ void Attachment::update(int ticks)
}
float dt = stk_config->ticks2Time(ticks);
if (m_node_scale < m_wanted_node_scale)
if (m_node_scale < wanted_node_scale)
{
m_node_scale += dt*1.5f;
if (m_node_scale > m_wanted_node_scale)
m_node_scale = m_wanted_node_scale;
if (m_node_scale > wanted_node_scale)
m_node_scale = wanted_node_scale;
m_node->setScale(core::vector3df(m_node_scale,m_node_scale,
m_node_scale) );
}
@ -590,8 +576,6 @@ void Attachment::update(int ticks)
break;
case ATTACH_BOMB:
{
if (m_bomb_sound) m_bomb_sound->setPosition(m_kart->getXYZ());
// Mesh animation frames are 1 to 61 frames (60 steps)
// The idea is change second by second, counterclockwise 60 to 0 secs
// If longer times needed, it should be a surprise "oh! bomb activated!"
@ -609,24 +593,21 @@ void Attachment::update(int ticks)
he->setLocalPlayerKartHit();
projectile_manager->addHitEffect(he);
ExplosionAnimation::create(m_kart);
if (m_bomb_sound)
{
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
}
break;
}
case ATTACH_BUBBLEGUM_SHIELD:
case ATTACH_NOLOK_BUBBLEGUM_SHIELD:
if (m_ticks_left <= 0)
{
if (!RewindManager::get()->isRewinding())
{
if (m_bubble_explode_sound) m_bubble_explode_sound->deleteSFX();
m_bubble_explode_sound =
SFXManager::get()->createSoundSource("bubblegum_explode");
m_bubble_explode_sound->setPosition(m_kart->getXYZ());
m_bubble_explode_sound->play();
}
ItemManager::get()->dropNewItem(Item::ITEM_BUBBLEGUM, m_kart);
}
@ -634,10 +615,38 @@ void Attachment::update(int ticks)
} // switch
// Detach attachment if its time is up.
if ( m_ticks_left <= 0)
if (m_ticks_left <= 0)
clear();
} // update
// ----------------------------------------------------------------------------
void Attachment::updateGraphics(float dt)
{
switch (m_type)
{
case ATTACH_BOMB:
{
if (!m_bomb_sound)
{
m_bomb_sound = SFXManager::get()->createSoundSource("clock");
m_bomb_sound->setLoop(true);
m_bomb_sound->play();
}
m_bomb_sound->setPosition(m_kart->getXYZ());
return;
}
default:
break;
} // switch
if (m_bomb_sound)
{
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
} // updateGraphics
// ----------------------------------------------------------------------------
/** Return the additional weight of the attachment (some attachments slow
* karts down by also making them heavier).

View File

@ -116,6 +116,8 @@ public:
~Attachment();
void clear ();
void hitBanana(ItemState *item);
void updateGraphics(float dt);
void update(int ticks);
void handleCollisionWithKart(AbstractKart *other);
void set (AttachmentType type, int ticks,
@ -154,6 +156,15 @@ public:
/** Nothing to undo when going back during a rewind, the full state info
* will take care of creating the right attachment. */
virtual void undo(BareNetworkString *buffer) { }
// ------------------------------------------------------------------------
float getInitialSpeed() const { return m_initial_speed; }
// ------------------------------------------------------------------------
void setInitialSpeed(float speed) { m_initial_speed = speed; }
// ------------------------------------------------------------------------
float getNodeScale() const { return m_node_scale; }
// ------------------------------------------------------------------------
void setNodeScale(float scale) { m_node_scale = scale; }
}; // Attachment
#endif

View File

@ -348,7 +348,6 @@ void Powerup::use()
kart->getAttachment()->set(Attachment::ATTACH_ANVIL,
stk_config->
time2Ticks(kp->getAnvilDuration()) );
kart->updateWeight();
kart->adjustSpeed(kp->getAnvilSpeedFactor() * 0.5f);
// should we position the sound at the kart that is hit,

View File

@ -430,10 +430,6 @@ public:
* over. */
virtual void startEngineSFX() = 0;
// ------------------------------------------------------------------------
/** This method is to be called every time the mass of the kart is updated,
* which includes attaching an anvil to the kart (and detaching). */
virtual void updateWeight() = 0;
// ------------------------------------------------------------------------
/** Multiplies the velocity of the kart by a factor f (both linear
* and angular). This is used by anvils, which suddenly slow down the kart
* when they are attached. */

View File

@ -59,9 +59,6 @@ public:
virtual void updateGraphics(float dt) OVERRIDE;
virtual void reset() OVERRIDE;
// ------------------------------------------------------------------------
/** No physics body for ghost kart, so nothing to adjust. */
virtual void updateWeight() OVERRIDE {};
// ------------------------------------------------------------------------
/** No physics for ghost kart. */
virtual void applyEngineForce (float force) OVERRIDE {};
// ------------------------------------------------------------------------
@ -93,7 +90,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the time at which the kart was at a given distance.
* Returns -1.0f if none */
float getTimeForDistance(float distance);
virtual float getTimeForDistance(float distance) OVERRIDE;
// ----------------------------------------------------------------------------
/** Returns the smallest time at which the kart had the required number of eggs

View File

@ -351,6 +351,9 @@ void Kart::reset()
m_kart_gfx->reset();
m_skidding->reset();
m_weight = 0.0f;
updateWeight();
#ifndef SERVER_ONLY
if (m_collision_particles)
m_collision_particles->setCreationRateAbsolute(0.0f);
@ -856,10 +859,13 @@ void Kart::adjustSpeed(float f)
void Kart::updateWeight()
{
float mass = m_kart_properties->getMass() + m_attachment->weightAdjust();
if (m_weight != mass)
{
m_weight = mass;
btVector3 inertia;
m_kart_chassis.calculateLocalInertia(mass, inertia);
m_body->setMassProps(mass, inertia);
}
} // updateWeight
// ------------------------------------------------------------------------
@ -2524,6 +2530,7 @@ void Kart::updateEngineSFX(float dt)
*/
void Kart::updateEnginePowerAndBrakes(int ticks)
{
updateWeight();
updateNitro(ticks);
float engine_power = getActualWheelForce();
@ -2542,7 +2549,7 @@ void Kart::updateEnginePowerAndBrakes(int ticks)
{
// For a short time after a collision disable the engine,
// so that the karts can bounce back a bit from the obstacle.
if(m_bounce_back_ticks>0.0f)
if (m_bounce_back_ticks > 0)
engine_power = 0.0f;
// let a player going backwards accelerate quickly (e.g. if a player
// hits a wall, he needs to be able to start again quickly after
@ -2937,6 +2944,8 @@ void Kart::updateGraphics(float dt)
m_skid_sound->setPosition(getXYZ());
m_nitro_sound->setPosition(getXYZ());
m_attachment->updateGraphics(dt);
// update star effect (call will do nothing if stars are not activated)
m_stars_effect->update(dt);

View File

@ -214,6 +214,8 @@ protected:
float m_falling_time;
float m_weight;
/** 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;
@ -265,7 +267,7 @@ protected:
float getActualWheelForce();
void playCrashSFX(const Material* m, AbstractKart *k);
void loadData(RaceManager::KartType type, bool animatedModel);
void updateWeight();
public:
Kart(const std::string& ident, unsigned int world_kart_id,
int position, const btTransform& init_transform,
@ -276,7 +278,6 @@ public:
virtual void kartIsInRestNow() OVERRIDE;
virtual void updateGraphics(float dt) OVERRIDE;
virtual void createPhysics ();
virtual void updateWeight () OVERRIDE;
virtual float getSpeedForTurnRadius(float radius) const OVERRIDE;
virtual float getMaxSteerAngle(float speed) const;
virtual bool isInRest () const OVERRIDE;

View File

@ -22,6 +22,7 @@
#include "items/powerup.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/controller.hpp"
#include "karts/kart_properties.hpp"
#include "karts/max_speed.hpp"
#include "karts/skidding.hpp"
#include "modes/world.hpp"
@ -191,6 +192,9 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
// 3) Attachment, powerup, nitro
// ------------------------------
getAttachment()->rewindTo(buffer);
// Required for going back to anvil when rewinding
updateWeight();
getPowerup()->rewindTo(buffer);
m_min_nitro_ticks = buffer->getUInt8();
float nitro = buffer->getFloat();
@ -203,6 +207,7 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
// 6) Skidding
// -----------
m_skidding->rewindTo(buffer);
return;
} // restoreState
@ -218,6 +223,33 @@ void KartRewinder::update(int ticks)
// ----------------------------------------------------------------------------
void KartRewinder::rewindToEvent(BareNetworkString *buffer)
{
}; // rewindToEvent
} // rewindToEvent
// ----------------------------------------------------------------------------
std::function<void()> KartRewinder::getLocalStateRestoreFunction()
{
// In theory all ticks / boolean related stuff can be saved locally
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;
// Attachment local state
float initial_speed = getAttachment()->getInitialSpeed();
float node_scale = getAttachment()->getNodeScale();
return [bubblegum_ticks, bounce_back_ticks, invulnerable_ticks, squash_ticks,
fire_clicked, view_blocked_by_plunger, initial_speed,
node_scale, this]()
{
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;
getAttachment()->setInitialSpeed(initial_speed);
getAttachment()->setNodeScale(node_scale);
};
} // getLocalStateRestoreFunction

View File

@ -76,6 +76,9 @@ public:
virtual void undoEvent(BareNetworkString *p) OVERRIDE {}
// ------------------------------------------------------------------------
virtual bool enableSmoothing() const OVERRIDE { return true; }
// ------------------------------------------------------------------------
virtual std::function<void()> getLocalStateRestoreFunction() OVERRIDE;
}; // Rewinder
#endif

View File

@ -174,7 +174,6 @@ void addAttachment(Attachment::AttachmentType type)
stk_config->time2Ticks(kart->getKartProperties()
->getAnvilDuration()) );
kart->adjustSpeed(kart->getKartProperties()->getAnvilSpeedFactor());
kart->updateWeight();
}
else if (type == Attachment::ATTACH_PARACHUTE)
{