Fixed #879: avoid too many basket balls at the same time by introducing
a minimum amount of time (atm 15 seconds) before the next basket ball can be found. Thanks to nixt for the patch. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12722 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
81378440ba
commit
7ab65aee16
@ -26,6 +26,8 @@
|
||||
target-max-angle: Once the ball is aiming for its
|
||||
target, it can at most change the angle
|
||||
this much per second(!).
|
||||
time-between-balls: Reduces the frequency with which rubber
|
||||
balls are found to 1 every 'timer' seconds.
|
||||
min-interpolation-distance: how far the control
|
||||
points (which are center of squads)
|
||||
must be from each other. A large value
|
||||
@ -61,6 +63,7 @@
|
||||
early-target-factor="1"
|
||||
target-distance="15" target-max-angle = "90"
|
||||
min-interpolation-distance="5"
|
||||
time-between-balls="15"
|
||||
squash-slowdown="0.5" squash-duration="2"
|
||||
delete-time="5.0" max-height-difference="10" />
|
||||
<item name="parachute" icon="parachute-icon.png"
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "items/rubber_ball.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
@ -408,9 +409,27 @@ void Powerup::hitBonusBox(const Item &item, int add_info)
|
||||
int position = m_owner->getPosition();
|
||||
|
||||
unsigned int n=1;
|
||||
PowerupManager::PowerupType new_powerup =
|
||||
powerup_manager->getRandomPowerup(position, &n);
|
||||
PowerupManager::PowerupType new_powerup;
|
||||
|
||||
// Check if rubber ball is the current power up held by the kart. If so,
|
||||
// reset the bBallCollectTime to 0 before giving new powerup.
|
||||
if(m_type == PowerupManager::POWERUP_RUBBERBALL)
|
||||
powerup_manager->setBallCollectTime(0);
|
||||
|
||||
// Check if two bouncing balls are collected less than getRubberBallTimer()
|
||||
//seconds apart. If yes, then call getRandomPowerup again. If no, then break.
|
||||
for(int i=0; i<20; i++)
|
||||
{
|
||||
new_powerup = powerup_manager->getRandomPowerup(position, &n);
|
||||
if(new_powerup != PowerupManager::POWERUP_RUBBERBALL ||
|
||||
( World::getWorld()->getTime() - powerup_manager->getBallCollectTime()) >
|
||||
RubberBall::getTimeBetweenRubberBalls() )
|
||||
break;
|
||||
}
|
||||
|
||||
if(new_powerup == PowerupManager::POWERUP_RUBBERBALL)
|
||||
powerup_manager->setBallCollectTime(World::getWorld()->getTime());
|
||||
|
||||
// Always add a new powerup in ITEM_MODE_NEW (or if the kart
|
||||
// doesn't have a powerup atm).
|
||||
if(m_type == PowerupManager::POWERUP_NOTHING ||
|
||||
|
@ -112,6 +112,9 @@ private:
|
||||
/** Maximum turn angle for steering of homing powerups. */
|
||||
float m_all_max_turn_angle[POWERUP_MAX];
|
||||
|
||||
/** Last time the bouncing ball was collected */
|
||||
float m_rubber_ball_collect_time;
|
||||
|
||||
/** The mesh for each model (if the powerup has a model), e.g. a switch
|
||||
has none. */
|
||||
irr::scene::IMesh *m_all_meshes[POWERUP_MAX];
|
||||
@ -160,6 +163,8 @@ public:
|
||||
float getMaxTurnAngle (int type) const {return m_all_max_turn_angle[type];}
|
||||
const btVector3&
|
||||
getExtend (int type) const {return m_all_extends[type];}
|
||||
float getBallCollectTime() const {return m_rubber_ball_collect_time;}
|
||||
void setBallCollectTime(float time) {m_rubber_ball_collect_time=time;}
|
||||
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,8 @@ float RubberBall::m_st_max_height_difference;
|
||||
float RubberBall::m_st_fast_ping_distance;
|
||||
float RubberBall::m_st_early_target_factor;
|
||||
int RubberBall::m_next_id = 0;
|
||||
float RubberBall::m_time_between_balls;
|
||||
|
||||
|
||||
// Debug only, so that we can get a feel on how well balls are aiming etc.
|
||||
#undef PRINT_BALL_REMOVE_INFO
|
||||
@ -150,7 +152,8 @@ void RubberBall::computeTarget()
|
||||
if(m_target==m_owner && m_delete_timer < 0)
|
||||
{
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
printf("ball %d removed because owner is target.\n", m_id);
|
||||
Log::debug("RubberBall",
|
||||
"ball %d removed because owner is target.", m_id);
|
||||
#endif
|
||||
m_delete_timer = m_st_delete_time;
|
||||
}
|
||||
@ -162,7 +165,8 @@ void RubberBall::computeTarget()
|
||||
// aim at the owner (the ball is unlikely to hit it), and
|
||||
// this will trigger the usage of the delete time in updateAndDelete
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
printf("ball %d removed because no more active target.\n", m_id);
|
||||
Log::debug("RubberBall" "ball %d removed because no more active target.",
|
||||
m_id);
|
||||
#endif
|
||||
m_delete_timer = m_st_delete_time;
|
||||
m_target = m_owner;
|
||||
@ -232,9 +236,9 @@ void RubberBall::getNextControlPoint()
|
||||
/** Initialises this object with data from the power.xml file (this is a static
|
||||
* function).
|
||||
* \param node XML Node
|
||||
* \param bowling The bowling ball mesh
|
||||
* \param rubberball The rubber ball mesh
|
||||
*/
|
||||
void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
|
||||
void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
{
|
||||
m_st_interval = 1.0f;
|
||||
m_st_squash_duration = 3.0f;
|
||||
@ -246,46 +250,44 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
|
||||
m_st_max_height_difference = 10.0f;
|
||||
m_st_fast_ping_distance = 50.0f;
|
||||
m_st_early_target_factor = 1.0f;
|
||||
m_time_between_balls = 15;
|
||||
|
||||
if(!node.get("interval", &m_st_interval))
|
||||
printf("[powerup] Warning: no interval specified for rubber ball.\n");
|
||||
Log::warn("powerup", "No interval specified for rubber ball.");
|
||||
if(!node.get("squash-duration", &m_st_squash_duration))
|
||||
printf(
|
||||
"[powerup] Warning: no squash-duration specified for rubber ball.\n");
|
||||
Log::warn("powerup",
|
||||
"No squash-duration specified for rubber ball.");
|
||||
if(!node.get("squash-slowdown", &m_st_squash_slowdown))
|
||||
printf(
|
||||
"[powerup] Warning: no squash-slowdown specified for rubber ball.\n");
|
||||
Log::warn("powerup", "No squash-slowdown specified for rubber ball.");
|
||||
if(!node.get("min-interpolation-distance",
|
||||
&m_st_min_interpolation_distance))
|
||||
printf(
|
||||
"[powerup] Warning: no min-interpolation-distance specified "
|
||||
"for rubber ball.\n");
|
||||
Log::warn("powerup", "No min-interpolation-distance specified "
|
||||
"for rubber ball.");
|
||||
if(!node.get("target-distance", &m_st_target_distance))
|
||||
printf(
|
||||
"[powerup] Warning: no target-distance specified for rubber ball.\n");
|
||||
Log::warn("powerup",
|
||||
"No target-distance specified for rubber ball.");
|
||||
if(!node.get("delete-time", &m_st_delete_time))
|
||||
printf(
|
||||
"[powerup] Warning: no delete-time specified for rubber ball.\n");
|
||||
Log::warn("powerup", "No delete-time specified for rubber ball.");
|
||||
if(!node.get("target-max-angle", &m_st_target_max_angle))
|
||||
printf(
|
||||
"[powerup] Warning: no target-max-angle specified for rubber ball.\n");
|
||||
Log::warn("powerup", "No target-max-angle specified for rubber ball.");
|
||||
m_st_target_max_angle *= DEGREE_TO_RAD;
|
||||
if(!node.get("max-height-difference", &m_st_max_height_difference))
|
||||
printf(
|
||||
"[powerup] Warning: no max-height-difference specified for "
|
||||
"rubber ball.\n");
|
||||
Log::warn("powerup",
|
||||
"No max-height-difference specified for rubber ball.");
|
||||
if(!node.get("fast-ping-distance", &m_st_fast_ping_distance))
|
||||
printf(
|
||||
"[powerup] Warning: no fast-ping-distance specified for "
|
||||
"rubber ball.\n");
|
||||
Log::warn("powerup",
|
||||
"No fast-ping-distance specified for rubber ball.");
|
||||
if(m_st_fast_ping_distance < m_st_target_distance)
|
||||
printf("Warning: ping-distance is smaller than target distance.\n"
|
||||
"hat should not happen, but is ignored for now.\n");
|
||||
Log::warn("powerup",
|
||||
"Ping-distance is smaller than target distance.\n"
|
||||
"That should not happen, but is ignored for now.");
|
||||
if(!node.get("early-target-factor", &m_st_early_target_factor))
|
||||
printf(
|
||||
"[powerup] Warning: no early-target-factor specified for "
|
||||
"rubber ball.\n");
|
||||
Flyable::init(node, bowling, PowerupManager::POWERUP_RUBBERBALL);
|
||||
Log::warn("powerup",
|
||||
"No early-target-factor specified for rubber ball.");
|
||||
if(!node.get("time-between-balls", &m_time_between_balls))
|
||||
Log::warn("powerup",
|
||||
"No time-between-balls specified for rubber ball.");
|
||||
Flyable::init(node, rubberball, PowerupManager::POWERUP_RUBBERBALL);
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -324,7 +326,7 @@ bool RubberBall::updateAndDelete(float dt)
|
||||
{
|
||||
hit(NULL);
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
printf("ball %d deleted.\n", m_id);
|
||||
Log::debug("RubberBall", "ball %d deleted.", m_id);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -380,8 +382,8 @@ bool RubberBall::updateAndDelete(float dt)
|
||||
}
|
||||
|
||||
if(UserConfigParams::logFlyable())
|
||||
printf("newy2 %f gmth %f\n", new_y,
|
||||
getMaxTerrainHeight(vertical_offset));
|
||||
Log::verbose("RubberBall", "newy2 %f gmth %f", new_y,
|
||||
getMaxTerrainHeight(vertical_offset));
|
||||
|
||||
next_xyz.setY(new_y);
|
||||
m_previous_xyz = getXYZ();
|
||||
@ -504,10 +506,11 @@ bool RubberBall::checkTunneling()
|
||||
if(m_tunnel_count > 3)
|
||||
{
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
printf("Ball %d nearly tunneled at %f %f %f -> %f %f %f\n",
|
||||
m_id, m_previous_xyz.getX(),m_previous_xyz.getY(),
|
||||
m_previous_xyz.getZ(),
|
||||
getXYZ().getX(),getXYZ().getY(),getXYZ().getZ());
|
||||
Log::debug("RubberBall",
|
||||
"Ball %d nearly tunneled at %f %f %f -> %f %f %f",
|
||||
m_id, m_previous_xyz.getX(),m_previous_xyz.getY(),
|
||||
m_previous_xyz.getZ(),
|
||||
getXYZ().getX(),getXYZ().getY(),getXYZ().getZ());
|
||||
#endif
|
||||
hit(NULL);
|
||||
return true;
|
||||
@ -628,7 +631,7 @@ void RubberBall::updateDistanceToTarget()
|
||||
m_distance_to_target += world->getTrack()->getTrackLength();
|
||||
}
|
||||
if(UserConfigParams::logFlyable())
|
||||
printf("ball %d: target %f %f %f distance_2_target %f \n",
|
||||
printf("ball %d: target %f %f %f distance_2_target %f",
|
||||
m_id, m_target->getXYZ().getX(),m_target->getXYZ().getY(),
|
||||
m_target->getXYZ().getZ(),m_distance_to_target
|
||||
);
|
||||
@ -658,7 +661,8 @@ void RubberBall::updateDistanceToTarget()
|
||||
{
|
||||
m_delete_timer = m_st_delete_time;
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
printf("ball %d lost target (overtook?).\n", m_id);
|
||||
Log::debug("RubberBall", "ball %d lost target (overtook?).",
|
||||
m_id);
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -690,7 +694,7 @@ bool RubberBall::hit(AbstractKart* kart, PhysicalObject* object)
|
||||
{
|
||||
#ifdef PRINT_BALL_REMOVE_INFO
|
||||
if(kart)
|
||||
printf("ball %d hit kart.\n", m_id);
|
||||
Log::debug("RuberBall", "ball %d hit kart.", m_id);
|
||||
#endif
|
||||
if(kart && kart!=m_target)
|
||||
{
|
||||
|
@ -82,6 +82,11 @@ private:
|
||||
* ball will be deleted. */
|
||||
static float m_st_delete_time;
|
||||
|
||||
/** Timer before another rubber ball can be picked up. This is to ensure
|
||||
* that there are not too many rubber balls on the track in races with many
|
||||
* karts. */
|
||||
static float m_time_between_balls;
|
||||
|
||||
/** This factor is used to influence how much the rubber ball should aim
|
||||
* at its target early. It used the 'distance to center of track' of its
|
||||
* target, and adjusts the interpolation control points to be more or
|
||||
@ -199,10 +204,12 @@ private:
|
||||
public:
|
||||
RubberBall (AbstractKart* kart);
|
||||
virtual ~RubberBall();
|
||||
static void init(const XMLNode &node, scene::IMesh *bowling);
|
||||
static void init(const XMLNode &node, scene::IMesh *rubberball);
|
||||
virtual bool updateAndDelete(float dt);
|
||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
||||
virtual const core::stringw getHitString(const AbstractKart *kart) const;
|
||||
|
||||
static float getTimeBetweenRubberBalls() {return m_time_between_balls;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** This object does not create an explosion, all affects on
|
||||
* karts are handled by this hit() function. */
|
||||
|
@ -243,6 +243,9 @@ void World::reset()
|
||||
// Reset all data structures that depend on number of karts.
|
||||
irr_driver->reset();
|
||||
|
||||
//Reset the Rubber Ball Collect Time to some negative value.
|
||||
powerup_manager->setBallCollectTime(-100);
|
||||
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user