Add support for CTF map

This commit is contained in:
Benau 2018-08-16 02:09:44 +08:00
parent 03728708cd
commit 73c264df94
14 changed files with 471 additions and 282 deletions

View File

@ -36,7 +36,6 @@
#include "karts/abstract_kart.hpp"
#include "karts/explosion_animation.hpp"
#include "modes/linear_world.hpp"
#include "modes/soccer_world.hpp"
#include "network/compress_network_body.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
@ -243,14 +242,11 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
kart->isInvulnerable() ||
kart->getKartAnimation() ) continue;
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
if (sw)
{
// Don't hit teammates in soccer world
if (sw->getKartTeam(kart->getWorldKartId()) == sw
->getKartTeam(m_owner->getWorldKartId()))
// Don't hit teammates in team world
if (world->hasTeam() &&
world->getKartTeam(kart->getWorldKartId()) ==
world->getKartTeam(m_owner->getWorldKartId()))
continue;
}
btTransform t=kart->getTrans();
@ -548,15 +544,12 @@ void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
for ( unsigned int i = 0 ; i < world->getNumKarts() ; i++ )
{
AbstractKart *kart = world->getKart(i);
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
if (sw)
{
// Don't explode teammates in soccer world
if (sw->getKartTeam(kart->getWorldKartId()) == sw
->getKartTeam(m_owner->getWorldKartId()))
// Don't explode teammates in team world
if (world->hasTeam() &&
world->getKartTeam(kart->getWorldKartId()) ==
world->getKartTeam(m_owner->getWorldKartId()))
continue;
}
if (kart->isGhostKart()) continue;
// If no secondary hits should be done, only hit the

View File

@ -39,7 +39,6 @@
#include "karts/explosion_animation.hpp"
#include "karts/kart_properties.hpp"
#include "modes/world.hpp"
#include "modes/soccer_world.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
@ -290,14 +289,11 @@ void Swatter::chooseTarget()
if (kart->isInvulnerable() || kart->isSquashed())
continue;
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
if (sw)
{
// Don't hit teammates in soccer world
if (sw->getKartTeam(kart->getWorldKartId()) == sw
->getKartTeam(m_kart->getWorldKartId()))
// Don't hit teammates in team world
if (world->hasTeam() &&
world->getKartTeam(kart->getWorldKartId()) ==
world->getKartTeam(m_kart->getWorldKartId()))
continue;
}
float dist2 = (kart->getXYZ()-m_kart->getXYZ()).length2();
if(dist2<min_dist2)

View File

@ -16,8 +16,11 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "modes/capture_the_flag.hpp"
#include "io/file_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "network/network_config.hpp"
#include "tracks/track.hpp"
#include <algorithm>
//-----------------------------------------------------------------------------
@ -25,10 +28,55 @@
*/
CaptureTheFlag::CaptureTheFlag() : FreeForAll()
{
m_red_flag_node = m_blue_flag_node = NULL;
m_red_flag_mesh = m_blue_flag_mesh = NULL;
#ifndef SERVER_ONLY
file_manager->pushTextureSearchPath(
file_manager->getAsset(FileManager::MODEL,""), "models");
m_red_flag_mesh = irr_driver->getAnimatedMesh
(file_manager->getAsset(FileManager::MODEL, "red_flag.spm"));
m_blue_flag_mesh = irr_driver->getAnimatedMesh
(file_manager->getAsset(FileManager::MODEL, "blue_flag.spm"));
assert(m_red_flag_mesh);
assert(m_blue_flag_mesh);
irr_driver->grabAllTextures(m_red_flag_mesh);
irr_driver->grabAllTextures(m_blue_flag_mesh);
file_manager->popTextureSearchPath();
#endif
} // CaptureTheFlag
//-----------------------------------------------------------------------------
CaptureTheFlag::~CaptureTheFlag()
{
#ifndef SERVER_ONLY
irr_driver->dropAllTextures(m_red_flag_mesh);
irr_driver->dropAllTextures(m_blue_flag_mesh);
irr_driver->removeMeshFromCache(m_red_flag_mesh);
irr_driver->removeMeshFromCache(m_blue_flag_mesh);
#endif
} // ~CaptureTheFlag
//-----------------------------------------------------------------------------
void CaptureTheFlag::init()
{
FreeForAll::init();
const btTransform& red_pos = Track::getCurrentTrack()->getRedFlag();
const btTransform& blue_pos = Track::getCurrentTrack()->getBlueFlag();
#ifndef SERVER_ONLY
m_red_flag_node = irr_driver->addAnimatedMesh(m_red_flag_mesh, "red_flag");
m_blue_flag_node = irr_driver->addAnimatedMesh(m_blue_flag_mesh,
"blue_flag");
assert(m_red_flag_node);
assert(m_blue_flag_node);
m_red_flag_node->setPosition(Vec3(red_pos.getOrigin()).toIrrVector());
Vec3 hpr;
hpr.setHPR(red_pos.getRotation());
m_red_flag_node->setRotation(hpr.toIrrHPR());
m_blue_flag_node->setPosition(Vec3(blue_pos.getOrigin()).toIrrVector());
hpr.setHPR(blue_pos.getRotation());
m_blue_flag_node->setRotation(hpr.toIrrHPR());
#endif
} // init

View File

@ -23,14 +23,36 @@
#include <vector>
#include <string>
namespace irr
{
namespace scene
{
class IAnimatedMeshSceneNode; class IAnimatedMesh;
}
}
class CaptureTheFlag : public FreeForAll
{
private:
scene::IAnimatedMeshSceneNode* m_red_flag_node;
scene::IAnimatedMeshSceneNode* m_blue_flag_node;
irr::scene::IAnimatedMesh* m_red_flag_mesh;
irr::scene::IAnimatedMesh* m_blue_flag_mesh;
public:
// ------------------------------------------------------------------------
CaptureTheFlag();
// ------------------------------------------------------------------------
virtual ~CaptureTheFlag();
// ------------------------------------------------------------------------
virtual void init() OVERRIDE;
// ------------------------------------------------------------------------
virtual bool hasTeam() const OVERRIDE { return true; }
// ------------------------------------------------------------------------
}; // CaptureTheFlag
#endif

View File

@ -22,7 +22,6 @@
#include "audio/sfx_base.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/render_info.hpp"
#include "karts/kart_model.hpp"
@ -166,7 +165,6 @@ void SoccerWorld::reset()
}
m_reset_ball_ticks = -1;
initKartList();
m_ball->reset();
m_bgd.reset();
m_ball->setEnabled(false);
@ -484,40 +482,6 @@ void SoccerWorld::countdownReachedZero()
m_count_down_reached_zero = true;
} // countdownReachedZero
//-----------------------------------------------------------------------------
void SoccerWorld::initKartList()
{
#ifndef SERVER_ONLY
const unsigned int kart_amount = (unsigned int)m_karts.size();
//Loading the indicator textures
std::string red_path =
file_manager->getAsset(FileManager::GUI, "soccer_player_red.png");
std::string blue_path =
file_manager->getAsset(FileManager::GUI, "soccer_player_blue.png");
//Assigning indicators
for(unsigned int i = 0; i < kart_amount; i++)
{
scene::ISceneNode *arrow_node = NULL;
KartModel* km = m_karts[i]->getKartModel();
// Color of karts can be changed using shaders if the model supports
if (km->supportColorization() && CVS->isGLSL()) continue;
float arrow_pos_height = km->getHeight() + 0.5f;
KartTeam team = getKartTeam(i);
arrow_node = irr_driver->addBillboard(
core::dimension2d<irr::f32>(0.3f,0.3f),
team == KART_TEAM_BLUE ? blue_path : red_path,
m_karts[i]->getNode());
arrow_node->setPosition(core::vector3df(0, arrow_pos_height, 0));
}
#endif
} // initKartList
//-----------------------------------------------------------------------------
bool SoccerWorld::getKartSoccerResult(unsigned int kart_id) const
{
@ -534,112 +498,6 @@ bool SoccerWorld::getKartSoccerResult(unsigned int kart_id) const
} // getKartSoccerResult
//-----------------------------------------------------------------------------
std::shared_ptr<AbstractKart> SoccerWorld::createKart
(const std::string &kart_ident, int index, int local_player_id,
int global_player_id, RaceManager::KartType kart_type,
PerPlayerDifficulty difficulty)
{
int cur_red = getTeamNum(KART_TEAM_RED);
int cur_blue = getTeamNum(KART_TEAM_BLUE);
int pos_index = 0;
int position = index + 1;
KartTeam team = KART_TEAM_BLUE;
if (kart_type == RaceManager::KT_AI)
{
if (index < m_red_ai)
team = KART_TEAM_RED;
else
team = KART_TEAM_BLUE;
m_kart_team_map[index] = team;
}
else if (NetworkConfig::get()->isNetworking())
{
m_kart_team_map[index] = race_manager->getKartInfo(index).getKartTeam();
team = race_manager->getKartInfo(index).getKartTeam();
}
else
{
int rm_id = index -
(race_manager->getNumberOfKarts() - race_manager->getNumPlayers());
assert(rm_id >= 0);
team = race_manager->getKartInfo(rm_id).getKartTeam();
m_kart_team_map[index] = team;
}
core::stringw online_name;
if (global_player_id > -1)
{
online_name = race_manager->getKartInfo(global_player_id)
.getPlayerName();
}
// Notice: In blender, please set 1,3,5,7... for blue starting position;
// 2,4,6,8... for red.
if (team == KART_TEAM_BLUE)
{
pos_index = 1 + 2 * cur_blue;
}
else
{
pos_index = 2 + 2 * cur_red;
}
btTransform init_pos = getStartTransform(pos_index - 1);
m_kart_position_map[index] = (unsigned)(pos_index - 1);
std::shared_ptr<RenderInfo> ri = std::make_shared<RenderInfo>();
ri = (team == KART_TEAM_BLUE ? std::make_shared<RenderInfo>(0.66f) :
std::make_shared<RenderInfo>(1.0f));
std::shared_ptr<AbstractKart> new_kart;
if (RewindManager::get()->isEnabled())
{
auto kr = std::make_shared<KartRewinder>(kart_ident, index, position,
init_pos, difficulty, ri);
kr->rewinderAdd();
new_kart = kr;
}
else
{
new_kart = std::make_shared<Kart>(kart_ident, index, position,
init_pos, difficulty, ri);
}
new_kart->init(race_manager->getKartType(index));
Controller *controller = NULL;
switch(kart_type)
{
case RaceManager::KT_PLAYER:
controller = new LocalPlayerController(new_kart.get(), local_player_id,
difficulty);
m_num_players ++;
break;
case RaceManager::KT_NETWORK_PLAYER:
controller = new NetworkPlayerController(new_kart.get());
if (!online_name.empty())
new_kart->setOnScreenText(online_name.c_str());
m_num_players++;
break;
case RaceManager::KT_AI:
controller = loadAIController(new_kart.get());
break;
case RaceManager::KT_GHOST:
break;
case RaceManager::KT_LEADER:
break;
case RaceManager::KT_SPARE_TIRE:
break;
}
new_kart->setController(controller);
return new_kart;
} // createKart
//-----------------------------------------------------------------------------
/** Localize the ball on the navigation mesh.
*/
@ -709,16 +567,6 @@ int SoccerWorld::getBallNode() const
return m_ball_track_sector->getCurrentGraphNode();
} // getBallNode
//-----------------------------------------------------------------------------
KartTeam SoccerWorld::getKartTeam(unsigned int kart_id) const
{
std::map<int, KartTeam>::const_iterator n =
m_kart_team_map.find(kart_id);
assert(n != m_kart_team_map.end());
return n->second;
} // getKartTeam
//-----------------------------------------------------------------------------
bool SoccerWorld::isCorrectGoal(unsigned int kart_id, bool first_goal) const
{
@ -800,20 +648,6 @@ int SoccerWorld::getAttacker(KartTeam team) const
return -1;
} // getAttacker
//-----------------------------------------------------------------------------
int SoccerWorld::getTeamNum(KartTeam team) const
{
int total = 0;
if (m_kart_team_map.empty()) return total;
for (unsigned int i = 0; i < (unsigned)m_karts.size(); ++i)
{
if (team == getKartTeam(m_karts[i]->getWorldKartId())) total++;
}
return total;
} // getTeamNum
//-----------------------------------------------------------------------------
unsigned int SoccerWorld::getRescuePositionIndex(AbstractKart *kart)
{
@ -911,52 +745,3 @@ void SoccerWorld::enterRaceOverState()
}
} // enterRaceOverState
//-----------------------------------------------------------------------------
void SoccerWorld::setAITeam()
{
const int total_player = race_manager->getNumPlayers();
const int total_karts = race_manager->getNumberOfKarts();
// No AI
if ((total_karts - total_player) == 0) return;
int red_player = 0;
int blue_player = 0;
for (int i = 0; i < total_player; i++)
{
KartTeam team = race_manager->getKartInfo(i).getKartTeam();
// Happen in profiling mode
if (team == KART_TEAM_NONE)
{
race_manager->setKartTeam(i, KART_TEAM_BLUE);
team = KART_TEAM_BLUE;
continue;
}
team == KART_TEAM_BLUE ? blue_player++ : red_player++;
}
int available_ai = total_karts - red_player - blue_player;
while (available_ai > 0)
{
if ((m_red_ai + red_player) > (m_blue_ai + blue_player))
{
m_blue_ai++;
available_ai--;
}
else if ((m_blue_ai + blue_player) > (m_red_ai + red_player))
{
m_red_ai++;
available_ai--;
}
else if ((m_blue_ai + blue_player) == (m_red_ai + red_player))
{
blue_player > red_player ? m_red_ai++ : m_blue_ai++;
available_ai--;
}
}
Log::debug("SoccerWorld","blue AI: %d red AI: %d", m_blue_ai, m_red_ai);
} // setAITeam

