Fix swatter in network
This commit is contained in:
parent
05f5663888
commit
f0b46d08b2
@ -56,7 +56,7 @@ Attachment::Attachment(AbstractKart* kart)
|
|||||||
m_previous_owner = NULL;
|
m_previous_owner = NULL;
|
||||||
m_bomb_sound = NULL;
|
m_bomb_sound = NULL;
|
||||||
m_bubble_explode_sound = NULL;
|
m_bubble_explode_sound = NULL;
|
||||||
m_node_scale = 1.0f;
|
m_node_scale = std::numeric_limits<float>::max();
|
||||||
m_initial_speed = 0.0f;
|
m_initial_speed = 0.0f;
|
||||||
|
|
||||||
// If we attach a NULL mesh, we get a NULL scene node back. So we
|
// If we attach a NULL mesh, we get a NULL scene node back. So we
|
||||||
@ -110,9 +110,15 @@ Attachment::~Attachment()
|
|||||||
* previous owner exists.
|
* previous owner exists.
|
||||||
*/
|
*/
|
||||||
void Attachment::set(AttachmentType type, int ticks,
|
void Attachment::set(AttachmentType type, int ticks,
|
||||||
AbstractKart *current_kart)
|
AbstractKart *current_kart,
|
||||||
|
bool disable_swatter_animation)
|
||||||
{
|
{
|
||||||
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;
|
scene::ISceneNode* bomb_scene_node = NULL;
|
||||||
if (was_bomb && type == ATTACH_SWATTER)
|
if (was_bomb && type == ATTACH_SWATTER)
|
||||||
{
|
{
|
||||||
@ -132,7 +138,6 @@ void Attachment::set(AttachmentType type, int ticks,
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
m_node_scale = 0.3f;
|
|
||||||
|
|
||||||
// If necessary create the appropriate plugin which encapsulates
|
// If necessary create the appropriate plugin which encapsulates
|
||||||
// the associated behavior
|
// the associated behavior
|
||||||
@ -160,7 +165,12 @@ void Attachment::set(AttachmentType type, int ticks,
|
|||||||
m_node->setCurrentFrame(0);
|
m_node->setCurrentFrame(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_node->setScale(core::vector3df(m_node_scale,m_node_scale,m_node_scale));
|
if (m_node_scale == std::numeric_limits<float>::max())
|
||||||
|
{
|
||||||
|
m_node_scale = 0.3f;
|
||||||
|
m_node->setScale(core::vector3df(m_node_scale, m_node_scale,
|
||||||
|
m_node_scale));
|
||||||
|
}
|
||||||
|
|
||||||
m_type = type;
|
m_type = type;
|
||||||
m_ticks_left = ticks;
|
m_ticks_left = ticks;
|
||||||
@ -238,14 +248,22 @@ void Attachment::clear()
|
|||||||
*/
|
*/
|
||||||
void Attachment::saveState(BareNetworkString *buffer) const
|
void Attachment::saveState(BareNetworkString *buffer) const
|
||||||
{
|
{
|
||||||
// We use bit 7 to indicate if a previous owner is defined for a bomb
|
// We use bit 6 to indicate if a previous owner is defined for a bomb,
|
||||||
assert(ATTACH_MAX<=127);
|
// bit 7 to indicate if the attachment is swatter removing animation
|
||||||
|
assert(ATTACH_MAX < 64);
|
||||||
|
uint8_t bit_7 = 0;
|
||||||
|
Swatter* s = dynamic_cast<Swatter*>(m_plugin);
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
bit_7 = s->isRemovingBomb() ? 1 : 0;
|
||||||
|
bit_7 <<= 7;
|
||||||
|
}
|
||||||
uint8_t type = m_type | (( (m_type==ATTACH_BOMB) && (m_previous_owner!=NULL) )
|
uint8_t type = m_type | (( (m_type==ATTACH_BOMB) && (m_previous_owner!=NULL) )
|
||||||
? 0x80 : 0 );
|
? (1 << 6) : 0 ) | bit_7;
|
||||||
buffer->addUInt8(type);
|
buffer->addUInt8(type);
|
||||||
if(m_type!=ATTACH_NOTHING)
|
if(m_type!=ATTACH_NOTHING)
|
||||||
{
|
{
|
||||||
buffer->addUInt32(m_ticks_left);
|
buffer->addUInt16(m_ticks_left);
|
||||||
if(m_type==ATTACH_BOMB && m_previous_owner)
|
if(m_type==ATTACH_BOMB && m_previous_owner)
|
||||||
buffer->addUInt8(m_previous_owner->getWorldKartId());
|
buffer->addUInt8(m_previous_owner->getWorldKartId());
|
||||||
// m_initial_speed is not saved, on restore state it will
|
// m_initial_speed is not saved, on restore state it will
|
||||||
@ -260,19 +278,29 @@ void Attachment::saveState(BareNetworkString *buffer) const
|
|||||||
void Attachment::rewindTo(BareNetworkString *buffer)
|
void Attachment::rewindTo(BareNetworkString *buffer)
|
||||||
{
|
{
|
||||||
uint8_t type = buffer->getUInt8();
|
uint8_t type = buffer->getUInt8();
|
||||||
AttachmentType new_type = AttachmentType(type & 0x7f); // mask out bit 7
|
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();
|
||||||
|
|
||||||
|
// 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 there is no attachment, clear the attachment if necessary and exit
|
||||||
if(new_type==ATTACH_NOTHING)
|
if (new_type == ATTACH_NOTHING && !is_removing_bomb)
|
||||||
{
|
{
|
||||||
if(m_type!=new_type) clear();
|
if (m_type != new_type)
|
||||||
|
clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ticks_left = buffer->getUInt32();
|
int16_t ticks_left = buffer->getUInt16();
|
||||||
|
|
||||||
// Now it is a new attachment:
|
// Now it is a new attachment:
|
||||||
if (type == (ATTACH_BOMB | 0x80)) // we have previous owner information
|
if (type == (ATTACH_BOMB | 64)) // we have previous owner information
|
||||||
{
|
{
|
||||||
uint8_t kart_id = buffer->getUInt8();
|
uint8_t kart_id = buffer->getUInt8();
|
||||||
m_previous_owner = World::getWorld()->getKart(kart_id);
|
m_previous_owner = World::getWorld()->getKart(kart_id);
|
||||||
@ -282,6 +310,10 @@ void Attachment::rewindTo(BareNetworkString *buffer)
|
|||||||
m_previous_owner = NULL;
|
m_previous_owner = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If playing kart animation, don't rewind to any attacment
|
||||||
|
if (is_removing_bomb)
|
||||||
|
return;
|
||||||
|
|
||||||
// Attaching an object can be expensive (loading new models, ...)
|
// Attaching an object can be expensive (loading new models, ...)
|
||||||
// so avoid doing this if there is no change in attachment type
|
// so avoid doing this if there is no change in attachment type
|
||||||
// Don't use set to reset a model on local player if it's already cleared
|
// Don't use set to reset a model on local player if it's already cleared
|
||||||
@ -294,7 +326,9 @@ void Attachment::rewindTo(BareNetworkString *buffer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set(new_type, ticks_left, m_previous_owner);
|
set(new_type, ticks_left, m_previous_owner,
|
||||||
|
new_type == ATTACH_SWATTER && !is_removing_bomb
|
||||||
|
/*disable_swatter_animation*/);
|
||||||
} // rewindTo
|
} // rewindTo
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -314,9 +348,7 @@ void Attachment::rewind(BareNetworkString *buffer)
|
|||||||
*/
|
*/
|
||||||
void Attachment::hitBanana(ItemState *item_state)
|
void Attachment::hitBanana(ItemState *item_state)
|
||||||
{
|
{
|
||||||
// Don't keep on getting achievements due to rewind!
|
if (m_kart->getController()->canGetAchievements())
|
||||||
if (m_kart->getController()->canGetAchievements() &&
|
|
||||||
!RewindManager::get()->isRewinding())
|
|
||||||
{
|
{
|
||||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_BANANA,
|
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_BANANA,
|
||||||
"banana", 1);
|
"banana", 1);
|
||||||
@ -501,8 +533,6 @@ void Attachment::update(int ticks)
|
|||||||
|
|
||||||
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
|
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
|
||||||
m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD;
|
m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD;
|
||||||
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);
|
int slow_flashes = stk_config->time2Ticks(3.0f);
|
||||||
if (is_shield && m_ticks_left < slow_flashes)
|
if (is_shield && m_ticks_left < slow_flashes)
|
||||||
{
|
{
|
||||||
@ -518,16 +548,6 @@ void Attachment::update(int ticks)
|
|||||||
m_node->setVisible((division & 0x1) == 0);
|
m_node->setVisible((division & 0x1) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float dt = stk_config->ticks2Time(ticks);
|
|
||||||
if (m_node_scale < wanted_node_scale)
|
|
||||||
{
|
|
||||||
m_node_scale += dt*1.5f;
|
|
||||||
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) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_plugin)
|
if(m_plugin)
|
||||||
{
|
{
|
||||||
bool discard = m_plugin->updateAndTestFinished(ticks);
|
bool discard = m_plugin->updateAndTestFinished(ticks);
|
||||||
@ -622,6 +642,26 @@ void Attachment::update(int ticks)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void Attachment::updateGraphics(float dt)
|
void Attachment::updateGraphics(float dt)
|
||||||
{
|
{
|
||||||
|
if (m_plugin)
|
||||||
|
m_plugin->updateGrahpics(dt);
|
||||||
|
|
||||||
|
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
|
||||||
|
m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD;
|
||||||
|
float wanted_node_scale = is_shield ?
|
||||||
|
std::max(1.0f, m_kart->getHighestPoint() * 1.1f) : 1.0f;
|
||||||
|
if (m_node_scale < wanted_node_scale)
|
||||||
|
{
|
||||||
|
m_node_scale += dt * 1.5f;
|
||||||
|
float scale = m_node_scale;
|
||||||
|
if (scale > wanted_node_scale)
|
||||||
|
scale = wanted_node_scale;
|
||||||
|
m_node->setScale(core::vector3df(scale, scale, scale));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_node_scale = std::numeric_limits<float>::max();
|
||||||
|
}
|
||||||
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case ATTACH_BOMB:
|
case ATTACH_BOMB:
|
||||||
@ -644,7 +684,6 @@ void Attachment::updateGraphics(float dt)
|
|||||||
m_bomb_sound->deleteSFX();
|
m_bomb_sound->deleteSFX();
|
||||||
m_bomb_sound = NULL;
|
m_bomb_sound = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // updateGraphics
|
} // updateGraphics
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -82,7 +82,7 @@ private:
|
|||||||
AbstractKart *m_kart;
|
AbstractKart *m_kart;
|
||||||
|
|
||||||
/** Time left till attachment expires. */
|
/** Time left till attachment expires. */
|
||||||
int m_ticks_left;
|
int16_t m_ticks_left;
|
||||||
|
|
||||||
/** For parachutes only. */
|
/** For parachutes only. */
|
||||||
float m_initial_speed;
|
float m_initial_speed;
|
||||||
@ -121,7 +121,8 @@ public:
|
|||||||
void update(int ticks);
|
void update(int ticks);
|
||||||
void handleCollisionWithKart(AbstractKart *other);
|
void handleCollisionWithKart(AbstractKart *other);
|
||||||
void set (AttachmentType type, int ticks,
|
void set (AttachmentType type, int ticks,
|
||||||
AbstractKart *previous_kart=NULL);
|
AbstractKart *previous_kart=NULL,
|
||||||
|
bool disable_swatter_animation = false);
|
||||||
virtual void rewind(BareNetworkString *buffer);
|
virtual void rewind(BareNetworkString *buffer);
|
||||||
void rewindTo(BareNetworkString *buffer);
|
void rewindTo(BareNetworkString *buffer);
|
||||||
void saveState(BareNetworkString *buffer) const;
|
void saveState(BareNetworkString *buffer) const;
|
||||||
@ -135,10 +136,10 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns how much time (in ticks) is left before this attachment is
|
/** Returns how much time (in ticks) is left before this attachment is
|
||||||
* removed. */
|
* removed. */
|
||||||
int getTicksLeft() const { return m_ticks_left; }
|
int16_t getTicksLeft() const { return m_ticks_left; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets how long this attachment will remain attached. */
|
/** Sets how long this attachment will remain attached. */
|
||||||
void setTicksLeft(int t){ m_ticks_left = t; }
|
void setTicksLeft(int16_t t) { m_ticks_left = t; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the previous owner of this attachment, used in bombs that
|
/** Returns the previous owner of this attachment, used in bombs that
|
||||||
* are being passed between karts. */
|
* are being passed between karts. */
|
||||||
@ -160,10 +161,6 @@ public:
|
|||||||
float getInitialSpeed() const { return m_initial_speed; }
|
float getInitialSpeed() const { return m_initial_speed; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void setInitialSpeed(float speed) { m_initial_speed = 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
|
}; // Attachment
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ public:
|
|||||||
|
|
||||||
virtual ~AttachmentPlugin() {}
|
virtual ~AttachmentPlugin() {}
|
||||||
|
|
||||||
|
virtual void updateGrahpics(float dt) = 0;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Updates a plugin. This is called once each time frame. If the
|
/** Updates a plugin. This is called once each time frame. If the
|
||||||
* function returns true, the attachment is discarded. */
|
* function returns true, the attachment is discarded. */
|
||||||
|
@ -34,12 +34,12 @@
|
|||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "items/attachment_manager.hpp"
|
#include "items/attachment_manager.hpp"
|
||||||
#include "items/projectile_manager.hpp"
|
#include "items/projectile_manager.hpp"
|
||||||
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/controller/controller.hpp"
|
#include "karts/controller/controller.hpp"
|
||||||
#include "karts/explosion_animation.hpp"
|
#include "karts/explosion_animation.hpp"
|
||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "modes/soccer_world.hpp"
|
#include "modes/soccer_world.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
|
||||||
|
|
||||||
#define SWAT_POS_OFFSET core::vector3df(0.0, 0.2f, -0.4f)
|
#define SWAT_POS_OFFSET core::vector3df(0.0, 0.2f, -0.4f)
|
||||||
#define SWAT_ANGLE_MIN 45
|
#define SWAT_ANGLE_MIN 45
|
||||||
@ -61,10 +61,9 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
|||||||
{
|
{
|
||||||
m_animation_phase = SWATTER_AIMING;
|
m_animation_phase = SWATTER_AIMING;
|
||||||
m_discard_now = false;
|
m_discard_now = false;
|
||||||
m_discard_timeout = 0.0f;
|
|
||||||
m_target = NULL;
|
m_target = NULL;
|
||||||
m_closest_kart = NULL;
|
m_closest_kart = NULL;
|
||||||
m_removing_bomb = was_bomb;
|
|
||||||
m_bomb_scene_node = bomb_scene_node;
|
m_bomb_scene_node = bomb_scene_node;
|
||||||
m_swat_bomb_frame = 0.0f;
|
m_swat_bomb_frame = 0.0f;
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
|||||||
m_scene_node = kart->getAttachment()->getNode();
|
m_scene_node = kart->getAttachment()->getNode();
|
||||||
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
m_scene_node->setPosition(SWAT_POS_OFFSET);
|
||||||
|
|
||||||
if (m_removing_bomb)
|
if (was_bomb)
|
||||||
{
|
{
|
||||||
m_scene_node->setMesh(attachment_manager
|
m_scene_node->setMesh(attachment_manager
|
||||||
->getMesh(Attachment::ATTACH_SWATTER_ANIM));
|
->getMesh(Attachment::ATTACH_SWATTER_ANIM));
|
||||||
@ -80,16 +79,26 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
|
|||||||
m_scene_node->setAnimationSpeed(0.9f);
|
m_scene_node->setAnimationSpeed(0.9f);
|
||||||
m_scene_node->setCurrentFrame(0.0f);
|
m_scene_node->setCurrentFrame(0.0f);
|
||||||
m_scene_node->setLoopMode(false);
|
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;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_removed_bomb_ticks = std::numeric_limits<int>::max();
|
||||||
m_scene_node->setAnimationSpeed(0);
|
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")
|
if (kart->getIdent() == "nolok")
|
||||||
m_swat_sound = SFXManager::get()->createSoundSource("hammer");
|
m_swat_sound = SFXManager::get()->createSoundSource("hammer");
|
||||||
else
|
else
|
||||||
m_swat_sound = SFXManager::get()->createSoundSource("swatter");
|
m_swat_sound = SFXManager::get()->createSoundSource("swatter");
|
||||||
|
#endif
|
||||||
} // Swatter
|
} // Swatter
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -102,24 +111,19 @@ Swatter::~Swatter()
|
|||||||
irr_driver->removeNode(m_bomb_scene_node);
|
irr_driver->removeNode(m_bomb_scene_node);
|
||||||
m_bomb_scene_node = NULL;
|
m_bomb_scene_node = NULL;
|
||||||
}
|
}
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
if (m_swat_sound)
|
if (m_swat_sound)
|
||||||
{
|
{
|
||||||
m_swat_sound->deleteSFX();
|
m_swat_sound->deleteSFX();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // ~Swatter
|
} // ~Swatter
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Updates an armed swatter: it checks for any karts that are close enough
|
void Swatter::updateGrahpics(float dt)
|
||||||
* and not invulnerable, it swats the kart.
|
|
||||||
* \param dt Time step size.
|
|
||||||
* \return True if the attachment should be discarded.
|
|
||||||
*/
|
|
||||||
bool Swatter::updateAndTestFinished(int ticks)
|
|
||||||
{
|
{
|
||||||
float dt = stk_config->ticks2Time(ticks);
|
#ifndef SERVER_ONLY
|
||||||
if (!m_discard_now)
|
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||||
{
|
|
||||||
if (m_removing_bomb)
|
|
||||||
{
|
{
|
||||||
m_swat_bomb_frame += dt*25.0f;
|
m_swat_bomb_frame += dt*25.0f;
|
||||||
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
m_scene_node->setRotation(core::vector3df(0.0, -180.0, 0.0));
|
||||||
@ -136,7 +140,7 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
|
|
||||||
if (m_swat_bomb_frame >= m_scene_node->getEndFrame())
|
if (m_swat_bomb_frame >= m_scene_node->getEndFrame())
|
||||||
{
|
{
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
else if (m_swat_bomb_frame >= 35)
|
else if (m_swat_bomb_frame >= 35)
|
||||||
{
|
{
|
||||||
@ -146,10 +150,27 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
m_bomb_scene_node = NULL;
|
m_bomb_scene_node = NULL;
|
||||||
}
|
}
|
||||||
} // bom_frame > 35
|
} // bom_frame > 35
|
||||||
|
} // if removing bomb
|
||||||
|
#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 True if the attachment should be discarded.
|
||||||
|
*/
|
||||||
|
bool Swatter::updateAndTestFinished(int ticks)
|
||||||
|
{
|
||||||
|
if (m_removed_bomb_ticks != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
if (World::getWorld()->getTicksSinceStart() >= m_removed_bomb_ticks)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
} // if removing bomb
|
} // if removing bomb
|
||||||
|
|
||||||
|
if (!m_discard_now)
|
||||||
|
{
|
||||||
switch (m_animation_phase)
|
switch (m_animation_phase)
|
||||||
{
|
{
|
||||||
case SWATTER_AIMING:
|
case SWATTER_AIMING:
|
||||||
@ -161,10 +182,14 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
// Get the node corresponding to the joint at the center of the
|
// Get the node corresponding to the joint at the center of the
|
||||||
// swatter (by swatter, I mean the thing hold in the hand, not
|
// swatter (by swatter, I mean the thing hold in the hand, not
|
||||||
// the whole thing)
|
// the whole thing)
|
||||||
scene::ISceneNode* swatter_node =
|
// The joint node doesn't update in server without graphics,
|
||||||
m_scene_node->getJointNode("Swatter");
|
// so an approximate position is used
|
||||||
assert(swatter_node);
|
//scene::ISceneNode* swatter_node =
|
||||||
Vec3 swatter_pos = swatter_node->getAbsolutePosition();
|
// m_scene_node->getJointNode("Swatter");
|
||||||
|
//assert(swatter_node);
|
||||||
|
//Vec3 swatter_pos = swatter_node->getAbsolutePosition();
|
||||||
|
Vec3 swatter_pos = m_kart->getTrans()(Vec3(SWAT_POS_OFFSET));
|
||||||
|
|
||||||
float dist2 = (m_closest_kart->getXYZ()-swatter_pos).length2();
|
float dist2 = (m_closest_kart->getXYZ()-swatter_pos).length2();
|
||||||
float min_dist2
|
float min_dist2
|
||||||
= m_kart->getKartProperties()->getSwatterDistance();
|
= m_kart->getKartProperties()->getSwatterDistance();
|
||||||
@ -173,31 +198,40 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
{
|
{
|
||||||
// Start squashing
|
// Start squashing
|
||||||
m_animation_phase = SWATTER_TO_TARGET;
|
m_animation_phase = SWATTER_TO_TARGET;
|
||||||
|
m_start_swat_ticks =
|
||||||
|
World::getWorld()->getTicksSinceStart() + 20;
|
||||||
// Setup the animation
|
// Setup the animation
|
||||||
m_scene_node->setCurrentFrame(0.0f);
|
m_scene_node->setCurrentFrame(0.0f);
|
||||||
m_scene_node->setLoopMode(false);
|
m_scene_node->setLoopMode(false);
|
||||||
m_scene_node->setAnimationSpeed(SWATTER_ANIMATION_SPEED);
|
m_scene_node->setAnimationSpeed(SWATTER_ANIMATION_SPEED);
|
||||||
|
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
// Play swat sound
|
// Play swat sound
|
||||||
|
const int wt = World::getWorld()->getTicksSinceStart();
|
||||||
|
auto it = m_swat_sound_ticks.find(wt);
|
||||||
|
if (it == m_swat_sound_ticks.end())
|
||||||
|
{
|
||||||
m_swat_sound->setPosition(swatter_pos);
|
m_swat_sound->setPosition(swatter_pos);
|
||||||
m_swat_sound->play();
|
m_swat_sound->play();
|
||||||
|
m_swat_sound_ticks.insert(wt);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SWATTER_TO_TARGET:
|
case SWATTER_TO_TARGET:
|
||||||
{
|
{
|
||||||
pointToTarget();
|
pointToTarget();
|
||||||
const float middle_frame = m_scene_node->getEndFrame()/2.0f;
|
|
||||||
float current_frame = m_scene_node->getFrameNr();
|
|
||||||
|
|
||||||
// Did we just finish the first part of the movement?
|
// Did we just finish the first part of the movement?
|
||||||
if(current_frame >= middle_frame)
|
if (World::getWorld()->getTicksSinceStart() > m_start_swat_ticks)
|
||||||
{
|
{
|
||||||
|
m_start_swat_ticks = std::numeric_limits<int>::max();
|
||||||
// Squash the karts and items around and
|
// Squash the karts and items around and
|
||||||
// change the current phase
|
// change the current phase
|
||||||
squashThingsAround();
|
squashThingsAround();
|
||||||
m_animation_phase = SWATTER_FROM_TARGET;
|
m_animation_phase = SWATTER_FROM_TARGET;
|
||||||
|
const int end_ticks =
|
||||||
|
World::getWorld()->getTicksSinceStart() + 60;
|
||||||
if (race_manager
|
if (race_manager
|
||||||
->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES ||
|
->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES ||
|
||||||
race_manager
|
race_manager
|
||||||
@ -207,6 +241,7 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
// after one successful hit
|
// after one successful hit
|
||||||
m_discard_now = true;
|
m_discard_now = true;
|
||||||
}
|
}
|
||||||
|
m_end_swat_ticks = end_ticks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -215,19 +250,19 @@ bool Swatter::updateAndTestFinished(int ticks)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_discard_timeout += dt;
|
|
||||||
|
|
||||||
return (m_discard_now && m_discard_timeout > 0.5f ? true : false);
|
if (m_discard_now)
|
||||||
} // updateAndTestFinished
|
{
|
||||||
|
return World::getWorld()->getTicksSinceStart() > m_end_swat_ticks;
|
||||||
// ----------------------------------------------------------------------------
|
}
|
||||||
/** When the animation ends, the swatter is ready again.
|
else if (World::getWorld()->getTicksSinceStart() > m_end_swat_ticks)
|
||||||
*/
|
|
||||||
void Swatter::onAnimationEnd()
|
|
||||||
{
|
{
|
||||||
m_animation_phase = SWATTER_AIMING;
|
m_animation_phase = SWATTER_AIMING;
|
||||||
} // onAnimationEnd
|
m_end_swat_ticks = std::numeric_limits<int>::max();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // updateAndTestFinished
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Determine the nearest kart or item and update the current target
|
/** Determine the nearest kart or item and update the current target
|
||||||
@ -275,6 +310,7 @@ void Swatter::chooseTarget()
|
|||||||
* default position. */
|
* default position. */
|
||||||
void Swatter::pointToTarget()
|
void Swatter::pointToTarget()
|
||||||
{
|
{
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
if(!m_target)
|
if(!m_target)
|
||||||
{
|
{
|
||||||
m_scene_node->setRotation(core::vector3df());
|
m_scene_node->setRotation(core::vector3df());
|
||||||
@ -288,6 +324,7 @@ void Swatter::pointToTarget()
|
|||||||
float angle = SWAT_ANGLE_OFFSET + atan2f(dy, dx) * 180 / M_PI;
|
float angle = SWAT_ANGLE_OFFSET + atan2f(dy, dx) * 180 / M_PI;
|
||||||
m_scene_node->setRotation(core::vector3df(0.0, angle, 0.0));
|
m_scene_node->setRotation(core::vector3df(0.0, angle, 0.0));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} // pointToTarget
|
} // pointToTarget
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -23,8 +23,9 @@
|
|||||||
#include "items/attachment_plugin.hpp"
|
#include "items/attachment_plugin.hpp"
|
||||||
#include "utils/cpp2011.hpp"
|
#include "utils/cpp2011.hpp"
|
||||||
#include "utils/no_copy.hpp"
|
#include "utils/no_copy.hpp"
|
||||||
#include "utils/random_generator.hpp"
|
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
#include <vector3d.h>
|
#include <vector3d.h>
|
||||||
#include <IAnimatedMeshSceneNode.h>
|
#include <IAnimatedMeshSceneNode.h>
|
||||||
|
|
||||||
@ -53,9 +54,6 @@ private:
|
|||||||
/** True if the swatter will be discarded now. */
|
/** True if the swatter will be discarded now. */
|
||||||
bool m_discard_now;
|
bool m_discard_now;
|
||||||
|
|
||||||
/** Require for the sfx to complete. */
|
|
||||||
float m_discard_timeout;
|
|
||||||
|
|
||||||
/** The kart the swatter is aiming at. */
|
/** The kart the swatter is aiming at. */
|
||||||
Moveable *m_target;
|
Moveable *m_target;
|
||||||
|
|
||||||
@ -63,8 +61,8 @@ private:
|
|||||||
|
|
||||||
SFXBase *m_swat_sound;
|
SFXBase *m_swat_sound;
|
||||||
|
|
||||||
/** True if the swatter is removing an attached bomb. */
|
/** Set the end ticks to complete the removing an attached bomb animation. */
|
||||||
bool m_removing_bomb;
|
int m_removed_bomb_ticks;
|
||||||
|
|
||||||
/** The scene node of the attachment. */
|
/** The scene node of the attachment. */
|
||||||
scene::IAnimatedMeshSceneNode *m_scene_node;
|
scene::IAnimatedMeshSceneNode *m_scene_node;
|
||||||
@ -76,21 +74,30 @@ private:
|
|||||||
/** For some reason the built-in animation system doesn't work correctly here?? */
|
/** For some reason the built-in animation system doesn't work correctly here?? */
|
||||||
float m_swat_bomb_frame;
|
float m_swat_bomb_frame;
|
||||||
|
|
||||||
|
std::set<int> m_swat_sound_ticks;
|
||||||
|
|
||||||
|
int m_start_swat_ticks;
|
||||||
|
|
||||||
|
int m_end_swat_ticks;
|
||||||
public:
|
public:
|
||||||
Swatter(AbstractKart *kart, bool was_bomb,
|
Swatter(AbstractKart *kart, bool was_bomb,
|
||||||
scene::ISceneNode* bomb_scene_node);
|
scene::ISceneNode* bomb_scene_node);
|
||||||
virtual ~Swatter();
|
virtual ~Swatter();
|
||||||
|
void updateGrahpics(float dt) OVERRIDE;
|
||||||
bool updateAndTestFinished(int ticks) OVERRIDE;
|
bool updateAndTestFinished(int ticks) OVERRIDE;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns if the swatter is currently aiming, i.e. can be used to
|
/** Returns if the swatter is currently aiming, i.e. can be used to
|
||||||
* swat an incoming projectile. */
|
* swat an incoming projectile. */
|
||||||
bool isSwatterReady() const {
|
bool isSwatterReady() const
|
||||||
|
{
|
||||||
return m_animation_phase == SWATTER_AIMING;
|
return m_animation_phase == SWATTER_AIMING;
|
||||||
} // isSwatterReady
|
} // isSwatterReady
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void onAnimationEnd() OVERRIDE;
|
bool isRemovingBomb() const
|
||||||
// ------------------------------------------------------------------------
|
{
|
||||||
|
return m_removed_bomb_ticks != std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Determine the nearest kart or item and update the current target accordingly */
|
/** Determine the nearest kart or item and update the current target accordingly */
|
||||||
|
@ -400,7 +400,8 @@ void LocalPlayerController::nitroNotFullSound()
|
|||||||
*/
|
*/
|
||||||
bool LocalPlayerController::canGetAchievements() const
|
bool LocalPlayerController::canGetAchievements() const
|
||||||
{
|
{
|
||||||
return m_player->getConstProfile() == PlayerManager::getCurrentPlayer();
|
return !RewindManager::get()->isRewinding() &&
|
||||||
|
m_player->getConstProfile() == PlayerManager::getCurrentPlayer();
|
||||||
} // canGetAchievements
|
} // canGetAchievements
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -36,6 +36,8 @@ public:
|
|||||||
{
|
{
|
||||||
} // ~NetworkPlayerController
|
} // ~NetworkPlayerController
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
virtual bool canGetAchievements() const OVERRIDE { return false; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** This player is not a local player. This affect e.g. special sfx and
|
/** This player is not a local player. This affect e.g. special sfx and
|
||||||
* camera effects to be triggered. */
|
* camera effects to be triggered. */
|
||||||
virtual bool isLocalPlayerController() const OVERRIDE
|
virtual bool isLocalPlayerController() const OVERRIDE
|
||||||
|
@ -2939,7 +2939,7 @@ void Kart::updateGraphics(float dt)
|
|||||||
if (m_custom_sounds[n] != NULL) m_custom_sounds[n]->position(getXYZ());
|
if (m_custom_sounds[n] != NULL) m_custom_sounds[n]->position(getXYZ());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
if (m_squash_time != std::numeric_limits<float>::max())
|
if (m_squash_time != std::numeric_limits<float>::max())
|
||||||
{
|
{
|
||||||
m_squash_time -= dt;
|
m_squash_time -= dt;
|
||||||
@ -2962,6 +2962,7 @@ void Kart::updateGraphics(float dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // if squashed
|
} // if squashed
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < EMITTER_COUNT; i++)
|
for (int i = 0; i < EMITTER_COUNT; i++)
|
||||||
m_emitters[i]->setPosition(getXYZ());
|
m_emitters[i]->setPosition(getXYZ());
|
||||||
|
@ -252,7 +252,6 @@ std::function<void()> KartRewinder::getLocalStateRestoreFunction()
|
|||||||
|
|
||||||
// Attachment local state
|
// Attachment local state
|
||||||
float initial_speed = getAttachment()->getInitialSpeed();
|
float initial_speed = getAttachment()->getInitialSpeed();
|
||||||
float node_scale = getAttachment()->getNodeScale();
|
|
||||||
|
|
||||||
// Controller local state
|
// Controller local state
|
||||||
int steer_val_l = 0;
|
int steer_val_l = 0;
|
||||||
@ -265,14 +264,13 @@ std::function<void()> KartRewinder::getLocalStateRestoreFunction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [has_started, bounce_back_ticks, brake_ticks, min_nitro_ticks,
|
return [has_started, bounce_back_ticks, brake_ticks, min_nitro_ticks,
|
||||||
initial_speed, node_scale, steer_val_l, steer_val_r, this]()
|
initial_speed, steer_val_l, steer_val_r, this]()
|
||||||
{
|
{
|
||||||
m_has_started = has_started;
|
m_has_started = has_started;
|
||||||
m_bounce_back_ticks = bounce_back_ticks;
|
m_bounce_back_ticks = bounce_back_ticks;
|
||||||
m_brake_ticks = brake_ticks;
|
m_brake_ticks = brake_ticks;
|
||||||
m_min_nitro_ticks = min_nitro_ticks;
|
m_min_nitro_ticks = min_nitro_ticks;
|
||||||
getAttachment()->setInitialSpeed(initial_speed);
|
getAttachment()->setInitialSpeed(initial_speed);
|
||||||
getAttachment()->setNodeScale(node_scale);
|
|
||||||
PlayerController* pc = dynamic_cast<PlayerController*>(m_controller);
|
PlayerController* pc = dynamic_cast<PlayerController*>(m_controller);
|
||||||
if (pc)
|
if (pc)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user