Make the AI handle bubblegum better (esp. using shield).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14274 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
c6fa95d262
commit
2da9ab0845
@ -253,6 +253,8 @@
|
||||
disable-slipstream-usage: even if the AI is not trying to use slipstream,
|
||||
it can get a lot of bonus, esp. on easy since the AI creates trains.
|
||||
Set this to true to make sure AI does not get any slipstream bonus.
|
||||
shield-incoming-radius: Radius at which projectiles will be detected and
|
||||
trigger a shield usage.
|
||||
false-start-probability: Probability of a false start.
|
||||
min/max-start-delay: Minimum and maximum start delay.
|
||||
See http://www.humanbenchmark.com/tests/reactiontime/stats.php
|
||||
@ -316,6 +318,7 @@
|
||||
straight-length-for-zipper="35"
|
||||
use-slipstream="false"
|
||||
disable-slipstream-usage="true"
|
||||
shield-incoming-radius="0"
|
||||
false-start-probability="0.08"
|
||||
min-start-delay="0.3" max-start-delay="0.5"
|
||||
nitro-usage="none"
|
||||
@ -333,6 +336,7 @@
|
||||
straight-length-for-zipper="35"
|
||||
use-slipstream="false"
|
||||
disable-slipstream-usage="false"
|
||||
shield-incoming-radius="10"
|
||||
false-start-probability="0.04"
|
||||
min-start-delay="0.25" max-start-delay="0.4"
|
||||
nitro-usage="some"
|
||||
@ -350,6 +354,7 @@
|
||||
straight-length-for-zipper="35"
|
||||
use-slipstream="true"
|
||||
disable-slipstream-usage="false"
|
||||
shield-incoming-radius="10"
|
||||
false-start-probability="0.01"
|
||||
min-start-delay="0.15" max-start-delay="0.28"
|
||||
nitro-usage="all"
|
||||
@ -367,6 +372,7 @@
|
||||
straight-length-for-zipper="35"
|
||||
use-slipstream="true"
|
||||
disable-slipstream-usage="false"
|
||||
shield-incoming-radius="10"
|
||||
false-start-probability="0.0"
|
||||
min-start-delay="0.15" max-start-delay="0.2"
|
||||
nitro-usage="all"
|
||||
|
@ -264,7 +264,7 @@ void Powerup::use()
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
|
||||
projectile_manager->newProjectile(m_owner, world->getTrack(), m_type);
|
||||
projectile_manager->newProjectile(m_owner, m_type);
|
||||
break ;
|
||||
|
||||
case PowerupManager::POWERUP_SWATTER:
|
||||
|
@ -156,8 +156,13 @@ void ProjectileManager::updateClient(float dt)
|
||||
} // for i in m_active_projectiles
|
||||
|
||||
} // updateClient
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
|
||||
/** Creates a new projectile of the given type.
|
||||
* \param kart The kart which shoots the projectile.
|
||||
* \param type Type of projectile.
|
||||
*/
|
||||
Flyable *ProjectileManager::newProjectile(AbstractKart *kart,
|
||||
PowerupManager::PowerupType type)
|
||||
{
|
||||
Flyable *f;
|
||||
@ -173,3 +178,22 @@ Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
|
||||
m_active_projectiles.push_back(f);
|
||||
return f;
|
||||
} // newProjectile
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Returns true if a projectile is within the given distance of the specified
|
||||
* kart.
|
||||
* \param kart The kart for which the test is done.
|
||||
* \param radius Distance within which the projectile must be.
|
||||
*/
|
||||
bool ProjectileManager::projectileIsClose(const AbstractKart * const kart,
|
||||
float radius)
|
||||
{
|
||||
float r2 = radius*radius;
|
||||
|
||||
for(Projectiles::iterator i = m_active_projectiles.begin();
|
||||
i != m_active_projectiles.end(); i++)
|
||||
{
|
||||
float dist2 = (*i)->getXYZ().distance2(kart->getXYZ());
|
||||
if(dist2<r2) return true;
|
||||
}
|
||||
return false;
|
||||
} // projectileIsClose
|
@ -61,10 +61,12 @@ public:
|
||||
void loadData ();
|
||||
void cleanup ();
|
||||
void update (float dt);
|
||||
Flyable* newProjectile (AbstractKart *kart, Track* track,
|
||||
Flyable* newProjectile (AbstractKart *kart,
|
||||
PowerupManager::PowerupType type);
|
||||
void Deactivate (Flyable *p) {}
|
||||
void removeTextures ();
|
||||
bool projectileIsClose(const AbstractKart * const kart,
|
||||
float radius);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a special hit effect to be shown.
|
||||
* \param hit_effect The hit effect to be added. */
|
||||
|
@ -38,6 +38,7 @@ AIProperties::AIProperties(RaceManager::Difficulty difficulty)
|
||||
m_skidding_threshold = UNDEFINED;
|
||||
m_min_start_delay = UNDEFINED;
|
||||
m_max_start_delay = UNDEFINED;
|
||||
m_shield_incoming_radius = UNDEFINED;
|
||||
m_false_start_probability = UNDEFINED;
|
||||
m_make_use_of_slipstream = false;
|
||||
m_collect_avoid_items = false;
|
||||
@ -68,6 +69,7 @@ void AIProperties::load(const XMLNode *ai_node)
|
||||
ai_node->get("collect-avoid-items", &m_collect_avoid_items );
|
||||
ai_node->get("handle-bomb", &m_handle_bomb );
|
||||
ai_node->get("skidding-threshold", &m_skidding_threshold );
|
||||
ai_node->get("shield-incoming-radius", &m_shield_incoming_radius );
|
||||
ai_node->get("false-start-probability", &m_false_start_probability );
|
||||
ai_node->get("min-start-delay", &m_min_start_delay );
|
||||
ai_node->get("max-start-delay", &m_max_start_delay );
|
||||
@ -109,6 +111,7 @@ void AIProperties::checkAllSet(const std::string &filename) const
|
||||
CHECK_NEG(m_bad_item_closeness_2, "bad-item-closeness" );
|
||||
CHECK_NEG(m_straight_length_for_zipper,"straight-length-for-zipper");
|
||||
CHECK_NEG(m_skidding_threshold, "skidding-threshold" );
|
||||
CHECK_NEG(m_shield_incoming_radius, "shield-incoming-radius" );
|
||||
CHECK_NEG(m_false_start_probability, "false-start-probability" );
|
||||
CHECK_NEG(m_min_start_delay, "min-start-delay" );
|
||||
CHECK_NEG(m_max_start_delay, "max-start-delay" );
|
||||
|
@ -79,7 +79,10 @@ protected:
|
||||
|
||||
/** To determine the probability of selecting an item. */
|
||||
InterpolationArray m_collect_item_probability;
|
||||
|
||||
|
||||
/** Distance at which a detected projectile triggers a shield. */
|
||||
float m_shield_incoming_radius;
|
||||
|
||||
/** Probability of a false start. Note that Nolok in boss battle will never
|
||||
* have a false start. */
|
||||
float m_false_start_probability;
|
||||
|
@ -41,6 +41,10 @@
|
||||
#endif
|
||||
#include "graphics/show_curve.hpp"
|
||||
#include "graphics/slip_stream.hpp"
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/kart_control.hpp"
|
||||
#include "karts/controller/ai_properties.hpp"
|
||||
@ -49,9 +53,6 @@
|
||||
#include "karts/rescue_animation.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
#include "karts/skidding_properties.hpp"
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
@ -1169,7 +1170,7 @@ void SkiddingAI::handleItems(const float dt)
|
||||
|
||||
if( m_time_since_last_shot > 3.0f )
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_fire = true;
|
||||
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_SWATTER)
|
||||
m_time_since_last_shot = 3.0f;
|
||||
else
|
||||
@ -1201,29 +1202,54 @@ void SkiddingAI::handleItems(const float dt)
|
||||
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;
|
||||
{
|
||||
Attachment::AttachmentType type = m_kart->getAttachment()->getType();
|
||||
// Don't use shield when we have a swatter.
|
||||
if( type == Attachment::ATTACH_SWATTER ||
|
||||
type == Attachment::ATTACH_NOLOKS_SWATTER )
|
||||
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
|
||||
// kart is not behind but more to the side of this kart and so won't
|
||||
// be hit by the bubble gum anyway). Should we check the speed of the
|
||||
// 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 );//TODO: is this criteria sufficient to hit another kart with a high probability
|
||||
// Check if a flyable (cake, ...) is close. If so, use bubblegum
|
||||
// as shield
|
||||
if( !m_kart->isShielded() &&
|
||||
projectile_manager->projectileIsClose(m_kart,
|
||||
m_ai_properties->m_shield_incoming_radius) )
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
// Avoid dropping all bubble gums one after another
|
||||
if( m_time_since_last_shot < 3.0f) break;
|
||||
|
||||
break; // POWERUP_BUBBLEGUM
|
||||
// Use bubblegum if the next kart behind is 'close' but not too close
|
||||
// (too close likely means that the kart is not behind but more to the
|
||||
// side of this kart and so won't be hit by the bubble gum anyway).
|
||||
// Should we check the speed of the 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.
|
||||
if(m_distance_behind < 15.0f && m_distance_behind > 3.0f )
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// If this kart is in its last lap, drop bubble gums at every
|
||||
// opportunity, since this kart won't envounter them anymore.
|
||||
LinearWorld *lin_world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
if(m_time_since_last_shot > 3.0f &&
|
||||
lin_world &&
|
||||
lin_world->getKartLaps(m_kart->getWorldKartId())
|
||||
== race_manager->getNumLaps()-1)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = true;
|
||||
break;
|
||||
}
|
||||
break; // POWERUP_BUBBLEGUM
|
||||
}
|
||||
// All the thrown/fired items might be improved by considering the angle
|
||||
// towards m_kart_ahead.
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
|
Loading…
x
Reference in New Issue
Block a user