View File

@ -50,12 +50,6 @@ public:
bool m_correct_goal;
}; // ScorerData
protected:
virtual std::shared_ptr<AbstractKart> createKart
(const std::string &kart_ident, int index, int local_player_id,
int global_player_id, RaceManager::KartType type,
PerPlayerDifficulty difficulty) OVERRIDE;
private:
class KartDistanceMap
{
@ -284,20 +278,12 @@ private:
std::vector<ScorerData> m_blue_scorers;
std::vector<float> m_blue_score_times;
std::map<int, KartTeam> m_kart_team_map;
std::map<int, unsigned int> m_kart_position_map;
/** Data generated from navmesh */
TrackSector* m_ball_track_sector;
int m_red_ai;
int m_blue_ai;
float m_ball_heading;
std::vector<btTransform> m_goal_transforms;
/** Set the team for the karts */
void initKartList();
/** Function to update the location the ball on the polygon map */
void updateBallPosition(int ticks);
/** Function to update data for AI usage. */
@ -350,9 +336,6 @@ public:
/** Get the soccer result of kart in soccer world (including AIs) */
bool getKartSoccerResult(unsigned int kart_id) const;
// ------------------------------------------------------------------------
/** Get the team of kart in soccer world (including AIs) */
KartTeam getKartTeam(unsigned int kart_id) const;
// ------------------------------------------------------------------------
int getScore(KartTeam team) const
{
return (int)(team == KART_TEAM_BLUE ? m_blue_scorers.size()
@ -404,8 +387,6 @@ public:
/** Get the AI who will attack the other team ball chaser. */
int getAttacker(KartTeam team) const;
// ------------------------------------------------------------------------
void setAITeam();
// ------------------------------------------------------------------------
void handlePlayerGoalFromServer(const NetworkString& ns);
// ------------------------------------------------------------------------
void handleResetBallFromServer(const NetworkString& ns);

View File

@ -26,6 +26,7 @@
#include "challenges/unlock_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
@ -45,11 +46,11 @@
#include "karts/controller/test_ai.hpp"
#include "karts/controller/network_player_controller.hpp"
#include "karts/kart.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties_manager.hpp"
#include "karts/kart_rewinder.hpp"
#include "modes/overworld.hpp"
#include "modes/profile_world.hpp"
#include "modes/soccer_world.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "physics/btKart.hpp"
@ -67,6 +68,7 @@
#include "states_screens/race_gui.hpp"
#include "states_screens/race_result_gui.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track_object_manager.hpp"
@ -154,6 +156,7 @@ void World::init()
m_eliminated_players = 0;
m_num_players = 0;
unsigned int gk = 0;
m_red_ai = m_blue_ai = 0;
if (race_manager->hasGhostKarts())
gk = ReplayPlay::get()->getNumGhostKart();
@ -199,10 +202,9 @@ void World::init()
m_karts.push_back(ReplayPlay::get()->getGhostKart(k));
}
// Assign team of AIs for soccer mode before createKart
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(this);
if (sw)
sw->setAITeam();
// Assign team of AIs for team mode before createKart
if (hasTeam())
setAITeam();
for(unsigned int i=0; i<num_karts; i++)
{
@ -212,10 +214,20 @@ void World::init()
: race_manager->getKartIdent(i);
int local_player_id = race_manager->getKartLocalPlayerId(i);
int global_player_id = race_manager->getKartGlobalPlayerId(i);
auto newkart = createKart(kart_ident, i, local_player_id,
global_player_id, race_manager->getKartType(i),
race_manager->getPlayerDifficulty(i));
m_karts.push_back(newkart);
std::shared_ptr<AbstractKart> new_kart;
if (hasTeam())
{
new_kart = createKartWithTeam(kart_ident, i, local_player_id,
global_player_id, race_manager->getKartType(i),
race_manager->getPlayerDifficulty(i));
}
else
{
new_kart = createKart(kart_ident, i, local_player_id,
global_player_id, race_manager->getKartType(i),
race_manager->getPlayerDifficulty(i));
}
m_karts.push_back(new_kart);
} // for i
@ -244,6 +256,7 @@ void World::init()
} // if server with graphics of is watching replay
} // if getNumCameras()==0
initTeamArrows();
} // init
//-----------------------------------------------------------------------------
@ -1356,4 +1369,219 @@ unsigned int World::getNumberOfRescuePositions() const
return Track::getCurrentTrack()->getNumberOfStartPositions();
} // getNumberOfRescuePositions
/* EOF */
//-----------------------------------------------------------------------------
std::shared_ptr<AbstractKart> World::createKartWithTeam
(const std::string &kart_ident, int index, int local_player_id,
int global_player_id, RaceManager::KartType kart_type,
PerPlayerDifficulty difficulty)
{
int cur_red = getTeamNum(KART_TEAM_RED);
int cur_blue = getTeamNum(KART_TEAM_BLUE);
int pos_index = 0;
int position = index + 1;
KartTeam team = KART_TEAM_BLUE;
if (kart_type == RaceManager::KT_AI)
{
if (index < m_red_ai)
team = KART_TEAM_RED;
else
team = KART_TEAM_BLUE;
m_kart_team_map[index] = team;
}
else if (NetworkConfig::get()->isNetworking())
{
m_kart_team_map[index] = race_manager->getKartInfo(index).getKartTeam();
team = race_manager->getKartInfo(index).getKartTeam();
}
else
{
int rm_id = index -
(race_manager->getNumberOfKarts() - race_manager->getNumPlayers());
assert(rm_id >= 0);
team = race_manager->getKartInfo(rm_id).getKartTeam();
m_kart_team_map[index] = team;
}
core::stringw online_name;
if (global_player_id > -1)
{
online_name = race_manager->getKartInfo(global_player_id)
.getPlayerName();
}
// Notice: In blender, please set 1,3,5,7... for blue starting position;
// 2,4,6,8... for red.
if (team == KART_TEAM_BLUE)
{
pos_index = 1 + 2 * cur_blue;
}
else
{
pos_index = 2 + 2 * cur_red;
}
btTransform init_pos = getStartTransform(pos_index - 1);
m_kart_position_map[index] = (unsigned)(pos_index - 1);
std::shared_ptr<RenderInfo> ri = std::make_shared<RenderInfo>();
ri = (team == KART_TEAM_BLUE ? std::make_shared<RenderInfo>(0.66f) :
std::make_shared<RenderInfo>(1.0f));
std::shared_ptr<AbstractKart> new_kart;
if (RewindManager::get()->isEnabled())
{
auto kr = std::make_shared<KartRewinder>(kart_ident, index, position,
init_pos, difficulty, ri);
kr->rewinderAdd();
new_kart = kr;
}
else
{
new_kart = std::make_shared<Kart>(kart_ident, index, position,
init_pos, difficulty, ri);
}
new_kart->init(race_manager->getKartType(index));
Controller *controller = NULL;
switch(kart_type)
{
case RaceManager::KT_PLAYER:
controller = new LocalPlayerController(new_kart.get(), local_player_id,
difficulty);
m_num_players ++;
break;
case RaceManager::KT_NETWORK_PLAYER:
controller = new NetworkPlayerController(new_kart.get());
if (!online_name.empty())
new_kart->setOnScreenText(online_name.c_str());
m_num_players++;
break;
case RaceManager::KT_AI:
controller = loadAIController(new_kart.get());
break;
case RaceManager::KT_GHOST:
break;
case RaceManager::KT_LEADER:
break;
case RaceManager::KT_SPARE_TIRE:
break;
}
new_kart->setController(controller);
return new_kart;
} // createKartWithTeam
//-----------------------------------------------------------------------------
int World::getTeamNum(KartTeam team) const
{
int total = 0;
if (m_kart_team_map.empty()) return total;
for (unsigned int i = 0; i < (unsigned)m_karts.size(); ++i)
{
if (team == getKartTeam(m_karts[i]->getWorldKartId())) total++;
}
return total;
} // getTeamNum
//-----------------------------------------------------------------------------
KartTeam World::getKartTeam(unsigned int kart_id) const
{
std::map<int, KartTeam>::const_iterator n =
m_kart_team_map.find(kart_id);
assert(n != m_kart_team_map.end());
return n->second;
} // getKartTeam
//-----------------------------------------------------------------------------
void World::initTeamArrows()
{
if (!hasTeam())
return;
#ifndef SERVER_ONLY
const unsigned int kart_amount = (unsigned int)m_karts.size();
//Loading the indicator textures
std::string red_path =
file_manager->getAsset(FileManager::GUI, "soccer_player_red.png");
std::string blue_path =
file_manager->getAsset(FileManager::GUI, "soccer_player_blue.png");
//Assigning indicators
for(unsigned int i = 0; i < kart_amount; i++)
{
scene::ISceneNode *arrow_node = NULL;
KartModel* km = m_karts[i]->getKartModel();
// Color of karts can be changed using shaders if the model supports
if (km->supportColorization() && CVS->isGLSL()) continue;
float arrow_pos_height = km->getHeight() + 0.5f;
KartTeam team = getKartTeam(i);
arrow_node = irr_driver->addBillboard(
core::dimension2d<irr::f32>(0.3f,0.3f),
team == KART_TEAM_BLUE ? blue_path : red_path,
m_karts[i]->getNode());
arrow_node->setPosition(core::vector3df(0, arrow_pos_height, 0));
}
#endif
} // initTeamArrows
//-----------------------------------------------------------------------------
void World::setAITeam()
{
const int total_player = race_manager->getNumPlayers();
const int total_karts = race_manager->getNumberOfKarts();
// No AI
if ((total_karts - total_player) == 0) return;
int red_player = 0;
int blue_player = 0;
for (int i = 0; i < total_player; i++)
{
KartTeam team = race_manager->getKartInfo(i).getKartTeam();
// Happen in profiling mode
if (team == KART_TEAM_NONE)
{
race_manager->setKartTeam(i, KART_TEAM_BLUE);
team = KART_TEAM_BLUE;
continue;
}
team == KART_TEAM_BLUE ? blue_player++ : red_player++;
}
int available_ai = total_karts - red_player - blue_player;
while (available_ai > 0)
{
if ((m_red_ai + red_player) > (m_blue_ai + blue_player))
{
m_blue_ai++;
available_ai--;
}
else if ((m_blue_ai + blue_player) > (m_red_ai + red_player))
{
m_red_ai++;
available_ai--;
}
else if ((m_blue_ai + blue_player) == (m_red_ai + red_player))
{
blue_player > red_player ? m_red_ai++ : m_blue_ai++;
available_ai--;
}
}
Log::debug("World", "Blue AI: %d red AI: %d", m_blue_ai, m_red_ai);
} // setAITeam

