Move check manager to track to allow copying easier later
This commit is contained in:
@@ -78,7 +78,7 @@ RubberBall::RubberBall(AbstractKart *kart)
|
||||
void RubberBall::onFireFlyable()
|
||||
{
|
||||
Flyable::onFireFlyable();
|
||||
CheckManager::get()->addFlyableToCannons(this);
|
||||
Track::getCurrentTrack()->getCheckManager()->addFlyableToCannons(this);
|
||||
// Don't let Flyable update the terrain information, since this object
|
||||
// has to do it earlier than that.
|
||||
setDoTerrainInfo(false);
|
||||
@@ -129,7 +129,7 @@ void RubberBall::onFireFlyable()
|
||||
RubberBall::~RubberBall()
|
||||
{
|
||||
removePingSFX();
|
||||
CheckManager::get()->removeFlyableFromCannons(this);
|
||||
Track::getCurrentTrack()->getCheckManager()->removeFlyableFromCannons(this);
|
||||
} // ~RubberBall
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "network/network_string.hpp"
|
||||
#include "tracks/check_cannon.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/mini_glm.hpp"
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
@@ -399,13 +400,14 @@ void CannonAnimation::restoreData(BareNetworkString* buffer)
|
||||
};
|
||||
|
||||
int cc_idx = buffer->getInt8();
|
||||
if ((unsigned)cc_idx > CheckManager::get()->getCheckStructureCount())
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
if ((unsigned)cc_idx > cm->getCheckStructureCount())
|
||||
{
|
||||
throw CannonCreationException(
|
||||
"Server has different check structure size.", skipping_offset);
|
||||
}
|
||||
CheckCannon* cc = dynamic_cast<CheckCannon*>
|
||||
(CheckManager::get()->getCheckStructure(cc_idx));
|
||||
(cm->getCheckStructure(cc_idx));
|
||||
if (!cc)
|
||||
{
|
||||
throw CannonCreationException(
|
||||
|
||||
@@ -1163,10 +1163,11 @@ void LinearWorld::saveCompleteState(BareNetworkString* bns, STKPeer* peer)
|
||||
for (TrackSector* ts : m_kart_track_sector)
|
||||
ts->saveCompleteState(bns);
|
||||
|
||||
const uint8_t cc = (uint8_t)CheckManager::get()->getCheckStructureCount();
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
const uint8_t cc = (uint8_t)cm->getCheckStructureCount();
|
||||
bns->addUInt8(cc);
|
||||
for (unsigned i = 0; i < cc; i++)
|
||||
CheckManager::get()->getCheckStructure(i)->saveCompleteState(bns);
|
||||
cm->getCheckStructure(i)->saveCompleteState(bns);
|
||||
} // saveCompleteState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -1190,14 +1191,15 @@ void LinearWorld::restoreCompleteState(const BareNetworkString& b)
|
||||
|
||||
updateRacePosition();
|
||||
const unsigned cc = b.getUInt8();
|
||||
if (cc != CheckManager::get()->getCheckStructureCount())
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
if (cc != cm->getCheckStructureCount())
|
||||
{
|
||||
Log::warn("LinearWorld",
|
||||
"Server has different check structures size.");
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < cc; i++)
|
||||
CheckManager::get()->getCheckStructure(i)->restoreCompleteState(b);
|
||||
cm->getCheckStructure(i)->restoreCompleteState(b);
|
||||
} // restoreCompleteState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -1229,10 +1231,11 @@ void LinearWorld::updateCheckLinesServer(int check_id, int kart_id)
|
||||
cl.addUInt32(m_fastest_lap_ticks);
|
||||
cl.encodeString(m_fastest_lap_kart_name);
|
||||
|
||||
const uint8_t cc = (uint8_t)CheckManager::get()->getCheckStructureCount();
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
const uint8_t cc = (uint8_t)cm->getCheckStructureCount();
|
||||
cl.addUInt8(cc);
|
||||
for (unsigned i = 0; i < cc; i++)
|
||||
CheckManager::get()->getCheckStructure(i)->saveIsActive(kart_id, &cl);
|
||||
cm->getCheckStructure(i)->saveIsActive(kart_id, &cl);
|
||||
|
||||
STKHost::get()->sendPacketToAllPeers(&cl, true);
|
||||
} // updateCheckLinesServer
|
||||
@@ -1256,17 +1259,17 @@ void LinearWorld::updateCheckLinesClient(const BareNetworkString& b)
|
||||
b.decodeStringW(&m_fastest_lap_kart_name);
|
||||
|
||||
const unsigned cc = b.getUInt8();
|
||||
if (cc != CheckManager::get()->getCheckStructureCount())
|
||||
if (cc != Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount())
|
||||
return;
|
||||
for (unsigned i = 0; i < cc; i++)
|
||||
CheckManager::get()->getCheckStructure(i)->restoreIsActive(kart_id, b);
|
||||
Track::getCurrentTrack()->getCheckManager()->getCheckStructure(i)->restoreIsActive(kart_id, b);
|
||||
|
||||
} // updateCheckLinesClient
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void LinearWorld::handleServerCheckStructureCount(unsigned count)
|
||||
{
|
||||
if (count != CheckManager::get()->getCheckStructureCount())
|
||||
if (count != Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount())
|
||||
{
|
||||
Log::warn("LinearWorld",
|
||||
"Server has different check structures size.");
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/check_goal.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/graph.hpp"
|
||||
#include "tracks/quad.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
@@ -46,6 +48,189 @@
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
//=============================================================================
|
||||
class BallGoalData
|
||||
{
|
||||
// These data are used by AI to determine ball aiming angle
|
||||
private:
|
||||
// Radius of the ball
|
||||
float m_radius;
|
||||
|
||||
// Slope of the line from ball to the center point of goals
|
||||
float m_red_goal_slope;
|
||||
float m_blue_goal_slope;
|
||||
|
||||
// The transform only takes the ball heading into account,
|
||||
// ie no hpr of ball which allowing setting aim point easier
|
||||
btTransform m_trans;
|
||||
|
||||
// Two goals
|
||||
CheckGoal* m_blue_check_goal;
|
||||
CheckGoal* m_red_check_goal;
|
||||
|
||||
// Location to red/blue goal points from the ball heading point of view
|
||||
Vec3 m_red_goal_1;
|
||||
Vec3 m_red_goal_2;
|
||||
Vec3 m_red_goal_3;
|
||||
Vec3 m_blue_goal_1;
|
||||
Vec3 m_blue_goal_2;
|
||||
Vec3 m_blue_goal_3;
|
||||
public:
|
||||
void reset()
|
||||
{
|
||||
m_red_goal_1 = Vec3(0, 0, 0);
|
||||
m_red_goal_2 = Vec3(0, 0, 0);
|
||||
m_red_goal_3 = Vec3(0, 0, 0);
|
||||
m_blue_goal_1 = Vec3(0, 0, 0);
|
||||
m_blue_goal_2 = Vec3(0, 0, 0);
|
||||
m_blue_goal_3 = Vec3(0, 0, 0);
|
||||
m_red_goal_slope = 1.0f;
|
||||
m_blue_goal_slope = 1.0f;
|
||||
m_trans = btTransform(btQuaternion(0, 0, 0, 1), Vec3(0, 0, 0));
|
||||
} // reset
|
||||
|
||||
float getDiameter() const
|
||||
{
|
||||
return m_radius * 2;
|
||||
} // getDiameter
|
||||
|
||||
void init(float ball_radius)
|
||||
{
|
||||
m_radius = ball_radius;
|
||||
assert(m_radius > 0.0f);
|
||||
|
||||
// Save two goals
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
unsigned int n = cm->getCheckStructureCount();
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
CheckGoal* goal = dynamic_cast<CheckGoal*>
|
||||
(cm->getCheckStructure(i));
|
||||
if (goal)
|
||||
{
|
||||
if (goal->getTeam())
|
||||
m_blue_check_goal = goal;
|
||||
else
|
||||
m_red_check_goal = goal;
|
||||
}
|
||||
}
|
||||
if (m_blue_check_goal == NULL || m_red_check_goal == NULL)
|
||||
{
|
||||
Log::error("SoccerWorld", "Goal(s) is missing!");
|
||||
}
|
||||
} // init
|
||||
|
||||
void updateBallAndGoal(const Vec3& ball_pos, float heading)
|
||||
{
|
||||
btQuaternion quat(Vec3(0, 1, 0), -heading);
|
||||
m_trans = btTransform(btQuaternion(Vec3(0, 1, 0), heading),
|
||||
ball_pos);
|
||||
|
||||
// Red goal
|
||||
m_red_goal_1 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_FIRST) - ball_pos);
|
||||
m_red_goal_2 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_CENTER) - ball_pos);
|
||||
m_red_goal_3 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_LAST) - ball_pos);
|
||||
|
||||
// Blue goal
|
||||
m_blue_goal_1 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_FIRST) - ball_pos);
|
||||
m_blue_goal_2 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_CENTER) - ball_pos);
|
||||
m_blue_goal_3 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_LAST) - ball_pos);
|
||||
|
||||
// Update the slope:
|
||||
// Use y = mx + c as an equation from goal center to ball
|
||||
// As the line always intercept in (0,0) which is the ball location,
|
||||
// so y(z)/x is the slope , it is used for determine aiming position
|
||||
// of ball later
|
||||
m_red_goal_slope = m_red_goal_2.z() / m_red_goal_2.x();
|
||||
m_blue_goal_slope = m_blue_goal_2.z() / m_blue_goal_2.x();
|
||||
} // updateBallAndGoal
|
||||
|
||||
bool isApproachingGoal(KartTeam team) const
|
||||
{
|
||||
// If the ball lies between the first and last pos, and faces
|
||||
// in front of either of them, (inside angular size of goal)
|
||||
// than it's likely to goal
|
||||
if (team == KART_TEAM_BLUE)
|
||||
{
|
||||
if ((m_blue_goal_1.z() > 0.0f || m_blue_goal_3.z() > 0.0f) &&
|
||||
((m_blue_goal_1.x() < 0.0f && m_blue_goal_3.x() > 0.0f) ||
|
||||
(m_blue_goal_3.x() < 0.0f && m_blue_goal_1.x() > 0.0f)))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((m_red_goal_1.z() > 0.0f || m_red_goal_3.z() > 0.0f) &&
|
||||
((m_red_goal_1.x() < 0.0f && m_red_goal_3.x() > 0.0f) ||
|
||||
(m_red_goal_3.x() < 0.0f && m_red_goal_1.x() > 0.0f)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // isApproachingGoal
|
||||
|
||||
Vec3 getAimPosition(KartTeam team, bool reverse) const
|
||||
{
|
||||
// If it's likely to goal already, aim the ball straight behind
|
||||
// should do the job
|
||||
if (isApproachingGoal(team))
|
||||
return m_trans(Vec3(0, 0, reverse ? m_radius*2 : -m_radius*2));
|
||||
|
||||
// Otherwise do the below:
|
||||
// This is done by using Pythagorean Theorem and solving the
|
||||
// equation from ball to goal center (y = (m_***_goal_slope) x)
|
||||
|
||||
// We aim behind the ball from the center of the ball to its
|
||||
// diameter, so 2*m_radius = sqrt (x2 + y2),
|
||||
// which is next x = sqrt (2*m_radius - y2)
|
||||
// And than we have x = y / m(m_***_goal_slope)
|
||||
// After put that in the slope equation, we have
|
||||
// y = sqrt(2*m_radius*m2 / (1+m2))
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
if (team == KART_TEAM_BLUE)
|
||||
{
|
||||
y = sqrt((m_blue_goal_slope * m_blue_goal_slope * m_radius*2) /
|
||||
(1 + (m_blue_goal_slope * m_blue_goal_slope)));
|
||||
if (m_blue_goal_2.x() == 0.0f ||
|
||||
(m_blue_goal_2.x() > 0.0f && m_blue_goal_2.z() > 0.0f) ||
|
||||
(m_blue_goal_2.x() < 0.0f && m_blue_goal_2.z() > 0.0f))
|
||||
{
|
||||
// Determine when y should be negative
|
||||
y = -y;
|
||||
}
|
||||
x = y / m_blue_goal_slope;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = sqrt((m_red_goal_slope * m_red_goal_slope * m_radius*2) /
|
||||
(1 + (m_red_goal_slope * m_red_goal_slope)));
|
||||
if (m_red_goal_2.x() == 0.0f ||
|
||||
(m_red_goal_2.x() > 0.0f && m_red_goal_2.z() > 0.0f) ||
|
||||
(m_red_goal_2.x() < 0.0f && m_red_goal_2.z() > 0.0f))
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
x = y / m_red_goal_slope;
|
||||
}
|
||||
assert (!std::isnan(x));
|
||||
assert (!std::isnan(y));
|
||||
// Return the world coordinates
|
||||
return (reverse ? m_trans(Vec3(-x, 0, -y)) :
|
||||
m_trans(Vec3(x, 0, y)));
|
||||
} // getAimPosition
|
||||
void resetCheckGoal(const Track* t)
|
||||
{
|
||||
m_red_check_goal->reset(*t);
|
||||
m_blue_check_goal->reset(*t);
|
||||
}
|
||||
}; // BallGoalData
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Constructor. Sets up the clock mode etc.
|
||||
*/
|
||||
@@ -66,6 +251,7 @@ SoccerWorld::SoccerWorld() : WorldWithRank()
|
||||
m_red_ai = 0;
|
||||
m_blue_ai = 0;
|
||||
m_ball_track_sector = NULL;
|
||||
m_bgd.reset(new BallGoalData());
|
||||
} // SoccerWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -118,7 +304,7 @@ void SoccerWorld::init()
|
||||
if (!m_ball)
|
||||
Log::fatal("SoccerWorld","Ball is missing in soccer field, abort.");
|
||||
|
||||
m_bgd.init(m_ball->getPhysicalObject()->getRadius());
|
||||
m_bgd->init(m_ball->getPhysicalObject()->getRadius());
|
||||
|
||||
} // init
|
||||
|
||||
@@ -161,7 +347,7 @@ void SoccerWorld::reset(bool restart)
|
||||
|
||||
m_reset_ball_ticks = -1;
|
||||
m_ball->reset();
|
||||
m_bgd.reset();
|
||||
m_bgd->reset();
|
||||
m_ticks_back_to_own_goal = -1;
|
||||
m_ball->setEnabled(false);
|
||||
|
||||
@@ -445,7 +631,7 @@ void SoccerWorld::resetKartsToSelfGoals()
|
||||
{
|
||||
m_ball->setEnabled(true);
|
||||
m_ball->reset();
|
||||
m_bgd.resetCheckGoal(Track::getCurrentTrack());
|
||||
m_bgd->resetCheckGoal(Track::getCurrentTrack());
|
||||
for (unsigned i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
auto& kart = m_karts[i];
|
||||
@@ -635,7 +821,7 @@ void SoccerWorld::updateAIData()
|
||||
std::sort(m_blue_kdm.begin(), m_blue_kdm.end());
|
||||
|
||||
// Fill Ball and goals data
|
||||
m_bgd.updateBallAndGoal(getBallPosition(), getBallHeading());
|
||||
m_bgd->updateBallAndGoal(getBallPosition(), getBallHeading());
|
||||
|
||||
} // updateAIData
|
||||
|
||||
@@ -855,3 +1041,21 @@ void SoccerWorld::restoreCompleteState(const BareNetworkString& b)
|
||||
m_reset_ball_ticks = b.getTime();
|
||||
m_ticks_back_to_own_goal = b.getTime();
|
||||
} // restoreCompleteState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float SoccerWorld::getBallDiameter() const
|
||||
{
|
||||
return m_bgd->getDiameter();
|
||||
} // getBallDiameter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool SoccerWorld::ballApproachingGoal(KartTeam team) const
|
||||
{
|
||||
return m_bgd->isApproachingGoal(team);
|
||||
} // ballApproachingGoal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Vec3 SoccerWorld::getBallAimPosition(KartTeam team, bool reverse) const
|
||||
{
|
||||
return m_bgd->getAimPosition(team, reverse);
|
||||
} // getBallAimPosition
|
||||
|
||||
@@ -22,13 +22,12 @@
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "tracks/check_goal.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
|
||||
#include <IMesh.h>
|
||||
#include <string>
|
||||
|
||||
class AbstractKart;
|
||||
class BallGoalData;
|
||||
class Controller;
|
||||
class NetworkString;
|
||||
class TrackObject;
|
||||
@@ -79,189 +78,9 @@ private:
|
||||
}
|
||||
}; // KartDistanceMap
|
||||
|
||||
class BallGoalData
|
||||
{
|
||||
// These data are used by AI to determine ball aiming angle
|
||||
private:
|
||||
// Radius of the ball
|
||||
float m_radius;
|
||||
|
||||
// Slope of the line from ball to the center point of goals
|
||||
float m_red_goal_slope;
|
||||
float m_blue_goal_slope;
|
||||
|
||||
// The transform only takes the ball heading into account,
|
||||
// ie no hpr of ball which allowing setting aim point easier
|
||||
btTransform m_trans;
|
||||
|
||||
// Two goals
|
||||
CheckGoal* m_blue_check_goal;
|
||||
CheckGoal* m_red_check_goal;
|
||||
|
||||
// Location to red/blue goal points from the ball heading point of view
|
||||
Vec3 m_red_goal_1;
|
||||
Vec3 m_red_goal_2;
|
||||
Vec3 m_red_goal_3;
|
||||
Vec3 m_blue_goal_1;
|
||||
Vec3 m_blue_goal_2;
|
||||
Vec3 m_blue_goal_3;
|
||||
public:
|
||||
void reset()
|
||||
{
|
||||
m_red_goal_1 = Vec3(0, 0, 0);
|
||||
m_red_goal_2 = Vec3(0, 0, 0);
|
||||
m_red_goal_3 = Vec3(0, 0, 0);
|
||||
m_blue_goal_1 = Vec3(0, 0, 0);
|
||||
m_blue_goal_2 = Vec3(0, 0, 0);
|
||||
m_blue_goal_3 = Vec3(0, 0, 0);
|
||||
m_red_goal_slope = 1.0f;
|
||||
m_blue_goal_slope = 1.0f;
|
||||
m_trans = btTransform(btQuaternion(0, 0, 0, 1), Vec3(0, 0, 0));
|
||||
} // reset
|
||||
|
||||
float getDiameter() const
|
||||
{
|
||||
return m_radius * 2;
|
||||
} // getDiameter
|
||||
|
||||
void init(float ball_radius)
|
||||
{
|
||||
m_radius = ball_radius;
|
||||
assert(m_radius > 0.0f);
|
||||
|
||||
// Save two goals
|
||||
unsigned int n = CheckManager::get()->getCheckStructureCount();
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
CheckGoal* goal = dynamic_cast<CheckGoal*>
|
||||
(CheckManager::get()->getCheckStructure(i));
|
||||
if (goal)
|
||||
{
|
||||
if (goal->getTeam())
|
||||
m_blue_check_goal = goal;
|
||||
else
|
||||
m_red_check_goal = goal;
|
||||
}
|
||||
}
|
||||
if (m_blue_check_goal == NULL || m_red_check_goal == NULL)
|
||||
{
|
||||
Log::error("SoccerWorld", "Goal(s) is missing!");
|
||||
}
|
||||
} // init
|
||||
|
||||
void updateBallAndGoal(const Vec3& ball_pos, float heading)
|
||||
{
|
||||
btQuaternion quat(Vec3(0, 1, 0), -heading);
|
||||
m_trans = btTransform(btQuaternion(Vec3(0, 1, 0), heading),
|
||||
ball_pos);
|
||||
|
||||
// Red goal
|
||||
m_red_goal_1 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_FIRST) - ball_pos);
|
||||
m_red_goal_2 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_CENTER) - ball_pos);
|
||||
m_red_goal_3 = quatRotate(quat, m_red_check_goal
|
||||
->getPoint(CheckGoal::POINT_LAST) - ball_pos);
|
||||
|
||||
// Blue goal
|
||||
m_blue_goal_1 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_FIRST) - ball_pos);
|
||||
m_blue_goal_2 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_CENTER) - ball_pos);
|
||||
m_blue_goal_3 = quatRotate(quat, m_blue_check_goal
|
||||
->getPoint(CheckGoal::POINT_LAST) - ball_pos);
|
||||
|
||||
// Update the slope:
|
||||
// Use y = mx + c as an equation from goal center to ball
|
||||
// As the line always intercept in (0,0) which is the ball location,
|
||||
// so y(z)/x is the slope , it is used for determine aiming position
|
||||
// of ball later
|
||||
m_red_goal_slope = m_red_goal_2.z() / m_red_goal_2.x();
|
||||
m_blue_goal_slope = m_blue_goal_2.z() / m_blue_goal_2.x();
|
||||
} // updateBallAndGoal
|
||||
|
||||
bool isApproachingGoal(KartTeam team) const
|
||||
{
|
||||
// If the ball lies between the first and last pos, and faces
|
||||
// in front of either of them, (inside angular size of goal)
|
||||
// than it's likely to goal
|
||||
if (team == KART_TEAM_BLUE)
|
||||
{
|
||||
if ((m_blue_goal_1.z() > 0.0f || m_blue_goal_3.z() > 0.0f) &&
|
||||
((m_blue_goal_1.x() < 0.0f && m_blue_goal_3.x() > 0.0f) ||
|
||||
(m_blue_goal_3.x() < 0.0f && m_blue_goal_1.x() > 0.0f)))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((m_red_goal_1.z() > 0.0f || m_red_goal_3.z() > 0.0f) &&
|
||||
((m_red_goal_1.x() < 0.0f && m_red_goal_3.x() > 0.0f) ||
|
||||
(m_red_goal_3.x() < 0.0f && m_red_goal_1.x() > 0.0f)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // isApproachingGoal
|
||||
|
||||
Vec3 getAimPosition(KartTeam team, bool reverse) const
|
||||
{
|
||||
// If it's likely to goal already, aim the ball straight behind
|
||||
// should do the job
|
||||
if (isApproachingGoal(team))
|
||||
return m_trans(Vec3(0, 0, reverse ? m_radius*2 : -m_radius*2));
|
||||
|
||||
// Otherwise do the below:
|
||||
// This is done by using Pythagorean Theorem and solving the
|
||||
// equation from ball to goal center (y = (m_***_goal_slope) x)
|
||||
|
||||
// We aim behind the ball from the center of the ball to its
|
||||
// diameter, so 2*m_radius = sqrt (x2 + y2),
|
||||
// which is next x = sqrt (2*m_radius - y2)
|
||||
// And than we have x = y / m(m_***_goal_slope)
|
||||
// After put that in the slope equation, we have
|
||||
// y = sqrt(2*m_radius*m2 / (1+m2))
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
if (team == KART_TEAM_BLUE)
|
||||
{
|
||||
y = sqrt((m_blue_goal_slope * m_blue_goal_slope * m_radius*2) /
|
||||
(1 + (m_blue_goal_slope * m_blue_goal_slope)));
|
||||
if (m_blue_goal_2.x() == 0.0f ||
|
||||
(m_blue_goal_2.x() > 0.0f && m_blue_goal_2.z() > 0.0f) ||
|
||||
(m_blue_goal_2.x() < 0.0f && m_blue_goal_2.z() > 0.0f))
|
||||
{
|
||||
// Determine when y should be negative
|
||||
y = -y;
|
||||
}
|
||||
x = y / m_blue_goal_slope;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = sqrt((m_red_goal_slope * m_red_goal_slope * m_radius*2) /
|
||||
(1 + (m_red_goal_slope * m_red_goal_slope)));
|
||||
if (m_red_goal_2.x() == 0.0f ||
|
||||
(m_red_goal_2.x() > 0.0f && m_red_goal_2.z() > 0.0f) ||
|
||||
(m_red_goal_2.x() < 0.0f && m_red_goal_2.z() > 0.0f))
|
||||
{
|
||||
y = -y;
|
||||
}
|
||||
x = y / m_red_goal_slope;
|
||||
}
|
||||
assert (!std::isnan(x));
|
||||
assert (!std::isnan(y));
|
||||
// Return the world coordinates
|
||||
return (reverse ? m_trans(Vec3(-x, 0, -y)) :
|
||||
m_trans(Vec3(x, 0, y)));
|
||||
} // getAimPosition
|
||||
void resetCheckGoal(const Track* t)
|
||||
{
|
||||
m_red_check_goal->reset(*t);
|
||||
m_blue_check_goal->reset(*t);
|
||||
}
|
||||
}; // BallGoalData
|
||||
|
||||
std::vector<KartDistanceMap> m_red_kdm;
|
||||
std::vector<KartDistanceMap> m_blue_kdm;
|
||||
BallGoalData m_bgd;
|
||||
std::unique_ptr<BallGoalData> m_bgd;
|
||||
|
||||
/** Keep a pointer to the track object of soccer ball */
|
||||
TrackObject* m_ball;
|
||||
@@ -367,14 +186,11 @@ public:
|
||||
float getBallHeading() const
|
||||
{ return m_ball_heading; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getBallDiameter() const
|
||||
{ return m_bgd.getDiameter(); }
|
||||
float getBallDiameter() const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool ballApproachingGoal(KartTeam team) const
|
||||
{ return m_bgd.isApproachingGoal(team); }
|
||||
bool ballApproachingGoal(KartTeam team) const;
|
||||
// ------------------------------------------------------------------------
|
||||
Vec3 getBallAimPosition(KartTeam team, bool reverse = false) const
|
||||
{ return m_bgd.getAimPosition(team, reverse); }
|
||||
Vec3 getBallAimPosition(KartTeam team, bool reverse = false) const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool isCorrectGoal(unsigned int kart_id, bool first_goal) const;
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -883,7 +883,7 @@ void World::moveKartTo(AbstractKart* kart, const btTransform &transform)
|
||||
// Project kart to surface of track
|
||||
// This will set the physics transform
|
||||
Track::getCurrentTrack()->findGround(kart);
|
||||
CheckManager::get()->resetAfterKartMove(kart);
|
||||
Track::getCurrentTrack()->getCheckManager()->resetAfterKartMove(kart);
|
||||
|
||||
} // moveKartTo
|
||||
|
||||
|
||||
@@ -1946,7 +1946,7 @@ void ServerLobby::finishedLoadingLiveJoinClient(Event* event)
|
||||
spectator = true;
|
||||
}
|
||||
|
||||
const uint8_t cc = (uint8_t)CheckManager::get()->getCheckStructureCount();
|
||||
const uint8_t cc = (uint8_t)Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount();
|
||||
NetworkString* ns = getNetworkString(10);
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(LE_LIVE_JOIN_ACK).addUInt64(m_client_starting_time)
|
||||
@@ -4386,7 +4386,7 @@ void ServerLobby::configPeersStartTime()
|
||||
NetworkString* ns = getNetworkString(10);
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(LE_START_RACE).addUInt64(start_time);
|
||||
const uint8_t cc = (uint8_t)CheckManager::get()->getCheckStructureCount();
|
||||
const uint8_t cc = (uint8_t)Track::getCurrentTrack()->getCheckManager()->getCheckStructureCount();
|
||||
ns->addUInt8(cc);
|
||||
*ns += *m_items_complete_state;
|
||||
m_client_starting_time = start_time;
|
||||
|
||||
@@ -358,7 +358,7 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks,
|
||||
}
|
||||
|
||||
// Update check line, so the cannon animation can be replayed correctly
|
||||
CheckManager::get()->resetAfterRewind();
|
||||
Track::getCurrentTrack()->getCheckManager()->resetAfterRewind();
|
||||
|
||||
if (exact_rewind_ticks >= 2)
|
||||
{
|
||||
|
||||
@@ -25,11 +25,10 @@
|
||||
#include "items/item.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
|
||||
CheckCylinder::CheckCylinder(const XMLNode &node,
|
||||
std::function<void(int)> triggering_function)
|
||||
: CheckStructure(CheckManager::get()->getCheckStructureCount())
|
||||
: CheckStructure()
|
||||
{
|
||||
m_radius2 = 1;
|
||||
m_height = 0;
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#include "tracks/drive_graph.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
CheckManager *CheckManager::m_check_manager = NULL;
|
||||
|
||||
/** Loads all check structure informaiton from the specified xml file.
|
||||
*/
|
||||
void CheckManager::load(const XMLNode &node)
|
||||
@@ -106,7 +104,6 @@ CheckManager::~CheckManager()
|
||||
{
|
||||
delete m_all_checks[i];
|
||||
}
|
||||
m_check_manager = NULL;
|
||||
} // ~CheckManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -40,12 +40,8 @@ class CheckManager : public NoCopy
|
||||
{
|
||||
private:
|
||||
std::vector<CheckStructure*> m_all_checks;
|
||||
static CheckManager *m_check_manager;
|
||||
/** Private constructor, to make sure it is only called via
|
||||
* the static create function. */
|
||||
CheckManager() {m_all_checks.clear();};
|
||||
~CheckManager();
|
||||
public:
|
||||
~CheckManager();
|
||||
void add(CheckStructure* strct) { m_all_checks.push_back(strct); }
|
||||
void addFlyableToCannons(Flyable *flyable);
|
||||
void removeFlyableFromCannons(Flyable *flyable);
|
||||
@@ -57,21 +53,9 @@ public:
|
||||
unsigned int getLapLineIndex() const;
|
||||
int getChecklineTriggering(const Vec3 &from, const Vec3 &to) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates an instance of the check manager. */
|
||||
static void create()
|
||||
{
|
||||
assert(!m_check_manager);
|
||||
m_check_manager = new CheckManager();
|
||||
} // create
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the instance of the check manager. */
|
||||
static CheckManager* get() { return m_check_manager; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Destroys the check manager. */
|
||||
static void destroy() { delete m_check_manager; m_check_manager = NULL; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of check structures defined. */
|
||||
unsigned int getCheckStructureCount() const { return (unsigned int) m_all_checks.size(); }
|
||||
unsigned int getCheckStructureCount() const
|
||||
{ return (unsigned int) m_all_checks.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the nth. check structure. */
|
||||
CheckStructure *getCheckStructure(unsigned int n) const
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -73,6 +74,15 @@ CheckStructure::CheckStructure(const XMLNode &node, unsigned int index)
|
||||
node.get("active", &m_active_at_reset);
|
||||
} // CheckStructure
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
CheckStructure::CheckStructure()
|
||||
: m_active_at_reset(true),
|
||||
m_index(Track::getCurrentTrack()->getCheckManager()
|
||||
->getCheckStructureCount()),
|
||||
m_check_type(CT_TRIGGER)
|
||||
{
|
||||
} // CheckStructure
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the 'previous positions' of all karts with the start position
|
||||
* defined for this track.
|
||||
@@ -138,10 +148,10 @@ void CheckStructure::changeStatus(const std::vector<int> &indices,
|
||||
UserConfigParams::m_check_debug && race_manager->getNumPlayers()>0 &&
|
||||
kart_index == (int)World::getWorld()->getPlayerKart(0)->getWorldKartId();
|
||||
|
||||
CheckManager* cm = Track::getCurrentTrack()->getCheckManager();
|
||||
for(unsigned int i=0; i<indices.size(); i++)
|
||||
{
|
||||
CheckStructure *cs =
|
||||
CheckManager::get()->getCheckStructure(indices[i]);
|
||||
CheckStructure *cs = cm->getCheckStructure(indices[i]);
|
||||
if (cs == NULL) continue;
|
||||
|
||||
switch(change_state)
|
||||
@@ -187,9 +197,9 @@ void CheckStructure::changeStatus(const std::vector<int> &indices,
|
||||
|
||||
/*
|
||||
printf("--------\n");
|
||||
for (int n=0; n<CheckManager::get()->getCheckStructureCount(); n++)
|
||||
for (int n=0; n<m->getCheckStructureCount(); n++)
|
||||
{
|
||||
CheckStructure *cs = CheckManager::get()->getCheckStructure(n);
|
||||
CheckStructure *cs = cm->getCheckStructure(n);
|
||||
if (dynamic_cast<CheckLap*>(cs) != NULL)
|
||||
printf("Checkline %i (LAP) : %i\n", n, (int)cs->m_is_active[kart_index]);
|
||||
else
|
||||
|
||||
@@ -84,8 +84,7 @@ protected:
|
||||
unsigned int m_index;
|
||||
|
||||
/** For CheckTrigger or CheckCylinder */
|
||||
CheckStructure(unsigned index) : m_active_at_reset(true), m_index(index),
|
||||
m_check_type(CT_TRIGGER) {}
|
||||
CheckStructure();
|
||||
private:
|
||||
/** The type of this checkline. */
|
||||
CheckType m_check_type;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "tracks/check_trigger.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
/** Constructor for a check trigger.
|
||||
@@ -28,7 +27,7 @@
|
||||
*/
|
||||
CheckTrigger::CheckTrigger(const Vec3& center, float distance,
|
||||
std::function<void(int)> triggering_function)
|
||||
: CheckStructure(CheckManager::get()->getCheckStructureCount()),
|
||||
: CheckStructure(),
|
||||
m_center(center), m_distance2(distance * distance),
|
||||
m_triggering_function(triggering_function)
|
||||
{
|
||||
|
||||
@@ -283,7 +283,7 @@ unsigned int DriveGraph::getStartNode() const
|
||||
void DriveGraph::computeChecklineRequirements()
|
||||
{
|
||||
computeChecklineRequirements(getNode(0),
|
||||
CheckManager::get()->getLapLineIndex());
|
||||
Track::getCurrentTrack()->getCheckManager()->getLapLineIndex());
|
||||
} // computeChecklineRequirements
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -302,7 +302,7 @@ void DriveGraph::computeChecklineRequirements(DriveNode* node,
|
||||
|
||||
DriveNode* succ = getNode(succ_id);
|
||||
int new_latest_checkline =
|
||||
CheckManager::get()->getChecklineTriggering(node->getCenter(),
|
||||
Track::getCurrentTrack()->getCheckManager()->getChecklineTriggering(node->getCenter(),
|
||||
succ->getCenter() );
|
||||
if(new_latest_checkline==-1)
|
||||
new_latest_checkline = latest_checkline;
|
||||
|
||||
@@ -164,6 +164,7 @@ Track::Track(const std::string &filename)
|
||||
m_cache_track = UserConfigParams::m_cache_overworld &&
|
||||
m_ident=="overworld";
|
||||
m_render_target = NULL;
|
||||
m_check_manager = NULL;
|
||||
m_minimap_x_scale = 1.0f;
|
||||
m_minimap_y_scale = 1.0f;
|
||||
m_force_disable_fog = false;
|
||||
@@ -289,7 +290,7 @@ void Track::removeCachedData()
|
||||
void Track::reset()
|
||||
{
|
||||
m_ambient_color = m_default_ambient_color;
|
||||
CheckManager::get()->reset(*this);
|
||||
m_check_manager->reset(*this);
|
||||
ItemManager::get()->reset();
|
||||
m_track_object_manager->reset();
|
||||
m_startup_run = false;
|
||||
@@ -347,7 +348,8 @@ void Track::cleanup()
|
||||
|
||||
m_all_emitters.clearAndDeleteAll();
|
||||
|
||||
CheckManager::destroy();
|
||||
delete m_check_manager;
|
||||
m_check_manager = NULL;
|
||||
|
||||
delete m_track_object_manager;
|
||||
m_track_object_manager = NULL;
|
||||
@@ -1623,7 +1625,7 @@ void Track::update(int ticks)
|
||||
m_startup_run = true;
|
||||
}
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
CheckManager::get()->update(dt);
|
||||
m_check_manager->update(dt);
|
||||
ItemManager::get()->update(ticks);
|
||||
|
||||
// TODO: enable onUpdate scripts if we ever find a compelling use for them
|
||||
@@ -1788,7 +1790,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
reverse_track = false;
|
||||
}
|
||||
main_loop->renderGUI(3000);
|
||||
CheckManager::create();
|
||||
m_check_manager = new CheckManager();
|
||||
assert(m_all_cached_meshes.size()==0);
|
||||
if(UserConfigParams::logMemory())
|
||||
{
|
||||
@@ -2222,7 +2224,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
|
||||
// Only print warning if not in battle mode, since battle tracks don't have
|
||||
// any quads or check lines.
|
||||
if (CheckManager::get()->getCheckStructureCount()==0 &&
|
||||
if (m_check_manager->getCheckStructureCount()==0 &&
|
||||
!race_manager->isBattleMode() && !m_is_cutscene)
|
||||
{
|
||||
Log::warn("track", "No check lines found in track '%s'.",
|
||||
@@ -2342,7 +2344,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path,
|
||||
}
|
||||
else if (name == "checks")
|
||||
{
|
||||
CheckManager::get()->load(*node);
|
||||
m_check_manager->load(*node);
|
||||
}
|
||||
else if (name == "particle-emitter")
|
||||
{
|
||||
|
||||
@@ -352,6 +352,7 @@ private:
|
||||
|
||||
/** The render target for the mini map, which is displayed in the race gui. */
|
||||
RenderTarget *m_render_target;
|
||||
CheckManager* m_check_manager;
|
||||
float m_minimap_x_scale;
|
||||
float m_minimap_y_scale;
|
||||
|
||||
@@ -709,6 +710,8 @@ public:
|
||||
bool isAddon() const { return m_is_addon; }
|
||||
// ------------------------------------------------------------------------
|
||||
void convertTrackToBullet(scene::ISceneNode *node);
|
||||
// ------------------------------------------------------------------------
|
||||
CheckManager* getCheckManager() const { return m_check_manager; }
|
||||
}; // class Track
|
||||
|
||||
#endif
|
||||
|
||||
@@ -679,7 +679,7 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(
|
||||
|
||||
if (trigger_when_near)
|
||||
{
|
||||
CheckManager::get()->add(
|
||||
Track::getCurrentTrack()->getCheckManager()->add(
|
||||
new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
|
||||
&TrackObjectPresentationSound::onTriggerItemApproached,
|
||||
this, std::placeholders::_1)));
|
||||
@@ -1097,14 +1097,14 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
|
||||
|
||||
if (m_type == TRIGGER_TYPE_POINT)
|
||||
{
|
||||
CheckManager::get()->add(
|
||||
Track::getCurrentTrack()->getCheckManager()->add(
|
||||
new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
|
||||
&TrackObjectPresentationActionTrigger::onTriggerItemApproached,
|
||||
this, std::placeholders::_1)));
|
||||
}
|
||||
else if (m_type == TRIGGER_TYPE_CYLINDER)
|
||||
{
|
||||
CheckManager::get()->add(new CheckCylinder(xml_node, std::bind(
|
||||
Track::getCurrentTrack()->getCheckManager()->add(new CheckCylinder(xml_node, std::bind(
|
||||
&TrackObjectPresentationActionTrigger::onTriggerItemApproached,
|
||||
this, std::placeholders::_1)));
|
||||
}
|
||||
@@ -1129,7 +1129,7 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
|
||||
m_xml_reenable_timeout = 999999.9f;
|
||||
setReenableTimeout(0.0f);
|
||||
m_type = TRIGGER_TYPE_POINT;
|
||||
CheckManager::get()->add(
|
||||
Track::getCurrentTrack()->getCheckManager()->add(
|
||||
new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
|
||||
&TrackObjectPresentationActionTrigger::onTriggerItemApproached,
|
||||
this, std::placeholders::_1)));
|
||||
|
||||
Reference in New Issue
Block a user