Redo swatter for network
This commit is contained in:
parent
17fd68e662
commit
9b8b0b7c1e
@ -43,6 +43,8 @@
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
#include <IAnimatedMeshSceneNode.h>
|
||||
|
||||
/** Initialises the attachment each kart has.
|
||||
*/
|
||||
Attachment::Attachment(AbstractKart* kart)
|
||||
@ -70,7 +72,6 @@ Attachment::Attachment(AbstractKart* kart)
|
||||
std::string debug_name = kart->getIdent()+" (attachment)";
|
||||
m_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_node->setAnimationEndCallback(this);
|
||||
m_node->setParent(m_kart->getNode());
|
||||
m_node->setVisible(false);
|
||||
} // Attachment
|
||||
@ -109,46 +110,19 @@ Attachment::~Attachment()
|
||||
*/
|
||||
void Attachment::set(AttachmentType type, int ticks,
|
||||
AbstractKart *current_kart,
|
||||
bool disable_swatter_animation,
|
||||
bool set_by_rewind_parachute)
|
||||
{
|
||||
bool was_bomb = m_type == ATTACH_BOMB;
|
||||
// Don't override currently player swatter removing bomb animation
|
||||
/*Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||
if (s && s->isRemovingBomb())
|
||||
return;
|
||||
|
||||
bool was_bomb = (m_type == ATTACH_BOMB) && !disable_swatter_animation;
|
||||
scene::ISceneNode* bomb_scene_node = NULL;
|
||||
if (was_bomb && type == ATTACH_SWATTER)
|
||||
{
|
||||
// let's keep the bomb node, and create a new one for
|
||||
// the new attachment
|
||||
bomb_scene_node = m_node;
|
||||
|
||||
m_node = irr_driver->addAnimatedMesh(
|
||||
attachment_manager->getMesh(Attachment::ATTACH_BOMB), "bomb");
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = m_kart->getIdent() + " (attachment)";
|
||||
m_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_node->setAnimationEndCallback(this);
|
||||
m_node->setParent(m_kart->getNode());
|
||||
m_node->setVisible(false);
|
||||
}*/
|
||||
|
||||
int16_t prev_ticks = m_ticks_left;
|
||||
clear();
|
||||
|
||||
// If necessary create the appropriate plugin which encapsulates
|
||||
// the associated behavior
|
||||
switch(type)
|
||||
{
|
||||
case ATTACH_SWATTER :
|
||||
//if (m_kart->getIdent() == "nolok")
|
||||
// m_node->setMesh(attachment_manager->getMesh(ATTACH_NOLOKS_SWATTER));
|
||||
//else
|
||||
// m_node->setMesh(attachment_manager->getMesh(type));
|
||||
//m_plugin = new Swatter(m_kart, was_bomb, bomb_scene_node, ticks);
|
||||
case ATTACH_SWATTER:
|
||||
m_plugin =
|
||||
new Swatter(m_kart, was_bomb ? prev_ticks : -1, ticks, this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -214,14 +188,12 @@ void Attachment::clear(bool update_graphical_now)
|
||||
void Attachment::saveState(BareNetworkString *buffer) const
|
||||
{
|
||||
// We use bit 6 to indicate if a previous owner is defined for a bomb,
|
||||
// bit 7 to indicate if the attachment is swatter removing animation
|
||||
// bit 7 to indicate if the attachment is a plugin
|
||||
assert(ATTACH_MAX < 64);
|
||||
uint8_t bit_7 = 0;
|
||||
Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||
if (s)
|
||||
if (m_plugin)
|
||||
{
|
||||
bit_7 = s->isRemovingBomb() ? 1 : 0;
|
||||
bit_7 <<= 7;
|
||||
bit_7 = 1 << 7;
|
||||
}
|
||||
uint8_t type = m_type | (( (m_type==ATTACH_BOMB) && (m_previous_owner!=NULL) )
|
||||
? (1 << 6) : 0 ) | bit_7;
|
||||
@ -233,6 +205,8 @@ void Attachment::saveState(BareNetworkString *buffer) const
|
||||
buffer->addUInt8(m_previous_owner->getWorldKartId());
|
||||
// m_initial_speed is not saved, on restore state it will
|
||||
// be set to the kart speed, which has already been restored
|
||||
if (m_plugin)
|
||||
m_plugin->saveState(buffer);
|
||||
}
|
||||
} // saveState
|
||||
|
||||
@ -243,19 +217,14 @@ void Attachment::saveState(BareNetworkString *buffer) const
|
||||
void Attachment::rewindTo(BareNetworkString *buffer)
|
||||
{
|
||||
uint8_t type = buffer->getUInt8();
|
||||
bool is_removing_bomb = (type >> 7 & 1) == 1;
|
||||
|
||||
Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||
// If locally removing a bomb
|
||||
if (s)
|
||||
is_removing_bomb = s->isRemovingBomb();
|
||||
bool is_plugin = (type >> 7 & 1) == 1;
|
||||
|
||||
// mask out bit 6 and 7
|
||||
AttachmentType new_type = AttachmentType(type & 63);
|
||||
type &= 127;
|
||||
|
||||
// If there is no attachment, clear the attachment if necessary and exit
|
||||
if (new_type == ATTACH_NOTHING && !is_removing_bomb)
|
||||
if (new_type == ATTACH_NOTHING)
|
||||
{
|
||||
if (m_type != new_type)
|
||||
clear();
|
||||
@ -277,9 +246,18 @@ void Attachment::rewindTo(BareNetworkString *buffer)
|
||||
m_previous_owner = NULL;
|
||||
}
|
||||
|
||||
// If playing kart animation, don't rewind to any attacment
|
||||
if (is_removing_bomb)
|
||||
return;
|
||||
if (is_plugin)
|
||||
{
|
||||
if (!m_plugin)
|
||||
m_plugin = new Swatter(m_kart, -1, 0, this);
|
||||
m_plugin->restoreState(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove unconfirmed plugin
|
||||
delete m_plugin;
|
||||
m_plugin = NULL;
|
||||
}
|
||||
|
||||
m_type = new_type;
|
||||
m_ticks_left = ticks_left;
|
||||
@ -475,17 +453,10 @@ void Attachment::update(int ticks)
|
||||
|
||||
if (m_plugin)
|
||||
{
|
||||
int discard_ticks = m_plugin->updateAndTestFinished(ticks);
|
||||
if (discard_ticks != -1)
|
||||
if (m_plugin->updateAndTestFinished(ticks))
|
||||
{
|
||||
// Save it for rewinding
|
||||
m_ticks_left =
|
||||
discard_ticks - World::getWorld()->getTicksSinceStart();
|
||||
if (m_ticks_left <= 0)
|
||||
{
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
}
|
||||
clear(); // also removes the plugin
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,7 +526,11 @@ void Attachment::updateGraphics(float dt)
|
||||
// Add the suitable graphical effects if different attachment is set
|
||||
if (m_type != m_graphical_type)
|
||||
{
|
||||
// Old attachement is cleared, add suitable sfx effects
|
||||
// Attachement is different, reset and add suitable sfx effects
|
||||
m_node->setPosition(core::vector3df(0.0f, 0.0f, 0.0f));
|
||||
m_node->setRotation(core::vector3df(0.0f, 0.0f, 0.0f));
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
m_node->setLoopMode(true);
|
||||
switch (m_type)
|
||||
{
|
||||
case ATTACH_NOTHING:
|
||||
@ -605,6 +580,9 @@ void Attachment::updateGraphics(float dt)
|
||||
m_graphical_type = m_type;
|
||||
}
|
||||
|
||||
if (m_plugin)
|
||||
m_plugin->updateGrahpics(dt);
|
||||
|
||||
if (m_type != ATTACH_NOTHING)
|
||||
{
|
||||
m_node->setVisible(true);
|
||||
@ -644,9 +622,6 @@ void Attachment::updateGraphics(float dt)
|
||||
else
|
||||
m_node->setVisible(false);
|
||||
|
||||
if (m_plugin)
|
||||
m_plugin->updateGrahpics(dt);
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case ATTACH_BOMB:
|
||||
@ -690,11 +665,3 @@ float Attachment::weightAdjust() const
|
||||
? m_kart->getKartProperties()->getAnvilWeight()
|
||||
: 0.0f;
|
||||
} // weightAdjust
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Inform any eventual plugin when an animation is done. */
|
||||
void Attachment::OnAnimationEnd(scene::IAnimatedMeshSceneNode* node)
|
||||
{
|
||||
if(m_plugin)
|
||||
m_plugin->onAnimationEnd();
|
||||
} // OnAnimationEnd
|
||||
|
@ -19,13 +19,16 @@
|
||||
#ifndef HEADER_ATTACHMENT_HPP
|
||||
#define HEADER_ATTACHMENT_HPP
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "items/attachment_plugin.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <IAnimatedMeshSceneNode.h>
|
||||
using namespace irr;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class IAnimatedMeshSceneNode; }
|
||||
}
|
||||
|
||||
class AbstractKart;
|
||||
class BareNetworkString;
|
||||
class ItemState;
|
||||
@ -44,7 +47,7 @@ class SFXBase;
|
||||
* a scene node).
|
||||
* \ingroup items
|
||||
*/
|
||||
class Attachment: public NoCopy, public scene::IAnimationEndCallBack
|
||||
class Attachment: public NoCopy
|
||||
{
|
||||
public:
|
||||
// Some loop in attachment.cpp depend on ATTACH_FIRST and ATTACH_MAX.
|
||||
@ -124,7 +127,6 @@ public:
|
||||
void handleCollisionWithKart(AbstractKart *other);
|
||||
void set (AttachmentType type, int ticks,
|
||||
AbstractKart *previous_kart=NULL,
|
||||
bool disable_swatter_animation = false,
|
||||
bool set_by_rewind_parachute = false);
|
||||
void rewindTo(BareNetworkString *buffer);
|
||||
void saveState(BareNetworkString *buffer) const;
|
||||
@ -153,13 +155,6 @@ public:
|
||||
/** Return the currently associated scene node (used by e.g the swatter) */
|
||||
scene::IAnimatedMeshSceneNode* getNode() {return m_node;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Implement IAnimatedMeshSceneNode */
|
||||
virtual void OnAnimationEnd(scene::IAnimatedMeshSceneNode* node);
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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) { }
|
||||
// ------------------------------------------------------------------------
|
||||
void reset()
|
||||
{
|
||||
clear();
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
class AbstractKart;
|
||||
class Attachment;
|
||||
class BareNetworkString;
|
||||
|
||||
/**
|
||||
* \ingroup items
|
||||
@ -38,13 +39,15 @@ class AttachmentPlugin
|
||||
{
|
||||
protected:
|
||||
/** Kart the attachment is attached to. */
|
||||
AbstractKart *m_kart;
|
||||
AbstractKart* m_kart;
|
||||
|
||||
Attachment* m_attachment;
|
||||
public:
|
||||
/** Constructor for a plugin. */
|
||||
AttachmentPlugin(AbstractKart *kart)
|
||||
AttachmentPlugin(AbstractKart *kart, Attachment* attachment)
|
||||
{
|
||||
m_kart = kart;
|
||||
m_kart = kart;
|
||||
m_attachment = attachment;
|
||||
}
|
||||
|
||||
virtual ~AttachmentPlugin() {}
|
||||
@ -53,13 +56,13 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Updates a plugin. This is called once each time frame. If the
|
||||
* function returns a non-negative number, the attachment is discarded
|
||||
* when world ticks >= that number. */
|
||||
virtual int updateAndTestFinished(int ticks) = 0;
|
||||
|
||||
* function returns true, the attachment is discarded. */
|
||||
virtual bool updateAndTestFinished(int ticks) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when the animation of the Attachment's node is done. */
|
||||
virtual void onAnimationEnd() {}
|
||||
virtual void restoreState(BareNetworkString *buffer) {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void saveState(BareNetworkString *buffer) const {}
|
||||
|
||||
}; // AttachmentPlugin
|
||||
|
||||
#endif
|
||||
|
@ -40,8 +40,7 @@
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/capture_the_flag.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/rewind_info.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
|
||||
#define SWAT_POS_OFFSET core::vector3df(0.0, 0.2f, -0.4f)
|
||||
@ -50,59 +49,39 @@
|
||||
#define SWAT_ANGLE_OFFSET (90.0f + 15.0f)
|
||||
#define SWATTER_ANIMATION_SPEED 100.0f
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor: creates a swatter at a given attachment for a kart. If there
|
||||
* was a bomb attached, it triggers the replace bomb animations.
|
||||
* \param attachment The attachment instance where the swatter is attached to.
|
||||
* \param kart The kart to which the swatter is attached.
|
||||
* \param was_bomb True if the kart had a bomb as attachment.
|
||||
* \param bomb_scene_node The scene node of the bomb (i.e. the previous
|
||||
* attachment scene node).
|
||||
* \param bomb_ticks Remaining bomb time in ticks, -1 if none.
|
||||
* \param ticks Swatter duration.
|
||||
* \param attachment class attachment from karts.
|
||||
*/
|
||||
Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
||||
scene::ISceneNode* bomb_scene_node, int ticks)
|
||||
: AttachmentPlugin(kart),
|
||||
m_swatter_start_ticks(World::getWorld()->getTicksSinceStart()),
|
||||
m_swatter_end_ticks(World::getWorld()->getTicksSinceStart() + ticks)
|
||||
Swatter::Swatter(AbstractKart *kart, int16_t bomb_ticks, int ticks,
|
||||
Attachment* attachment)
|
||||
: AttachmentPlugin(kart, attachment)
|
||||
{
|
||||
m_animation_phase = SWATTER_AIMING;
|
||||
m_discard_now = false;
|
||||
m_target = NULL;
|
||||
m_closest_kart = NULL;
|
||||
m_bomb_scene_node = bomb_scene_node;
|
||||
m_swat_bomb_frame = 0.0f;
|
||||
|
||||
// Setup the node
|
||||
m_scene_node = kart->getAttachment()->getNode();
|
||||
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
||||
|
||||
if (was_bomb)
|
||||
m_discard_ticks = World::getWorld()->getTicksSinceStart() + ticks;
|
||||
m_bomb_remaining = bomb_ticks;
|
||||
m_scene_node = NULL;
|
||||
m_bomb_scene_node = NULL;
|
||||
m_swatter_duration = stk_config->time2Ticks(
|
||||
kart->getKartProperties()->getSwatterDuration());
|
||||
if (m_bomb_remaining != -1)
|
||||
{
|
||||
m_scene_node->setMesh(attachment_manager
|
||||
->getMesh(Attachment::ATTACH_SWATTER_ANIM));
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
m_scene_node->setAnimationSpeed(0.9f);
|
||||
m_scene_node->setCurrentFrame(0.0f);
|
||||
m_scene_node->setLoopMode(false);
|
||||
// There are 40 frames in blender for swatter_anim.blender
|
||||
// so 40 / 25 * 120
|
||||
m_removed_bomb_ticks =
|
||||
World::getWorld()->getTicksSinceStart() + 192;
|
||||
m_discard_ticks =
|
||||
World::getWorld()->getTicksSinceStart() +
|
||||
stk_config->time2Ticks(40.0f / 25.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_removed_bomb_ticks = std::numeric_limits<int>::max();
|
||||
m_scene_node->setAnimationSpeed(0);
|
||||
}
|
||||
|
||||
m_swat_sound = NULL;
|
||||
m_start_swat_ticks = std::numeric_limits<int>::max();
|
||||
m_end_swat_ticks = std::numeric_limits<int>::max();
|
||||
#ifndef SERVER_ONLY
|
||||
if (kart->getIdent() == "nolok")
|
||||
m_swat_sound = SFXManager::get()->createSoundSource("hammer");
|
||||
else
|
||||
m_swat_sound = SFXManager::get()->createSoundSource("swatter");
|
||||
#endif
|
||||
m_swatter_animation_ticks = 0;
|
||||
m_played_swatter_animation = false;
|
||||
} // Swatter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -127,55 +106,139 @@ Swatter::~Swatter()
|
||||
void Swatter::updateGrahpics(float dt)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||
if (m_bomb_remaining != -1)
|
||||
{
|
||||
m_swat_bomb_frame += dt*25.0f;
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
|
||||
m_scene_node->setCurrentFrame(m_swat_bomb_frame);
|
||||
|
||||
if (m_swat_bomb_frame >= 32.5f && m_bomb_scene_node != NULL)
|
||||
if (!m_scene_node)
|
||||
{
|
||||
m_bomb_scene_node->setPosition(m_bomb_scene_node
|
||||
->getPosition() + core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
|
||||
m_bomb_scene_node->setRotation(m_bomb_scene_node
|
||||
->getRotation() + core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
|
||||
m_scene_node = m_kart->getAttachment()->getNode();
|
||||
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
||||
m_scene_node->setMesh(attachment_manager
|
||||
->getMesh(Attachment::ATTACH_SWATTER_ANIM));
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
m_scene_node->setAnimationSpeed(0.9f);
|
||||
m_scene_node->setCurrentFrame(0.0f);
|
||||
m_scene_node->setLoopMode(false);
|
||||
}
|
||||
|
||||
if (m_swat_bomb_frame >= m_scene_node->getEndFrame())
|
||||
if (!m_bomb_scene_node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (m_swat_bomb_frame >= 35)
|
||||
{
|
||||
if (m_bomb_scene_node != NULL)
|
||||
m_bomb_scene_node = irr_driver->addAnimatedMesh(
|
||||
attachment_manager->getMesh(Attachment::ATTACH_BOMB), "bomb");
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = m_kart->getIdent() + " (attachment)";
|
||||
m_bomb_scene_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_bomb_scene_node->setParent(m_kart->getNode());
|
||||
float time_left = stk_config->ticks2Time(m_bomb_remaining);
|
||||
if (time_left <= (m_bomb_scene_node->getEndFrame() -
|
||||
m_bomb_scene_node->getStartFrame() - 1))
|
||||
{
|
||||
irr_driver->removeNode(m_bomb_scene_node);
|
||||
m_bomb_scene_node = NULL;
|
||||
m_bomb_scene_node->setCurrentFrame(
|
||||
m_bomb_scene_node->getEndFrame()
|
||||
- m_bomb_scene_node->getStartFrame() - 1 - time_left);
|
||||
}
|
||||
m_bomb_scene_node->setAnimationSpeed(0.0f);
|
||||
}
|
||||
|
||||
float swat_bomb_frame = stk_config->ticks2Time(
|
||||
World::getWorld()->getTicksSinceStart() -
|
||||
(m_discard_ticks - stk_config->time2Ticks(40.0f / 25.0f)))
|
||||
* 25.0f;
|
||||
|
||||
if (swat_bomb_frame >= (float)m_scene_node->getEndFrame())
|
||||
swat_bomb_frame = (float)m_scene_node->getEndFrame();
|
||||
|
||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||
m_scene_node->setCurrentFrame(swat_bomb_frame);
|
||||
|
||||
if (swat_bomb_frame >= 32.5f && m_bomb_scene_node != NULL)
|
||||
{
|
||||
m_bomb_scene_node->setPosition(
|
||||
core::vector3df(-(swat_bomb_frame - 32.5f), 0.0f, 0.0f));
|
||||
m_bomb_scene_node->setRotation(
|
||||
core::vector3df(-(swat_bomb_frame - 32.5f), 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
if (swat_bomb_frame >= 35)
|
||||
{
|
||||
m_bomb_scene_node->setVisible(false);
|
||||
} // bom_frame > 35
|
||||
} // if removing bomb
|
||||
else
|
||||
{
|
||||
if (!m_scene_node)
|
||||
{
|
||||
m_scene_node = m_kart->getAttachment()->getNode();
|
||||
if (m_kart->getIdent() == "nolok")
|
||||
{
|
||||
m_scene_node->setMesh(attachment_manager
|
||||
->getMesh(Attachment::ATTACH_NOLOKS_SWATTER));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scene_node->setMesh(attachment_manager
|
||||
->getMesh(Attachment::ATTACH_SWATTER));
|
||||
}
|
||||
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
||||
m_scene_node->setLoopMode(false);
|
||||
m_scene_node->setAnimationSpeed(0.0f);
|
||||
}
|
||||
if (!m_swat_sound)
|
||||
{
|
||||
if (m_kart->getIdent() == "nolok")
|
||||
m_swat_sound = SFXManager::get()->createSoundSource("hammer");
|
||||
else
|
||||
m_swat_sound = SFXManager::get()->createSoundSource("swatter");
|
||||
}
|
||||
if (!m_discard_now)
|
||||
{
|
||||
switch (m_animation_phase)
|
||||
{
|
||||
case SWATTER_AIMING:
|
||||
{
|
||||
pointToTarget();
|
||||
m_played_swatter_animation = false;
|
||||
}
|
||||
break;
|
||||
case SWATTER_TO_TARGET:
|
||||
{
|
||||
if (!m_played_swatter_animation)
|
||||
{
|
||||
m_played_swatter_animation = true;
|
||||
// Setup the animation
|
||||
m_scene_node->setCurrentFrame(0.0f);
|
||||
m_scene_node->setAnimationSpeed(SWATTER_ANIMATION_SPEED);
|
||||
Vec3 swatter_pos =
|
||||
m_kart->getTrans()(Vec3(SWAT_POS_OFFSET));
|
||||
m_swat_sound->setPosition(swatter_pos);
|
||||
m_swat_sound->play();
|
||||
}
|
||||
pointToTarget();
|
||||
}
|
||||
break;
|
||||
case SWATTER_FROM_TARGET:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // updateGrahpics
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates an armed swatter: it checks for any karts that are close enough
|
||||
* and not invulnerable, it swats the kart.
|
||||
* \param dt Time step size.
|
||||
* \return World ticks to discard the swatter.
|
||||
* \param ticks Time step size.
|
||||
* \return True if the attachment should be discarded.
|
||||
*/
|
||||
int Swatter::updateAndTestFinished(int ticks)
|
||||
bool Swatter::updateAndTestFinished(int ticks)
|
||||
{
|
||||
const int ticks_start = World::getWorld()->getTicksSinceStart();
|
||||
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||
{
|
||||
if (ticks_start >= m_removed_bomb_ticks)
|
||||
return m_removed_bomb_ticks;
|
||||
return -1;
|
||||
} // if removing bomb
|
||||
if (World::getWorld()->getTicksSinceStart() > m_discard_ticks)
|
||||
return true;
|
||||
|
||||
if (RewindManager::get()->isRewinding())
|
||||
return -1;
|
||||
// If removing bomb animation playing, it will only ends when
|
||||
// m_discard_ticks > world ticks
|
||||
if (m_bomb_remaining != -1)
|
||||
return false;
|
||||
|
||||
if (!m_discard_now)
|
||||
{
|
||||
@ -185,13 +248,13 @@ int Swatter::updateAndTestFinished(int ticks)
|
||||
{
|
||||
// Avoid swatter near the start and the end lifetime of swatter
|
||||
// to make sure all clients know the existence of swatter each other
|
||||
if (ticks_start - m_swatter_start_ticks < 60 ||
|
||||
m_swatter_end_ticks - ticks_start < 60)
|
||||
return -1;
|
||||
if (m_swatter_duration - m_attachment->getTicksLeft() < 60 ||
|
||||
m_attachment->getTicksLeft() < 90) // ~20 and ~60 below
|
||||
return false;
|
||||
|
||||
chooseTarget();
|
||||
pointToTarget();
|
||||
if(!m_target || !m_closest_kart) break;
|
||||
if (!m_closest_kart)
|
||||
break;
|
||||
|
||||
// Get the node corresponding to the joint at the center of the
|
||||
// swatter (by swatter, I mean the thing hold in the hand, not
|
||||
@ -212,61 +275,45 @@ int Swatter::updateAndTestFinished(int ticks)
|
||||
{
|
||||
// Start squashing
|
||||
m_animation_phase = SWATTER_TO_TARGET;
|
||||
m_start_swat_ticks = ticks_start + 20;
|
||||
// Setup the animation
|
||||
m_scene_node->setCurrentFrame(0.0f);
|
||||
m_scene_node->setLoopMode(false);
|
||||
m_scene_node->setAnimationSpeed(SWATTER_ANIMATION_SPEED);
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
// Play swat sound
|
||||
m_swat_sound->setPosition(swatter_pos);
|
||||
m_swat_sound->play();
|
||||
#endif
|
||||
m_swatter_animation_ticks =
|
||||
m_attachment->getTicksLeft() - 20;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SWATTER_TO_TARGET:
|
||||
{
|
||||
pointToTarget();
|
||||
// Did we just finish the first part of the movement?
|
||||
if (ticks_start > m_start_swat_ticks)
|
||||
if (m_attachment->getTicksLeft() < m_swatter_animation_ticks &&
|
||||
m_attachment->getTicksLeft() > 60)
|
||||
{
|
||||
m_start_swat_ticks = std::numeric_limits<int>::max();
|
||||
// Squash the karts and items around and
|
||||
// change the current phase
|
||||
squashThingsAround();
|
||||
m_animation_phase = SWATTER_FROM_TARGET;
|
||||
const int end_ticks = ticks_start + 60;
|
||||
if (race_manager->isBattleMode() ||
|
||||
race_manager
|
||||
->getMinorMode()==RaceManager::MINOR_MODE_SOCCER)
|
||||
race_manager->isSoccerMode())
|
||||
{
|
||||
// Remove swatter from kart in arena gameplay
|
||||
// after one successful hit
|
||||
m_discard_now = true;
|
||||
m_discard_ticks = end_ticks;
|
||||
}
|
||||
m_end_swat_ticks = end_ticks;
|
||||
m_swatter_animation_ticks =
|
||||
m_attachment->getTicksLeft() - 60;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SWATTER_FROM_TARGET:
|
||||
{
|
||||
if (m_attachment->getTicksLeft() < m_swatter_animation_ticks &&
|
||||
m_attachment->getTicksLeft() > 0)
|
||||
m_animation_phase = SWATTER_AIMING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_discard_now)
|
||||
{
|
||||
return m_end_swat_ticks;
|
||||
}
|
||||
else if (ticks_start > m_end_swat_ticks)
|
||||
{
|
||||
m_animation_phase = SWATTER_AIMING;
|
||||
m_end_swat_ticks = std::numeric_limits<int>::max();
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
return false;
|
||||
} // updateAndTestFinished
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -303,8 +350,11 @@ void Swatter::chooseTarget()
|
||||
closest_kart = kart;
|
||||
}
|
||||
}
|
||||
m_target = closest_kart; // may be NULL
|
||||
m_closest_kart = closest_kart;
|
||||
// Not larger than 2^5 - 1 for kart id for optimizing state saving
|
||||
if (closest_kart->getWorldKartId() < 31)
|
||||
m_closest_kart = closest_kart;
|
||||
else
|
||||
m_closest_kart = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -313,16 +363,17 @@ void Swatter::chooseTarget()
|
||||
void Swatter::pointToTarget()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_kart->isGhostKart()) return;
|
||||
if (m_kart->isGhostKart() || !m_scene_node)
|
||||
return;
|
||||
|
||||
if(!m_target)
|
||||
if (!m_closest_kart)
|
||||
{
|
||||
m_scene_node->setRotation(core::vector3df());
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 swatter_to_target =
|
||||
m_kart->getTrans().inverse()(m_target->getXYZ());
|
||||
m_kart->getTrans().inverse()(m_closest_kart->getXYZ());
|
||||
float dy = -swatter_to_target.getZ();
|
||||
float dx = swatter_to_target.getX();
|
||||
float angle = SWAT_ANGLE_OFFSET + atan2f(dy, dx) * 180 / M_PI;
|
||||
@ -341,28 +392,13 @@ void Swatter::squashThingsAround()
|
||||
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
AbstractKart* closest_kart = m_closest_kart;
|
||||
float duration = kp->getSwatterSquashDuration();
|
||||
float slowdown = kp->getSwatterSquashSlowdown();
|
||||
// The squash attempt may fail because of invulnerability, shield, etc.
|
||||
// Making a bomb explode counts as a success
|
||||
bool success = closest_kart->setSquash(duration, slowdown);
|
||||
bool success = m_closest_kart->setSquash(duration, slowdown);
|
||||
const bool has_created_explosion_animation =
|
||||
success && closest_kart->getKartAnimation() != NULL;
|
||||
|
||||
// Locally add a event to replay the squash during rewind
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient() &&
|
||||
closest_kart->getKartAnimation() == NULL)
|
||||
{
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(),
|
||||
/*undo_function*/[](){},
|
||||
/*replay_function*/[closest_kart, duration, slowdown]()
|
||||
{
|
||||
closest_kart->setSquash(duration, slowdown);
|
||||
}));
|
||||
}
|
||||
success && m_closest_kart->getKartAnimation() != NULL;
|
||||
|
||||
if (success)
|
||||
{
|
||||
@ -390,7 +426,7 @@ void Swatter::squashThingsAround()
|
||||
}
|
||||
}
|
||||
|
||||
if (has_created_explosion_animation)
|
||||
if (has_created_explosion_animation && !RewindManager::get()->isRewinding())
|
||||
{
|
||||
HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", "explosion.xml");
|
||||
if(m_kart->getController()->isLocalPlayerController())
|
||||
@ -400,3 +436,52 @@ void Swatter::squashThingsAround()
|
||||
|
||||
// TODO: squash items
|
||||
} // squashThingsAround
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Swatter::restoreState(BareNetworkString* buffer)
|
||||
{
|
||||
int16_t prev_bomb_remaing = m_bomb_remaining;
|
||||
m_bomb_remaining = buffer->getUInt16();
|
||||
if (prev_bomb_remaing != m_bomb_remaining)
|
||||
{
|
||||
// Wrong state, clear mesh and let updateGraphics reset itself
|
||||
m_scene_node = NULL;
|
||||
if (m_bomb_scene_node)
|
||||
{
|
||||
irr_driver->removeNode(m_bomb_scene_node);
|
||||
m_bomb_scene_node = NULL;
|
||||
}
|
||||
}
|
||||
if (m_bomb_remaining == -1)
|
||||
{
|
||||
uint8_t combined = buffer->getUInt8();
|
||||
int kart_id = combined & 31;
|
||||
if (kart_id == 31)
|
||||
m_closest_kart = NULL;
|
||||
else
|
||||
m_closest_kart = World::getWorld()->getKart(kart_id);
|
||||
m_animation_phase = AnimationPhase((combined >> 5) & 3);
|
||||
m_discard_now = (combined >> 7) == 1;
|
||||
m_discard_ticks = buffer->getUInt32();
|
||||
m_swatter_animation_ticks = buffer->getUInt16();
|
||||
}
|
||||
else
|
||||
m_discard_ticks = buffer->getUInt32();
|
||||
} // restoreState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Swatter::saveState(BareNetworkString* buffer) const
|
||||
{
|
||||
buffer->addUInt16(m_bomb_remaining);
|
||||
if (m_bomb_remaining == -1)
|
||||
{
|
||||
uint8_t combined =
|
||||
m_closest_kart ? (uint8_t)m_closest_kart->getWorldKartId() : 31;
|
||||
combined |= m_animation_phase << 5;
|
||||
combined |= (m_discard_now ? (1 << 7) : 0);
|
||||
buffer->addUInt8(combined).addUInt32(m_discard_ticks)
|
||||
.addUInt16(m_swatter_animation_ticks);
|
||||
}
|
||||
else
|
||||
buffer->addUInt32(m_discard_ticks);
|
||||
} // saveState
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
using namespace irr;
|
||||
|
||||
class Attachment;
|
||||
class AbstractKart;
|
||||
class Item;
|
||||
class Moveable;
|
||||
@ -48,46 +49,49 @@ private:
|
||||
* - going down to the target
|
||||
* - going up from the target
|
||||
*/
|
||||
enum {SWATTER_AIMING, SWATTER_TO_TARGET, SWATTER_FROM_TARGET}
|
||||
m_animation_phase;
|
||||
|
||||
/** True if the swatter will be discarded now. */
|
||||
bool m_discard_now;
|
||||
enum AnimationPhase : uint8_t
|
||||
{
|
||||
SWATTER_AIMING = 0,
|
||||
SWATTER_TO_TARGET = 1,
|
||||
SWATTER_FROM_TARGET = 2
|
||||
};
|
||||
AnimationPhase m_animation_phase;
|
||||
|
||||
/** The kart the swatter is aiming at. */
|
||||
Moveable *m_target;
|
||||
|
||||
AbstractKart *m_closest_kart;
|
||||
|
||||
SFXBase *m_swat_sound;
|
||||
|
||||
/** Set the end ticks to complete the removing an attached bomb animation. */
|
||||
int m_removed_bomb_ticks;
|
||||
|
||||
/** The scene node of the attachment. */
|
||||
scene::IAnimatedMeshSceneNode *m_scene_node;
|
||||
|
||||
/** The scene node where a bomb is saved (in case that the swatter
|
||||
* replaces a bomb. */
|
||||
scene::ISceneNode *m_bomb_scene_node;
|
||||
scene::IAnimatedMeshSceneNode *m_bomb_scene_node;
|
||||
|
||||
/** For some reason the built-in animation system doesn't work correctly here?? */
|
||||
float m_swat_bomb_frame;
|
||||
int m_discard_ticks;
|
||||
|
||||
int m_start_swat_ticks;
|
||||
int m_swatter_duration;
|
||||
|
||||
int m_end_swat_ticks;
|
||||
/** Set the bomb remaing ticks so we can set the timer on the removing
|
||||
* bomb animation. */
|
||||
int16_t m_bomb_remaining;
|
||||
|
||||
const int m_swatter_start_ticks;
|
||||
int16_t m_swatter_animation_ticks;
|
||||
|
||||
const int m_swatter_end_ticks;
|
||||
/** True if the swatter will be discarded now. */
|
||||
bool m_discard_now;
|
||||
|
||||
/** True if the swatter animation has been played. */
|
||||
bool m_played_swatter_animation;
|
||||
public:
|
||||
Swatter(AbstractKart *kart, bool was_bomb,
|
||||
scene::ISceneNode* bomb_scene_node, int ticks);
|
||||
Swatter(AbstractKart *kart, int16_t bomb_ticks, int ticks,
|
||||
Attachment* attachment);
|
||||
virtual ~Swatter();
|
||||
void updateGrahpics(float dt) OVERRIDE;
|
||||
int updateAndTestFinished(int ticks) OVERRIDE;
|
||||
bool updateAndTestFinished(int ticks) OVERRIDE;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the swatter is currently aiming, i.e. can be used to
|
||||
@ -97,10 +101,9 @@ public:
|
||||
return m_animation_phase == SWATTER_AIMING;
|
||||
} // isSwatterReady
|
||||
// ------------------------------------------------------------------------
|
||||
bool isRemovingBomb() const
|
||||
{
|
||||
return m_removed_bomb_ticks != std::numeric_limits<int>::max();
|
||||
}
|
||||
virtual void restoreState(BareNetworkString *buffer) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void saveState(BareNetworkString *buffer) const OVERRIDE;
|
||||
|
||||
private:
|
||||
/** Determine the nearest kart or item and update the current target accordingly */
|
||||
|
@ -169,7 +169,6 @@ void GhostKart::update(int ticks)
|
||||
else if (attach_type != m_attachment->getType())
|
||||
{
|
||||
m_attachment->set(attach_type, attach_ticks, NULL,
|
||||
/*disable_swatter_animation*/false,
|
||||
/*set_by_rewind_parachute*/true);
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ void Kart::reset()
|
||||
m_saved_controller = NULL;
|
||||
}
|
||||
m_kart_model->setAnimation(KartModel::AF_DEFAULT);
|
||||
m_attachment->clear();
|
||||
m_attachment->reset();
|
||||
m_kart_gfx->reset();
|
||||
m_skidding->reset();
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "physics/btKart.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <ISceneNode.h>
|
||||
#include <string.h>
|
||||
|
||||
KartRewinder::KartRewinder(const std::string& ident,
|
||||
|
Loading…
Reference in New Issue
Block a user