Handle graphical models of attachment in updateGraphics

This commit is contained in:
Benau 2019-03-01 18:46:46 +08:00
parent c57af03b62
commit 17fd68e662
3 changed files with 109 additions and 103 deletions

View File

@ -54,9 +54,9 @@ 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 = std::numeric_limits<float>::max();
m_initial_speed = 0.0f; m_initial_speed = 0.0f;
m_graphical_type = ATTACH_NOTHING; m_graphical_type = ATTACH_NOTHING;
m_scaling_end_ticks = -1;
// 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
// have to attach some kind of mesh, but make it invisible. // have to attach some kind of mesh, but make it invisible.
if (kart->isGhostKart()) if (kart->isGhostKart())
@ -112,8 +112,9 @@ void Attachment::set(AttachmentType type, int ticks,
bool disable_swatter_animation, bool disable_swatter_animation,
bool set_by_rewind_parachute) bool set_by_rewind_parachute)
{ {
bool was_bomb = m_type == ATTACH_BOMB;
// Don't override currently player swatter removing bomb animation // Don't override currently player swatter removing bomb animation
Swatter* s = dynamic_cast<Swatter*>(m_plugin); /*Swatter* s = dynamic_cast<Swatter*>(m_plugin);
if (s && s->isRemovingBomb()) if (s && s->isRemovingBomb())
return; return;
@ -134,7 +135,7 @@ void Attachment::set(AttachmentType type, int ticks,
m_node->setAnimationEndCallback(this); m_node->setAnimationEndCallback(this);
m_node->setParent(m_kart->getNode()); m_node->setParent(m_kart->getNode());
m_node->setVisible(false); m_node->setVisible(false);
} }*/
clear(); clear();
@ -143,38 +144,21 @@ void Attachment::set(AttachmentType type, int ticks,
switch(type) switch(type)
{ {
case ATTACH_SWATTER : case ATTACH_SWATTER :
if (m_kart->getIdent() == "nolok") //if (m_kart->getIdent() == "nolok")
m_node->setMesh(attachment_manager->getMesh(ATTACH_NOLOKS_SWATTER)); // m_node->setMesh(attachment_manager->getMesh(ATTACH_NOLOKS_SWATTER));
else //else
m_node->setMesh(attachment_manager->getMesh(type)); // m_node->setMesh(attachment_manager->getMesh(type));
m_plugin = new Swatter(m_kart, was_bomb, bomb_scene_node, ticks); //m_plugin = new Swatter(m_kart, was_bomb, bomb_scene_node, ticks);
break;
case ATTACH_BOMB:
m_node->setMesh(attachment_manager->getMesh(type));
m_node->setAnimationSpeed(0);
break; break;
default: default:
m_node->setMesh(attachment_manager->getMesh(type));
break; break;
} // switch(type) } // switch(type)
if (UserConfigParams::m_particles_effects < 2)
{
m_node->setAnimationSpeed(0);
m_node->setCurrentFrame(0);
}
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;
m_previous_owner = current_kart; m_previous_owner = current_kart;
m_node->setRotation(core::vector3df(0, 0, 0)); m_scaling_end_ticks = World::getWorld()->getTicksSinceStart() +
stk_config->time2Ticks(0.7f);
// A parachute can be attached as result of the usage of an item. In this // A parachute can be attached as result of the usage of an item. In this
// case we have to save the current kart speed so that it can be detached // case we have to save the current kart speed so that it can be detached
@ -200,14 +184,7 @@ void Attachment::set(AttachmentType type, int ticks,
speed_mult = 1.0f + (f * (temp_mult - 1.0f)); speed_mult = 1.0f + (f * (temp_mult - 1.0f));
m_ticks_left = int(m_ticks_left * speed_mult); m_ticks_left = int(m_ticks_left * speed_mult);
if (UserConfigParams::m_particles_effects > 1)
{
// .blend was created @25 (<10 real, slow computer), make it faster
m_node->setAnimationSpeed(50);
} }
}
m_node->setVisible(true);
} // set } // set
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -215,7 +192,7 @@ void Attachment::set(AttachmentType type, int ticks,
* takes care of resetting the owner kart's physics structures to account for * takes care of resetting the owner kart's physics structures to account for
* the updated mass. * the updated mass.
*/ */
void Attachment::clear() void Attachment::clear(bool update_graphical_now)
{ {
if(m_plugin) if(m_plugin)
{ {
@ -226,9 +203,8 @@ void Attachment::clear()
m_type=ATTACH_NOTHING; m_type=ATTACH_NOTHING;
m_ticks_left = 0; m_ticks_left = 0;
m_node->setVisible(false); if (update_graphical_now)
m_node->setPosition(core::vector3df()); updateGraphicalTypeNow();
m_node->setRotation(core::vector3df());
} // clear } // clear
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -305,18 +281,8 @@ void Attachment::rewindTo(BareNetworkString *buffer)
if (is_removing_bomb) if (is_removing_bomb)
return; return;
// Attaching an object can be expensive (loading new models, ...) m_type = new_type;
// so avoid doing this if there is no change in attachment type m_ticks_left = ticks_left;
if (m_type == new_type)
{
setTicksLeft(ticks_left);
return;
}
set(new_type, ticks_left, m_previous_owner,
new_type == ATTACH_SWATTER && !is_removing_bomb
/*disable_swatter_animation*/,
new_type == ATTACH_PARACHUTE);
} // rewindTo } // rewindTo
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -466,7 +432,7 @@ void Attachment::handleCollisionWithKart(AbstractKart *other)
stk_config->m_bomb_time_increase), stk_config->m_bomb_time_increase),
m_kart); m_kart);
other->playCustomSFX(SFXManager::CUSTOM_ATTACH); other->playCustomSFX(SFXManager::CUSTOM_ATTACH);
clear(); clear(true/*update_graphical_now*/);
} }
} }
} // type==BOMB } // type==BOMB
@ -484,7 +450,7 @@ void Attachment::handleCollisionWithKart(AbstractKart *other)
other->getAttachment()->getTicksLeft()+ other->getAttachment()->getTicksLeft()+
stk_config->time2Ticks(stk_config->m_bomb_time_increase), stk_config->time2Ticks(stk_config->m_bomb_time_increase),
other); other);
other->getAttachment()->clear(); other->getAttachment()->clear(true/*update_graphical_now*/);
m_kart->playCustomSFX(SFXManager::CUSTOM_ATTACH); m_kart->playCustomSFX(SFXManager::CUSTOM_ATTACH);
} }
else else
@ -507,23 +473,6 @@ void Attachment::update(int ticks)
m_ticks_left -= ticks; m_ticks_left -= ticks;
bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD ||
m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD;
int slow_flashes = stk_config->time2Ticks(3.0f);
if (is_shield && m_ticks_left < slow_flashes)
{
int ticks_per_flash = stk_config->time2Ticks(0.2f);
int fast_flashes = stk_config->time2Ticks(0.5f);
if (m_ticks_left < fast_flashes)
{
ticks_per_flash = stk_config->time2Ticks(0.07f);
}
int division = (m_ticks_left / ticks_per_flash);
m_node->setVisible((division & 0x1) == 0);
}
if (m_plugin) if (m_plugin)
{ {
int discard_ticks = m_plugin->updateAndTestFinished(ticks); int discard_ticks = m_plugin->updateAndTestFinished(ticks);
@ -578,15 +527,6 @@ void Attachment::update(int ticks)
break; break;
case ATTACH_BOMB: case ATTACH_BOMB:
{ {
// 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!"
float time_left = stk_config->ticks2Time(m_ticks_left);
if (time_left <= (m_node->getEndFrame() - m_node->getStartFrame() - 1))
{
m_node->setCurrentFrame(m_node->getEndFrame()
- m_node->getStartFrame() - 1 - time_left);
}
if (m_ticks_left <= 0) if (m_ticks_left <= 0)
{ {
if (m_kart->getKartAnimation() == NULL) if (m_kart->getKartAnimation() == NULL)
@ -612,30 +552,13 @@ 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();
}
// Add the suitable graphical effects if different attachment is set // Add the suitable graphical effects if different attachment is set
if (m_type != m_graphical_type) if (m_type != m_graphical_type)
{ {
if (m_type == ATTACH_NOTHING) // Old attachement is cleared, add suitable sfx effects
switch (m_type)
{
case ATTACH_NOTHING:
{ {
if (m_graphical_type == ATTACH_BOMB) if (m_graphical_type == ATTACH_BOMB)
{ {
@ -657,10 +580,73 @@ void Attachment::updateGraphics(float dt)
m_bubble_explode_sound->setPosition(m_kart->getXYZ()); m_bubble_explode_sound->setPosition(m_kart->getXYZ());
m_bubble_explode_sound->play(); m_bubble_explode_sound->play();
} }
break;
}
case ATTACH_SWATTER:
// Graphical model set in swatter class
break;
default:
m_node->setMesh(attachment_manager->getMesh(m_type));
break;
} // switch(type)
if (UserConfigParams::m_particles_effects < 2 &&
m_type != ATTACH_NOTHING)
{
m_node->setAnimationSpeed(0);
m_node->setCurrentFrame(0);
}
if (UserConfigParams::m_particles_effects > 1 &&
m_type == ATTACH_PARACHUTE)
{
// .blend was created @25 (<10 real, slow computer), make it faster
m_node->setAnimationSpeed(50);
} }
m_graphical_type = m_type; m_graphical_type = m_type;
} }
if (m_type != ATTACH_NOTHING)
{
m_node->setVisible(true);
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;
float scale_ratio = stk_config->ticks2Time(m_scaling_end_ticks -
World::getWorld()->getTicksSinceStart()) / 0.7f;
if (scale_ratio > 0.0f)
{
float scale = 0.3 * scale_ratio +
wanted_node_scale * (1.0f - scale_ratio);
m_node->setScale(core::vector3df(scale, scale, scale));
}
else
{
m_node->setScale(core::vector3df(
wanted_node_scale, wanted_node_scale, wanted_node_scale));
}
int slow_flashes = stk_config->time2Ticks(3.0f);
if (is_shield && m_ticks_left < slow_flashes)
{
// Bubble gum flashing when close to dropping
int ticks_per_flash = stk_config->time2Ticks(0.2f);
int fast_flashes = stk_config->time2Ticks(0.5f);
if (m_ticks_left < fast_flashes)
{
ticks_per_flash = stk_config->time2Ticks(0.07f);
}
int division = (m_ticks_left / ticks_per_flash);
m_node->setVisible((division & 0x1) == 0);
}
}
else
m_node->setVisible(false);
if (m_plugin)
m_plugin->updateGrahpics(dt);
switch (m_type) switch (m_type)
{ {
case ATTACH_BOMB: case ATTACH_BOMB:
@ -672,6 +658,15 @@ void Attachment::updateGraphics(float dt)
m_bomb_sound->play(); m_bomb_sound->play();
} }
m_bomb_sound->setPosition(m_kart->getXYZ()); 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!"
float time_left = stk_config->ticks2Time(m_ticks_left);
if (time_left <= (m_node->getEndFrame() - m_node->getStartFrame() - 1))
{
m_node->setCurrentFrame(m_node->getEndFrame()
- m_node->getStartFrame() - 1 - time_left);
}
return; return;
} }
default: default:

View File

@ -88,7 +88,7 @@ private:
float m_initial_speed; float m_initial_speed;
/** For zoom-in animation */ /** For zoom-in animation */
float m_node_scale; int m_scaling_end_ticks;
/** Scene node of the attachment, which will be attached to the kart's /** Scene node of the attachment, which will be attached to the kart's
* scene node. */ * scene node. */
@ -105,13 +105,18 @@ private:
/** Ticking sound for the bomb */ /** Ticking sound for the bomb */
SFXBase *m_bomb_sound; SFXBase *m_bomb_sound;
/** Soung for exploding bubble gum shield */ /** Sound for exploding bubble gum shield */
SFXBase *m_bubble_explode_sound; SFXBase *m_bubble_explode_sound;
// ------------------------------------------------------------------------
/** Called in clear() to update m_graphical_type now, so for example
* the explosion sfx or bubblegum sound is not displayed or played when
* the bomb or shield is forcely cleared like in kart animation. */
void updateGraphicalTypeNow() { m_graphical_type = m_type; }
public: public:
Attachment(AbstractKart* kart); Attachment(AbstractKart* kart);
~Attachment(); ~Attachment();
void clear (); void clear (bool update_graphical_now = false);
void hitBanana(ItemState *item); void hitBanana(ItemState *item);
void updateGraphics(float dt); void updateGraphics(float dt);
@ -155,6 +160,12 @@ public:
* will take care of creating the right attachment. */ * will take care of creating the right attachment. */
virtual void undo(BareNetworkString *buffer) { } virtual void undo(BareNetworkString *buffer) { }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void reset()
{
clear();
m_scaling_end_ticks = -1;
}
// ------------------------------------------------------------------------
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; }

View File

@ -62,7 +62,7 @@ RescueAnimation::RescueAnimation(AbstractKart* kart, bool is_auto_rescue)
float velocity = max_height / timer; float velocity = max_height / timer;
init(rescue_transform, velocity); init(rescue_transform, velocity);
m_kart->getAttachment()->clear(); m_kart->getAttachment()->clear(true/*update_graphical_now*/);
// Add a hit unless it was auto-rescue // Add a hit unless it was auto-rescue
if (race_manager->isBattleMode() && if (race_manager->isBattleMode() &&