Merged bubble bum branch into trunk. The new bubble gum
shield is still work in progress. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@13444 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
72a2b69695
commit
df9d90b342
@ -74,6 +74,9 @@
|
||||
|
||||
* rubber_ball-icon, plunger icon, cake icon, bowling ball texture and icon
|
||||
by Totoplus62, released under CC-BY-SA 3.0
|
||||
|
||||
* shield-icon
|
||||
by tuxfan, release under CC-BY-SA 3.0
|
||||
|
||||
|
||||
Others are GPL, by the original (super)TuxKart team
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 64 KiB |
BIN
data/models/bubblegum_shield.b3d
Normal file
BIN
data/models/bubblegum_shield.b3d
Normal file
Binary file not shown.
BIN
data/models/bubblegum_shield.png
Normal file
BIN
data/models/bubblegum_shield.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
data/models/shield-icon.png
Normal file
BIN
data/models/shield-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
@ -114,8 +114,10 @@
|
||||
nolok-bubble-gum, easter egg -->
|
||||
<switch time="5" items="1 0 4 4 2 5 2 7"/>
|
||||
|
||||
<!-- How often bubblegum get driven over before it disappears. -->
|
||||
<bubblegum disappear-counter="1"/>
|
||||
<!-- disappear-counter: How often bubblegum gets driven over before it disappears.
|
||||
shield-time: How long the bubblegum shield lasts
|
||||
restrict-weapons: If true, using weapons will destroy the user's shield -->
|
||||
<bubblegum disappear-counter="1" shield-time="10.0" restrict-weapons="false"/>
|
||||
|
||||
<!-- explosion-impulse-objects is the impulse that pushes physical objects
|
||||
away if there is an explosion. -->
|
||||
|
@ -118,6 +118,7 @@ void STKConfig::load(const std::string &filename)
|
||||
CHECK_NEG(m_anvil_weight, "anvil-weight" );
|
||||
CHECK_NEG(m_item_switch_time, "item-switch-time" );
|
||||
CHECK_NEG(m_bubblegum_counter, "bubblegum disappear counter");
|
||||
CHECK_NEG(m_bubblegum_shield_time, "bubblegum shield-time" );
|
||||
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
|
||||
CHECK_NEG(m_max_history, "max-history" );
|
||||
CHECK_NEG(m_max_skidmarks, "max-skidmarks" );
|
||||
@ -159,6 +160,8 @@ void STKConfig::init_defaults()
|
||||
m_smooth_angle_limit =
|
||||
m_penalty_time = m_explosion_impulse_objects = UNDEFINED;
|
||||
m_bubblegum_counter = -100;
|
||||
m_bubblegum_shield_time = -100;
|
||||
m_shield_restrict_weapos = false;
|
||||
m_max_karts = -100;
|
||||
m_max_history = -100;
|
||||
m_max_skidmarks = -100;
|
||||
@ -335,7 +338,9 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
|
||||
if(const XMLNode *bubblegum_node= root->getNode("bubblegum"))
|
||||
{
|
||||
bubblegum_node->get("disappear-counter", &m_bubblegum_counter);
|
||||
bubblegum_node->get("disappear-counter", &m_bubblegum_counter );
|
||||
bubblegum_node->get("shield-time", &m_bubblegum_shield_time );
|
||||
bubblegum_node->get("restrict-weapons", &m_shield_restrict_weapos);
|
||||
}
|
||||
|
||||
if(const XMLNode *explosion_node= root->getNode("explosion"))
|
||||
|
@ -74,8 +74,10 @@ public:
|
||||
passed on. */
|
||||
float m_anvil_time; /**<Time an anvil is active. */
|
||||
float m_item_switch_time; /**< Time items will be switched. */
|
||||
int m_bubblegum_counter; /**< How many times bananas must be eaten
|
||||
before they disappear. */
|
||||
int m_bubblegum_counter; /**< How many times bubble gums must be
|
||||
driven over before they disappear. */
|
||||
float m_bubblegum_shield_time; /**<How long a bubble gum shield lasts. */
|
||||
bool m_shield_restrict_weapos; /**<Wether weapon usage is punished. */
|
||||
float m_explosion_impulse_objects;/**<Impulse of explosion on moving
|
||||
objects, e.g. road cones, ... */
|
||||
float m_penalty_time; /**< Penalty time when starting too
|
||||
|
@ -36,7 +36,8 @@
|
||||
#include "network/race_state.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
// Log::verbose("attachment", "Decreasing shield \n");
|
||||
/** Initialises the attachment each kart has.
|
||||
*/
|
||||
Attachment::Attachment(AbstractKart* kart)
|
||||
@ -92,7 +93,7 @@ void Attachment::set(AttachmentType type, float time,
|
||||
{
|
||||
bool was_bomb = (m_type == ATTACH_BOMB);
|
||||
scene::ISceneNode* bomb_scene_node = NULL;
|
||||
if (was_bomb && type == ATTACH_SWATTER)
|
||||
if (was_bomb && type == ATTACH_SWATTER) //What about ATTACH_NOLOKS_SWATTER ??
|
||||
{
|
||||
// let's keep the bomb node, and create a new one for
|
||||
// the new attachment
|
||||
@ -206,6 +207,13 @@ void Attachment::clear()
|
||||
*/
|
||||
void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
{
|
||||
//Bubble gum shield effect:
|
||||
if(m_type == ATTACH_BUBBLEGUM_SHIELD)
|
||||
{
|
||||
m_time_left -= stk_config->m_bubblegum_shield_time;
|
||||
return;
|
||||
}
|
||||
|
||||
float leftover_time = 0.0f;
|
||||
|
||||
bool add_a_new_item = true;
|
||||
@ -414,6 +422,18 @@ void Attachment::update(float dt)
|
||||
case ATTACH_TINYTUX:
|
||||
// Nothing to do for tinytux, this is all handled in EmergencyAnimation
|
||||
break;
|
||||
case ATTACH_BUBBLEGUM_SHIELD:
|
||||
if(!m_kart->isShielded())
|
||||
{
|
||||
m_time_left = 0.0f;
|
||||
if (m_kart->m_bubble_drop)
|
||||
{
|
||||
Log::verbose("Attachment", "Drop a small bubble gum. \n");;
|
||||
//TODO: drop a bubble gum item on the track
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
|
||||
// Detach attachment if its time is up.
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
ATTACH_SWATTER,
|
||||
ATTACH_NOLOKS_SWATTER,
|
||||
ATTACH_TINYTUX,
|
||||
ATTACH_BUBBLEGUM_SHIELD,
|
||||
ATTACH_MAX,
|
||||
ATTACH_NOTHING
|
||||
};
|
||||
|
@ -47,13 +47,14 @@ struct initAttachmentType {Attachment::AttachmentType attachment;
|
||||
|
||||
static const initAttachmentType iat[]=
|
||||
{
|
||||
{Attachment::ATTACH_PARACHUTE, "parachute.b3d", "parachute-attach-icon.png"},
|
||||
{Attachment::ATTACH_BOMB, "bomb.b3d", "bomb-attach-icon.png" },
|
||||
{Attachment::ATTACH_ANVIL, "anchor.b3d", "anchor-attach-icon.png" },
|
||||
{Attachment::ATTACH_SWATTER, "swatter.b3d", "swatter-icon.png" },
|
||||
{Attachment::ATTACH_NOLOKS_SWATTER, "swatter_nolok.b3d","swatter-icon.png" },
|
||||
{Attachment::ATTACH_TINYTUX, "reset-button.b3d", "reset-attach-icon.png" },
|
||||
{Attachment::ATTACH_MAX, "", "" },
|
||||
{Attachment::ATTACH_PARACHUTE, "parachute.b3d", "parachute-attach-icon.png" },
|
||||
{Attachment::ATTACH_BOMB, "bomb.b3d", "bomb-attach-icon.png" },
|
||||
{Attachment::ATTACH_ANVIL, "anchor.b3d", "anchor-attach-icon.png" },
|
||||
{Attachment::ATTACH_SWATTER, "swatter.b3d", "swatter-icon.png" },
|
||||
{Attachment::ATTACH_NOLOKS_SWATTER, "swatter_nolok.b3d", "swatter-icon.png" },
|
||||
{Attachment::ATTACH_TINYTUX, "reset-button.b3d", "reset-attach-icon.png" },
|
||||
{Attachment::ATTACH_BUBBLEGUM_SHIELD, "bubblegum_shield.b3d", "shield-icon.png" },
|
||||
{Attachment::ATTACH_MAX, "", "" },
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
float Bowling::m_st_max_distance; // maximum distance for a bowling ball to be attracted
|
||||
float Bowling::m_st_max_distance_squared;
|
||||
float Bowling::m_st_force_to_target;
|
||||
@ -213,11 +215,21 @@ bool Bowling::hit(AbstractKart* kart, PhysicalObject* obj)
|
||||
bool was_real_hit = Flyable::hit(kart, obj);
|
||||
if(was_real_hit)
|
||||
{
|
||||
m_has_hit_kart = kart != NULL;
|
||||
explode(kart, obj, /*hit_secondary*/false);
|
||||
if(kart && kart->isShielded())
|
||||
{
|
||||
kart->decreaseShieldTime(0.0f); //Decreasing the shield time by the default value.
|
||||
Log::verbose("Bowling", "Decreasing shield!");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_has_hit_kart = kart != NULL;
|
||||
explode(kart, obj, /*hit_secondary*/false);
|
||||
}
|
||||
}
|
||||
return was_real_hit;
|
||||
} // hit
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the hit effect object to use when this objects hits something.
|
||||
* \returns The hit effect object, or NULL if no hit effect should be played.
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
float Cake::m_st_max_distance_squared;
|
||||
float Cake::m_gravity;
|
||||
|
||||
@ -168,7 +170,15 @@ bool Cake::hit(AbstractKart* kart, PhysicalObject* obj)
|
||||
{
|
||||
bool was_real_hit = Flyable::hit(kart, obj);
|
||||
if(was_real_hit)
|
||||
{
|
||||
if(kart && kart->isShielded())
|
||||
{
|
||||
kart->decreaseShieldTime(0.0f); //Decreasing the shield time by the default value.
|
||||
Log::verbose("Cake", "Decreasing shield! \n");
|
||||
return false; //Not sure if a shield hit is a real hit.
|
||||
}
|
||||
explode(kart, obj);
|
||||
}
|
||||
|
||||
return was_real_hit;
|
||||
} // hit
|
||||
|
@ -425,7 +425,7 @@ void Flyable::updateFromServer(const FlyableInfo &f, float dt)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns true if the item hit the kart who shot it (to avoid that an item
|
||||
* that's too close to the shoter hits the shoter).
|
||||
* that's too close to the shooter hits the shooter).
|
||||
* \param kart Kart who was hit.
|
||||
*/
|
||||
bool Flyable::isOwnerImmunity(const AbstractKart* kart_hit) const
|
||||
@ -448,7 +448,7 @@ bool Flyable::hit(AbstractKart *kart_hit, PhysicalObject* object)
|
||||
if(isOwnerImmunity(kart_hit)) return false;
|
||||
|
||||
if (kart_hit != NULL)
|
||||
{
|
||||
{ //TODO: reduce shield time; add other string ?
|
||||
RaceGUIBase* gui = World::getWorld()->getRaceGUI();
|
||||
irr::core::stringw hit_message =
|
||||
StringUtils::insertValues(getHitString(kart_hit),
|
||||
|
@ -278,6 +278,10 @@ Item* ItemManager::newItem(const Vec3& xyz, float distance,
|
||||
void ItemManager::collectedItem(Item *item, AbstractKart *kart, int add_info)
|
||||
{
|
||||
assert(item);
|
||||
if((item->getType() == Item::ITEM_BUBBLEGUM || item->getType() == Item::ITEM_BUBBLEGUM_NOLOK) && kart->isShielded())
|
||||
{// shielded karts can simply drive over bubble gums without any effect.
|
||||
return;
|
||||
}
|
||||
item->collected(kart);
|
||||
kart->collectedItem(item, add_info);
|
||||
} // collectedItem
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
Plunger::Plunger(AbstractKart *kart)
|
||||
@ -180,6 +180,13 @@ bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
|
||||
{
|
||||
if(isOwnerImmunity(kart)) return false;
|
||||
|
||||
/*if(kart && kart->isShielded())
|
||||
{
|
||||
//kart->decreaseShieldTime(0.0f); //Decreasing the shield time by the default value.
|
||||
Log::verbose("Plunger", "Almost Decreasing shield! \n");
|
||||
|
||||
return false; //Not sure if a shield hit is a real hit.
|
||||
}*/
|
||||
RaceGUIBase* gui = World::getWorld()->getRaceGUI();
|
||||
irr::core::stringw hit_message;
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
const wchar_t* getAnchorString()
|
||||
{
|
||||
@ -164,7 +164,7 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
|
||||
break;
|
||||
|
||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||
m_sound_use = sfx_manager->createSoundSource("goo");
|
||||
m_sound_use = sfx_manager->createSoundSource("goo");
|
||||
break ;
|
||||
|
||||
case PowerupManager::POWERUP_SWITCH:
|
||||
@ -192,12 +192,38 @@ Material *Powerup::getIcon() const
|
||||
return powerup_manager->getIcon(m_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Does the sound configuration.
|
||||
*/
|
||||
void Powerup::adjustSound()
|
||||
{
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
|
||||
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
{
|
||||
// player karts played at full volume; AI karts much dimmer
|
||||
|
||||
if (m_owner->getController()->isPlayerController())
|
||||
{
|
||||
m_sound_use->volume( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sound_use->volume( std::min(0.5f, 1.0f / race_manager->getNumberOfKarts()) );
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Use (fire) this powerup.
|
||||
*/
|
||||
void Powerup::use()
|
||||
{
|
||||
// Play custom kart sound when collectible is used
|
||||
// Play custom kart sound when collectible is used //TODO: what about the bubble gum?
|
||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||
m_type != PowerupManager::POWERUP_SWATTER &&
|
||||
m_type != PowerupManager::POWERUP_ZIPPER)
|
||||
@ -233,26 +259,11 @@ void Powerup::use()
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
|
||||
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
{
|
||||
// player karts played at full volume; AI karts much dimmer
|
||||
|
||||
if (m_owner->getController()->isPlayerController())
|
||||
{
|
||||
m_sound_use->volume( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sound_use->volume( std::min(0.5f, 1.0f / race_manager->getNumberOfKarts()) );
|
||||
}
|
||||
}
|
||||
|
||||
if(stk_config->m_shield_restrict_weapos)
|
||||
m_owner->setShieldTime(0.0f); // make weapon usage destroy the shield
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
|
||||
projectile_manager->newProjectile(m_owner, world->getTrack(), m_type);
|
||||
break ;
|
||||
|
||||
@ -261,51 +272,55 @@ void Powerup::use()
|
||||
->set(Attachment::ATTACH_SWATTER,
|
||||
m_owner->getKartProperties()->getSwatterDuration());
|
||||
break;
|
||||
|
||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||
// use the bubble gum the traditional way, if the kart is looking back
|
||||
if (m_owner->getControls().m_look_back)
|
||||
{
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
const Material* material_hit;
|
||||
Vec3 pos = m_owner->getXYZ();
|
||||
Vec3 to=pos+Vec3(0, -10000, 0);
|
||||
world->getTrack()->getTriangleMesh().castRay(pos, to, &hit_point,
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
const Material* material_hit;
|
||||
Vec3 pos = m_owner->getXYZ();
|
||||
Vec3 to=pos+Vec3(0, -10000, 0);
|
||||
world->getTrack()->getTriangleMesh().castRay(pos, to, &hit_point,
|
||||
&material_hit, &normal);
|
||||
// This can happen if the kart is 'over nothing' when dropping
|
||||
// the bubble gum
|
||||
if(!material_hit)
|
||||
return;
|
||||
normal.normalize();
|
||||
// This can happen if the kart is 'over nothing' when dropping
|
||||
// the bubble gum
|
||||
if(!material_hit)
|
||||
return;
|
||||
normal.normalize();
|
||||
|
||||
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
|
||||
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
|
||||
if (race_manager->getNumLocalPlayers() > 1)
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
|
||||
pos.setY(hit_point.getY()-0.05f);
|
||||
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_owner);
|
||||
}
|
||||
else // if the kart is looking forward, use the bubblegum as a shield
|
||||
{
|
||||
const int np = race_manager->getNumLocalPlayers();
|
||||
const int nai = race_manager->getNumberOfKarts() - np;
|
||||
|
||||
// player karts played at full volume; AI karts much dimmer
|
||||
|
||||
if (m_owner->getController()->isPlayerController())
|
||||
if(!m_owner->isShielded()) //if the previous shield had been used up.
|
||||
{
|
||||
m_sound_use->volume( 1.0f );
|
||||
m_owner->getAttachment()->set(Attachment::ATTACH_BUBBLEGUM_SHIELD,
|
||||
stk_config->m_bubblegum_shield_time);
|
||||
}
|
||||
else
|
||||
else // using a bubble gum while still having a shield
|
||||
{
|
||||
m_sound_use->volume( 1.0f / nai );
|
||||
m_owner->getAttachment()->set(Attachment::ATTACH_BUBBLEGUM_SHIELD,
|
||||
stk_config->m_bubblegum_shield_time + m_owner->getShieldTime());
|
||||
}
|
||||
}
|
||||
|
||||
m_sound_use->position(m_owner->getXYZ());
|
||||
m_sound_use->play();
|
||||
m_sound_use = sfx_manager->createSoundSource("inflate");//Extraordinary. Usually sounds are set in Powerup::set()
|
||||
//In this case this is a workaround, since the bubblegum item has two different sounds.
|
||||
|
||||
pos.setY(hit_point.getY()-0.05f);
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_owner);
|
||||
}
|
||||
} // end of PowerupManager::POWERUP_BUBBLEGUM
|
||||
break;
|
||||
|
||||
case PowerupManager::POWERUP_ANVIL:
|
||||
|
||||
//Attach an anvil(twice as good as the one given
|
||||
//by the bananas) to the kart in the 1st position.
|
||||
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
|
||||
@ -351,6 +366,12 @@ void Powerup::use()
|
||||
{
|
||||
AbstractKart *kart=world->getKart(i);
|
||||
if(kart->isEliminated() || kart== m_owner) continue;
|
||||
if(kart->isShielded())
|
||||
{
|
||||
kart->decreaseShieldTime(stk_config->m_bubblegum_shield_time);
|
||||
Log::verbose("Powerup", "Decreasing shield \n");
|
||||
continue;
|
||||
}
|
||||
if(m_owner->getPosition() > kart->getPosition())
|
||||
{
|
||||
kart->getAttachment()
|
||||
|
@ -56,8 +56,9 @@ public:
|
||||
void set (PowerupManager::PowerupType _type, int n=1);
|
||||
void reset ();
|
||||
Material* getIcon () const;
|
||||
void adjustSound ();
|
||||
void use ();
|
||||
void hitBonusBox (const Item &item, int newC=-1);
|
||||
void hitBonusBox (const Item &item, int newC=-1);
|
||||
|
||||
/** Returns the number of powerups. */
|
||||
int getNum () const {return m_number;}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "audio/sfx_base.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "config/stk_config.hpp"
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
@ -28,6 +29,8 @@
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
float RubberBall::m_st_interval;
|
||||
float RubberBall::m_st_min_interpolation_distance;
|
||||
float RubberBall::m_st_squash_duration;
|
||||
@ -717,6 +720,21 @@ bool RubberBall::hit(AbstractKart* kart, PhysicalObject* object)
|
||||
}
|
||||
bool was_real_hit = Flyable::hit(kart, object);
|
||||
if(was_real_hit)
|
||||
explode(kart, object);
|
||||
{
|
||||
/*if(kart && kart->isShielded() && kart->getShieldTime() > stk_config->m_bubblegum_shield_time )
|
||||
{ //remove twice the default shield time
|
||||
kart->decreaseShieldTime(stk_config->m_bubblegum_shield_time * 2);
|
||||
Log::verbose("rubber_ball", "Decreasing shield 1! \n");
|
||||
}
|
||||
else */if(kart && kart->isShielded())
|
||||
{
|
||||
kart->decreaseShieldTime(stk_config->m_bubblegum_shield_time);
|
||||
//kart->getAttachment()->update(0.0f);
|
||||
//kart->setSquash(m_st_squash_duration, m_st_squash_slowdown);
|
||||
Log::verbose("rubber_ball", "Decreasing shield 2! \n");
|
||||
}
|
||||
else
|
||||
explode(kart, object);
|
||||
}
|
||||
return was_real_hit;
|
||||
} // hit
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
#include <IMesh.h>
|
||||
|
||||
const wchar_t* getPlungerString()
|
||||
@ -135,7 +137,7 @@ void RubberBand::updatePosition()
|
||||
*/
|
||||
void RubberBand::update(float dt)
|
||||
{
|
||||
if(m_owner->isEliminated())
|
||||
if(m_owner->isEliminated() || m_owner->isShielded())
|
||||
{
|
||||
// Rubber band snaps
|
||||
m_plunger->hit(NULL);
|
||||
@ -238,10 +240,20 @@ void RubberBand::hit(AbstractKart *kart_hit, const Vec3 *track_xyz)
|
||||
// a hit as well as the bullet physics.
|
||||
if(m_attached_state!=RB_TO_PLUNGER) return;
|
||||
|
||||
|
||||
// A kart was hit
|
||||
// ==============
|
||||
if(kart_hit)
|
||||
{
|
||||
if(kart_hit->isShielded())
|
||||
{
|
||||
kart_hit->decreaseShieldTime(0.0f); //Decreasing the shield time by the default value.
|
||||
m_plunger->setKeepAlive(0.0f);
|
||||
Log::verbose("rubber_band", "Decreasing shield! \n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_hit_kart = kart_hit;
|
||||
m_attached_state = RB_TO_KART;
|
||||
|
||||
|
@ -378,6 +378,18 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setInvulnerableTime(float t) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the kart is protected by a shield. */
|
||||
virtual bool isShielded() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setShieldTime(float t) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getShieldTime() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Decreases the kart's shield time. */
|
||||
//Hard coded shield decrease time
|
||||
virtual void decreaseShieldTime(float t) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Shows the star effect for a certain time. */
|
||||
virtual void showStarEffect(float t) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
@ -403,6 +415,9 @@ public:
|
||||
/** Set a text that is displayed on top of a kart.
|
||||
*/
|
||||
virtual void setOnScreenText(const wchar_t *text) = 0;
|
||||
/** Whether an unused bubble gum shield becomes a bubble gum on the ground.
|
||||
* */
|
||||
bool m_bubble_drop;
|
||||
}; // AbstractKart
|
||||
|
||||
|
||||
|
@ -1149,6 +1149,10 @@ void SkiddingAI::evaluateItems(const Item *item, float kart_aim_angle,
|
||||
* better job on higher level AI - e.g. aiming at karts ahead/behind, wait an
|
||||
* appropriate time before using multiple items etc.
|
||||
* \param dt Time step size.
|
||||
* TODO: Implications of Bubble-Shield for AI's powerup-handling
|
||||
|
||||
* STATE: shield on -> avoid usage of offensive items (with certain tolerance)
|
||||
* STATE: swatter on -> avoid usage of shield
|
||||
*/
|
||||
void SkiddingAI::handleItems(const float dt)
|
||||
{
|
||||
@ -1192,11 +1196,13 @@ void SkiddingAI::handleItems(const float dt)
|
||||
|
||||
// Tactic 2: calculate
|
||||
// -------------------
|
||||
float min_bubble_time = 2.0f;
|
||||
|
||||
switch( m_kart->getPowerup()->getType() )
|
||||
{
|
||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||
// Avoid dropping all bubble gums one after another
|
||||
if( m_time_since_last_shot <3.0f) break;
|
||||
if( m_time_since_last_shot < 3.0f) break;
|
||||
|
||||
// Either use the bubble gum after 10 seconds, or if the next kart
|
||||
// behind is 'close' but not too close (too close likely means that the
|
||||
@ -1205,16 +1211,30 @@ void SkiddingAI::handleItems(const float dt)
|
||||
// kart as well? I.e. only drop if the kart behind is faster? Otoh
|
||||
// this approach helps preventing an overtaken kart to overtake us
|
||||
// again.
|
||||
m_controls->m_look_back = true; //handle traditinal usage as bubble gum
|
||||
m_controls->m_fire = (m_distance_behind < 15.0f &&
|
||||
m_distance_behind > 3.0f );
|
||||
m_distance_behind > 3.0f );//TODO: is this criteria sufficient to hit another kart with a high probability
|
||||
|
||||
m_controls->m_look_back = false;
|
||||
//Do not use a shield, when you still have a swatter
|
||||
if (m_kart->getAttachment()->getType() == Attachment::ATTACH_SWATTER || m_kart->getAttachment()->getType() == Attachment::ATTACH_NOLOKS_SWATTER)
|
||||
break;
|
||||
//else there are no objections not to use a shield
|
||||
m_controls->m_fire = true;
|
||||
|
||||
break; // POWERUP_BUBBLEGUM
|
||||
|
||||
// All the thrown/fired items might be improved by considering the angle
|
||||
// towards m_kart_ahead.
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
{
|
||||
// Do not destroy your own shield
|
||||
if(m_kart->getShieldTime() > min_bubble_time) // if the kart has a shield, do not break it by using a swatter.
|
||||
break;
|
||||
// Leave some time between shots
|
||||
if(m_time_since_last_shot<3.0f) break;
|
||||
//TODO: do not fire if the kart is driving too slow
|
||||
|
||||
// Since cakes can be fired all around, just use a sane distance
|
||||
// with a bit of extra for backwards, as enemy will go towards cake
|
||||
bool fire_backwards = (m_kart_behind && m_kart_ahead &&
|
||||
@ -1231,6 +1251,9 @@ void SkiddingAI::handleItems(const float dt)
|
||||
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
{
|
||||
// Do not destroy your own shield
|
||||
if(m_kart->getShieldTime() > min_bubble_time) // if the kart has a shield, do not break it by using a swatter.
|
||||
break;
|
||||
// Leave more time between bowling balls, since they are
|
||||
// slower, so it should take longer to hit something which
|
||||
// can result in changing our target.
|
||||
@ -1258,6 +1281,10 @@ void SkiddingAI::handleItems(const float dt)
|
||||
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
{
|
||||
// Do not destroy your own shield
|
||||
if(m_kart->getShieldTime() > min_bubble_time) // if the kart has a shield, do not break it by using a swatter.
|
||||
break;
|
||||
|
||||
// Leave more time after a plunger, since it will take some
|
||||
// time before a plunger effect becomes obvious.
|
||||
if(m_time_since_last_shot < 5.0f) break;
|
||||
@ -1311,6 +1338,9 @@ void SkiddingAI::handleItems(const float dt)
|
||||
{
|
||||
// Squared distance for which the swatter works
|
||||
float d2 = m_kart->getKartProperties()->getSwatterDistance2();
|
||||
// if the kart has a shield, do not break it by using a swatter.
|
||||
if(m_kart->getShieldTime() > min_bubble_time)
|
||||
break;
|
||||
// Fire if the closest kart ahead or to the back is not already
|
||||
// squashed and close enough.
|
||||
// FIXME: this can be improved on, since more than one kart might
|
||||
@ -1325,6 +1355,9 @@ void SkiddingAI::handleItems(const float dt)
|
||||
break;
|
||||
}
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
// Do not destroy your own shield
|
||||
if(m_kart->getShieldTime() > min_bubble_time) // if the kart has a shield, do not break it by using a swatter.
|
||||
break;
|
||||
// Perhaps some more sophisticated algorithm might be useful.
|
||||
// For now: fire if there is a kart ahead (which means that
|
||||
// this kart is certainly not the first kart)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
/** A static create function that does only create an explosion if
|
||||
* the explosion happens to be close enough to affect the kart.
|
||||
@ -37,7 +38,12 @@ ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart,
|
||||
bool direct_hit)
|
||||
{
|
||||
if(kart->isInvulnerable()) return NULL;
|
||||
|
||||
/*else if(kart->isShielded() && !direct_hit) //How can I test this code ??
|
||||
{
|
||||
kart->decreaseShieldTime(0.0f); //Decreasing the shield time by the default value.
|
||||
Log::verbose("ExlosionAnimation", "Decreasing shield \n");
|
||||
return NULL;
|
||||
}*/
|
||||
float r = kart->getKartProperties()->getExplosionRadius();
|
||||
|
||||
// Ignore explosion that are too far away.
|
||||
@ -53,6 +59,12 @@ ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart,
|
||||
ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart)
|
||||
{
|
||||
if(kart->isInvulnerable()) return NULL;
|
||||
else if(kart->isShielded())
|
||||
{
|
||||
kart->decreaseShieldTime(0.0f) ; //decreasing the shieldtime by the default amount
|
||||
Log::verbose("ExplosionAnimation", "Decreasing shield 2\n");
|
||||
return NULL;
|
||||
}
|
||||
return new ExplosionAnimation(kart, kart->getXYZ(), /*direct hit*/true);
|
||||
} // create
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/explosion.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/particle_emitter.hpp"
|
||||
#include "graphics/particle_kind.hpp"
|
||||
@ -67,8 +68,9 @@
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
|
||||
|
||||
#include "graphics/explosion.hpp"
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
// Disable warning for using 'this' in base member initializer list
|
||||
@ -511,7 +513,23 @@ void Kart::setPosition(int p)
|
||||
} // setPosition
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime.
|
||||
*/
|
||||
void Kart::blockViewWithPlunger()
|
||||
{
|
||||
// Avoid that a plunger extends the plunger time
|
||||
if(m_view_blocked_by_plunger<=0 && !isShielded())
|
||||
m_view_blocked_by_plunger =
|
||||
m_kart_properties->getPlungerInFaceTime();
|
||||
if(isShielded())
|
||||
{
|
||||
decreaseShieldTime(0.0f); //decrease the default amount of time
|
||||
Log::verbose("Kart", "Decreasing shield, because of removing the plunger. \n");
|
||||
}
|
||||
} // blockViewWithPlunger
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns a transform that will align an object with the kart: the heading
|
||||
* and the pitch will be set appropriately. A custom pitch value can be
|
||||
* specified in order to overwrite the terrain pitch (which would be used
|
||||
@ -942,6 +960,67 @@ bool Kart::isNearGround() const
|
||||
< stk_config->m_near_ground);
|
||||
} // isNearGround
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Enables a kart shield protection for a certain amount of time.
|
||||
*/
|
||||
void Kart::setShieldTime(float t)
|
||||
{
|
||||
if(this->isShielded())
|
||||
{
|
||||
this->getAttachment()->setTimeLeft(t);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Returns true if the kart is protected by a shield.
|
||||
*/
|
||||
bool Kart::isShielded() const
|
||||
{
|
||||
if(getAttachment() != NULL)
|
||||
return getAttachment()->getType() == Attachment::ATTACH_BUBBLEGUM_SHIELD;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
*Returns the remaining time the kart is protected by a shield.
|
||||
*/
|
||||
float Kart::getShieldTime() const
|
||||
{
|
||||
if(isShielded())
|
||||
return getAttachment()->getTimeLeft();
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Decreases the kart's shield time.
|
||||
* \param t The time substracted from the shield timer. If t == 0.0f, the default amout of time is substracted.
|
||||
*/
|
||||
void Kart::decreaseShieldTime(float t)
|
||||
{
|
||||
if(this->isShielded())
|
||||
{
|
||||
getAttachment()->setTimeLeft( getAttachment()->getTimeLeft() - t );
|
||||
if(t == 0.0f)
|
||||
{
|
||||
getAttachment()->setTimeLeft( getAttachment()->getTimeLeft()
|
||||
- stk_config->m_bubblegum_shield_time);
|
||||
}
|
||||
|
||||
}
|
||||
//Let the kart drop a bubble gum, if the shield was not damaged.
|
||||
//This is the default, whenever a powerup is used by a kart.
|
||||
//It is turned off, if the shield was reduced below zero by a hit. (Or by intently damaging the shield.)
|
||||
if(!this->isShielded())
|
||||
m_bubble_drop = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Shows the star effect for a certain time.
|
||||
* \param t Time to show the star effect for.
|
||||
@ -1009,7 +1088,9 @@ void Kart::update(float dt)
|
||||
|
||||
// if its view is blocked by plunger, decrease remaining time
|
||||
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt;
|
||||
|
||||
//unblock the view if kart just became shielded
|
||||
if(isShielded())
|
||||
m_view_blocked_by_plunger = 0.0f;
|
||||
// Decrease remaining invulnerability time
|
||||
if(m_invulnerable_time>0)
|
||||
{
|
||||
@ -1085,6 +1166,7 @@ void Kart::update(float dt)
|
||||
// since use() can test if something needs to be switched on/off.
|
||||
m_powerup->use() ;
|
||||
World::getWorld()->onFirePressed(getController());
|
||||
m_bubble_drop = true;
|
||||
}
|
||||
// Reset the fire button
|
||||
m_controls.m_fire = 0;
|
||||
@ -1268,6 +1350,13 @@ void Kart::setSquash(float time, float slowdown)
|
||||
{
|
||||
if (isInvulnerable()) return;
|
||||
|
||||
if (isShielded())
|
||||
{
|
||||
decreaseShieldTime(stk_config->m_bubblegum_shield_time/2.0f);
|
||||
Log::verbose("Kart", "Decreasing shield \n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_attachment->getType()==Attachment::ATTACH_BOMB && time>0)
|
||||
{
|
||||
ExplosionAnimation::create(this);
|
||||
|
@ -136,6 +136,8 @@ private:
|
||||
/** The torque to apply after hitting a bubble gum. */
|
||||
float m_bubblegum_torque;
|
||||
|
||||
|
||||
|
||||
// Bullet physics parameters
|
||||
// -------------------------
|
||||
btCompoundShape m_kart_chassis;
|
||||
@ -310,13 +312,7 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets that the view is blocked by a plunger. The duration depends on
|
||||
* the difficulty, see KartPorperties getPlungerInFaceTime. */
|
||||
virtual void blockViewWithPlunger()
|
||||
{
|
||||
// Avoid that a plunger extends the plunger time
|
||||
if(m_view_blocked_by_plunger<=0)
|
||||
m_view_blocked_by_plunger =
|
||||
m_kart_properties->getPlungerInFaceTime();
|
||||
} // blockViewWithPlunger
|
||||
virtual void blockViewWithPlunger();
|
||||
// -------------------------------------------------------------------------
|
||||
/** Returns a bullet transform object located at the kart's position
|
||||
and oriented in the direction the kart is going. Can be useful
|
||||
@ -395,11 +391,25 @@ public:
|
||||
virtual void eliminate();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Makes a kart invulnerable for a certain amount of time. */
|
||||
virtual void setInvulnerableTime(float t) { m_invulnerable_time = t; };
|
||||
virtual void setInvulnerableTime(float t) { m_invulnerable_time = t; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the kart is invulnerable. */
|
||||
virtual bool isInvulnerable() const { return m_invulnerable_time > 0; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Enables a kart shield protection for a certain amount of time. */
|
||||
virtual void setShieldTime(float t);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if the kart is protected by a shield. */
|
||||
virtual bool isShielded() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the remaining time the kart is protected by a shield. */
|
||||
virtual float getShieldTime() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Decreases the kart's shield time. */
|
||||
//If t = 0.0f: decrease shield time by the default amount.
|
||||
virtual void decreaseShieldTime(float t);
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** Sets the energy the kart has collected. */
|
||||
virtual void setEnergy(float val) { m_collected_energy = val; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -76,7 +76,7 @@ void KartWithStats::update(float dt)
|
||||
*/
|
||||
void KartWithStats::setKartAnimation(AbstractKartAnimation *ka)
|
||||
{
|
||||
bool is_new = !getKartAnimation() && !isInvulnerable();
|
||||
bool is_new = !getKartAnimation() && !isInvulnerable() && !isShielded();
|
||||
Kart::setKartAnimation(ka);
|
||||
// Nothing to count if it's not a new animation
|
||||
if(!is_new) return;
|
||||
|
@ -223,11 +223,15 @@ void Physics::update(float dt)
|
||||
// --------------------
|
||||
// Only explode a bowling ball if the target is
|
||||
// not invulnerable
|
||||
AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
|
||||
if(p->getUserPointer(0)->getPointerFlyable()->getType()
|
||||
!=PowerupManager::POWERUP_BOWLING ||
|
||||
!p->getUserPointer(1)->getPointerKart()->isInvulnerable() )
|
||||
!=PowerupManager::POWERUP_BOWLING ||
|
||||
!target_kart->isInvulnerable() )
|
||||
{
|
||||
p->getUserPointer(0)->getPointerFlyable()
|
||||
->hit(p->getUserPointer(1)->getPointerKart());
|
||||
->hit(target_kart);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user