View File

@ -25,6 +25,7 @@
* battle, etc.)
*/
#include <map>
#include <memory>
#include <vector>
#include <stdexcept>
@ -85,6 +86,13 @@ public:
private:
/** A pointer to the global world object for a race. */
static World *m_world;
// ------------------------------------------------------------------------
void setAITeam();
// ------------------------------------------------------------------------
std::shared_ptr<AbstractKart> createKartWithTeam
(const std::string &kart_ident, int index, int local_player_id,
int global_player_id, RaceManager::KartType type,
PerPlayerDifficulty difficulty);
protected:
@ -92,6 +100,12 @@ protected:
unsigned int m_magic_number;
#endif
/* Team related variables. */
int m_red_ai;
int m_blue_ai;
std::map<int, KartTeam> m_kart_team_map;
std::map<int, unsigned int> m_kart_position_map;
/** The list of all karts. */
KartList m_karts;
RandomGenerator m_random;
@ -179,7 +193,8 @@ protected:
*/
virtual float estimateFinishTimeForKart(AbstractKart* kart)
{return getTime(); }
/** Set the team arrow on karts if necessary*/
void initTeamArrows();
public:
World();
@ -334,6 +349,11 @@ public:
// ------------------------------------------------------------------------
virtual bool hasTeam() const { return false; }
// ------------------------------------------------------------------------
/** Get the team of kart in world (including AIs) */
KartTeam getKartTeam(unsigned int kart_id) const;
// ------------------------------------------------------------------------
int getTeamNum(KartTeam team) const;
// ------------------------------------------------------------------------
/** Set the network mode (true if networked) */
void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; }

View File

@ -217,9 +217,9 @@ void GameSetup::sortPlayersForGrandPrix()
} // sortPlayersForGrandPrix
//-----------------------------------------------------------------------------
void GameSetup::sortPlayersForSoccer()
void GameSetup::sortPlayersForTeamGame()
{
if (race_manager->getMinorMode() != RaceManager::MINOR_MODE_SOCCER ||
if (!race_manager->teamEnabled() ||
NetworkConfig::get()->hasTeamChoosing())
return;
std::lock_guard<std::mutex> lock(m_players_mutex);
@ -229,4 +229,4 @@ void GameSetup::sortPlayersForSoccer()
assert(player);
player->setTeam((KartTeam)(i % 2));
}
} // sortPlayersForSoccer
} // sortPlayersForTeamGame

View File

@ -164,7 +164,7 @@ public:
// ------------------------------------------------------------------------
void sortPlayersForGrandPrix();
// ------------------------------------------------------------------------
void sortPlayersForSoccer();
void sortPlayersForTeamGame();
// ------------------------------------------------------------------------
void setHitCaptureTime(int hc, float time)
{

View File

@ -121,7 +121,7 @@ void LobbyProtocol::configRemoteKart(
rki.setDefaultKartColor(profile->getDefaultKartColor());
rki.setPerPlayerDifficulty(profile->getPerPlayerDifficulty());
rki.setOnlineId(profile->getOnlineId());
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
if (race_manager->teamEnabled())
rki.setKartTeam(profile->getTeam());
// Inform the race manager about the data for this kart.
race_manager->setPlayerKart(i, rki);

View File

@ -164,12 +164,25 @@ void ServerLobby::setup()
while (it != m_available_kts.second.end())
{
Track* t = track_manager->getTrack(*it);
if (!t->isArena() || t->isInternal())
if (race_manager->getMajorMode() ==
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG)
{
it = m_available_kts.second.erase(it);
if (!t->isCTF() || t->isInternal())
{
it = m_available_kts.second.erase(it);
}
else
it++;
}
else
it++;
{
if (!t->isArena() || t->isInternal())
{
it = m_available_kts.second.erase(it);
}
else
it++;
}
}
break;
}
@ -480,7 +493,7 @@ void ServerLobby::asynchronousUpdate()
// Remove disconnected player (if any) one last time
m_game_setup->update(true);
m_game_setup->sortPlayersForGrandPrix();
m_game_setup->sortPlayersForSoccer();
m_game_setup->sortPlayersForTeamGame();
auto players = m_game_setup->getConnectedPlayers();
NetworkString* load_world = getNetworkString();
load_world->setSynchronous(true);

View File

@ -130,6 +130,7 @@ Track::Track(const std::string &filename)
m_enable_push_back = true;
m_reverse_available = false;
m_is_arena = false;
m_is_ctf = false;
m_max_arena_players = 0;
m_has_easter_eggs = false;
m_has_navmesh = false;
@ -160,6 +161,8 @@ Track::Track(const std::string &filename)
m_minimap_y_scale = 1.0f;
m_force_disable_fog = false;
m_startup_run = false;
m_red_flag = m_blue_flag =
btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
m_default_number_of_laps = 3;
m_all_nodes.clear();
m_static_physics_only_nodes.clear();
@ -545,6 +548,7 @@ void Track::loadTrackInfo()
root->get("friction", &m_friction);
root->get("soccer", &m_is_soccer);
root->get("arena", &m_is_arena);
root->get("ctf", &m_is_ctf);
root->get("max-arena-players", &m_max_arena_players);
root->get("cutscene", &m_is_cutscene);
root->get("groups", &m_groups);
@ -2075,6 +2079,19 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
}
} // for i<root->getNumNodes()
}
if (m_is_ctf &&
race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG)
{
for (unsigned int i=0; i<root->getNumNodes(); i++)
{
const XMLNode *node = root->getNode(i);
const std::string &name = node->getName();
if (name == "red-flag" || name == "blue-flag")
{
flagCommand(node);
}
} // for i<root->getNumNodes()
}
delete root;
if (NetworkConfig::get()->isNetworking() &&
@ -2146,6 +2163,9 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
unsigned int start_position_counter = 0;
unsigned int node_count = root->getNumNodes();
const bool is_mode_ctf = m_is_ctf && race_manager->getMajorMode() ==
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG;
for (unsigned int i = 0; i < node_count; i++)
{
const XMLNode *node = root->getNode(i);
@ -2168,12 +2188,16 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
}
else if (name == "banana" || name == "item" ||
name == "small-nitro" || name == "big-nitro" ||
name == "easter-egg" )
name == "easter-egg" || name == "red-flag" ||
name == "blue-flag")
{
// will be handled later
}
else if (name == "start")
else if (name == "start" || name == "ctf-start")
{
if ((name == "start" && is_mode_ctf) ||
(name == "ctf-start" && !is_mode_ctf))
continue;
unsigned int position = start_position_counter;
start_position_counter++;
node->get("position", &position);
@ -2397,6 +2421,67 @@ void Track::handleSky(const XMLNode &xml_node, const std::string &filename)
} // if sky-box
} // handleSky
//-----------------------------------------------------------------------------
void Track::flagCommand(const XMLNode *node)
{
Vec3 xyz;
// Set some kind of default in case Y is not defined in the file
// (with the new track exporter it always is defined anyway).
// Y is the height from which the item is dropped on the track.
xyz.setY(1000);
node->getXYZ(&xyz);
Vec3 loc(xyz);
// Test if the item lies on a 3d node, if so adjust the normal
// Also do a raycast if drop item is given
Vec3 normal(0, 1, 0);
Vec3 quad_normal = normal;
Vec3 hit_point = loc;
if (Graph::get())
{
int road_sector = Graph::UNKNOWN_SECTOR;
Graph::get()->findRoadSector(xyz, &road_sector);
// Only do custom direction of raycast if item is on quad graph
if (road_sector != Graph::UNKNOWN_SECTOR)
{
quad_normal = Graph::get()->getQuad(road_sector)->getNormal();
}
}
const Material *m;
// If raycast is used, increase the start position slightly
// in case that the point is too close to the actual surface
// (e.g. floating point errors can cause a problem here).
loc += quad_normal * 0.1f;
#ifndef DEBUG
m_track_mesh->castRay(loc, loc + (-10000 * quad_normal), &hit_point,
&m, &normal);
#else
bool drop_success = m_track_mesh->castRay(loc, loc +
(-10000 * quad_normal), &hit_point, &m, &normal);
if (!drop_success)
{
Log::warn("track", "flag at position (%f,%f,%f) can not be dropped",
loc.getX(), loc.getY(), loc.getZ());
Log::warn("track", "onto terrain - position unchanged.");
}
#endif
const std::string &name = node->getName();
if (name == "red-flag")
{
m_red_flag = btTransform(shortestArcQuat(Vec3(0, 1, 0), normal),
hit_point);
}
else
{
m_blue_flag = btTransform(shortestArcQuat(Vec3(0, 1, 0), normal),
hit_point);
}
} // flagCommand
//-----------------------------------------------------------------------------
/** Handle creation and placement of an item.
* \param xyz The position of the item.
@ -2408,6 +2493,13 @@ void Track::itemCommand(const XMLNode *node)
{
const std::string &name = node->getName();
const bool is_mode_ctf = m_is_ctf &&
race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG;
bool ctf = false;
node->get("ctf", &ctf);
if ((is_mode_ctf && !ctf) || (!is_mode_ctf && ctf))
return;
Item::ItemType type;
if (name=="banana" ) type = Item::ITEM_BANANA;
else if(name=="item" ) type = Item::ITEM_BONUS_BOX;

View File

@ -200,8 +200,11 @@ private:
Vec3 m_aabb_min;
/** Maximum coordinates of this track. */
Vec3 m_aabb_max;
btTransform m_red_flag;
btTransform m_blue_flag;
/** True if this track is an arena. */
bool m_is_arena;
bool m_is_ctf;
/** Max players supported by an arena. */
unsigned int m_max_arena_players;
/** True if this track has easter eggs. */
@ -427,6 +430,7 @@ public:
void update(int ticks);
void reset();
void itemCommand(const XMLNode *node);
void flagCommand(const XMLNode *node);
core::stringw getName() const;
core::stringw getSortName() const;
bool isInGroup(const std::string &group_name);
@ -447,6 +451,8 @@ public:
/** Returns true if this track has an arena mode. */
bool isArena() const { return m_is_arena; }
// ------------------------------------------------------------------------
bool isCTF() const { return m_is_ctf; }
// ------------------------------------------------------------------------
/** Returns true if this track is a racing track. This means it is not an
* internal track (like cut scenes), arena, or soccer field. */
bool isRaceTrack() const
@ -681,6 +687,11 @@ public:
/** Adds the parent of the meta library for correction later */
void addMetaLibrary(TrackObject* parent, TrackObject* meta_library)
{ m_meta_library.emplace_back(parent, meta_library); }
// ------------------------------------------------------------------------
const btTransform& getRedFlag() const { return m_red_flag; }
// ------------------------------------------------------------------------
const btTransform& getBlueFlag() const { return m_blue_flag; }
}; // class Track
#endif