Merge soccer mode back into trunk - but still WIP, can be disabled via a #define in race_setup_screen.cpp
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12475 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
BIN
data/gui/mode_soccer.png
Normal file
BIN
data/gui/mode_soccer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
data/gui/soccer_ball_blue.png
Normal file
BIN
data/gui/soccer_ball_blue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
BIN
data/gui/soccer_ball_empty.png
Normal file
BIN
data/gui/soccer_ball_empty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
data/gui/soccer_ball_red.png
Normal file
BIN
data/gui/soccer_ball_red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
35
data/gui/soccer_setup.stkgui
Normal file
35
data/gui/soccer_setup.stkgui
Normal file
@@ -0,0 +1,35 @@
|
||||
<stkgui>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
|
||||
<header width="80%" text="Race Setup" align="center" text_align="center" />
|
||||
|
||||
<spacer height="25" width="25"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="50" align="center">
|
||||
<bright proportion="1" height="100%"
|
||||
I18N="In soccer setup menu" text="Number of goals to win" text_align="right" />
|
||||
<spacer width="50" height="25"/>
|
||||
<spinner id="goalamount" proportion="1" height="100%" min_value="1" max_value="30" wrap_around="true"/>
|
||||
</div>
|
||||
|
||||
<spacer height="25" width="25"/>
|
||||
|
||||
<bright height="15" width="25" I18N="In soccer setup menu" text="Use left/right to choose your team" text_align="center" align="center" />
|
||||
|
||||
<spacer height="25" width="25"/>
|
||||
|
||||
<div id="central_div" layout="horizontal-row" width="100%" proportion="1" align="center">
|
||||
<roundedbox x="2%" y="5%" proportion="1" layout="horizontal-row" height="100%">
|
||||
<!-- Content is added programmatically -->
|
||||
</roundedbox>
|
||||
<header id="vs" text="VS"/> <!-- Layout is done programmatically -->
|
||||
</div>
|
||||
|
||||
<button id="continue" I18N="In soccer setup screen" text="Continue" align="center" width="60%"/>
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
||||
@@ -127,6 +127,7 @@ src/modes/game_tutorial.cpp
|
||||
src/modes/linear_world.cpp
|
||||
src/modes/overworld.cpp
|
||||
src/modes/profile_world.cpp
|
||||
src/modes/soccer_world.cpp
|
||||
src/modes/standard_race.cpp
|
||||
src/modes/three_strikes_battle.cpp
|
||||
src/modes/tutorial_world.cpp
|
||||
@@ -197,6 +198,7 @@ src/states_screens/race_gui.cpp
|
||||
src/states_screens/race_gui_overworld.cpp
|
||||
src/states_screens/race_result_gui.cpp
|
||||
src/states_screens/race_setup_screen.cpp
|
||||
src/states_screens/soccer_setup_screen.cpp
|
||||
src/states_screens/state_manager.cpp
|
||||
src/states_screens/story_mode_lobby.cpp
|
||||
src/states_screens/tracks_screen.cpp
|
||||
@@ -212,6 +214,7 @@ src/tinygettext/tinygettext.cpp
|
||||
src/tracks/ambient_light_sphere.cpp
|
||||
src/tracks/bezier_curve.cpp
|
||||
src/tracks/check_cannon.cpp
|
||||
src/tracks/check_goal.cpp
|
||||
src/tracks/check_lap.cpp
|
||||
src/tracks/check_line.cpp
|
||||
src/tracks/check_manager.cpp
|
||||
|
||||
@@ -133,11 +133,11 @@ void ModelViewWidget::update(float delta)
|
||||
|
||||
if (distance_with_positive_rotation < distance_with_negative_rotation)
|
||||
{
|
||||
angle += delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
angle += m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
angle -= delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
angle -= m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
|
||||
}
|
||||
if (angle > 360) angle -= 360;
|
||||
if (angle < 0) angle += 360;
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace GUIEngine
|
||||
LEAK_CHECK()
|
||||
|
||||
ModelViewWidget();
|
||||
~ModelViewWidget();
|
||||
virtual ~ModelViewWidget();
|
||||
|
||||
void add();
|
||||
void clearModels();
|
||||
|
||||
@@ -842,10 +842,9 @@ int handleCmdLine(int argc, char **argv)
|
||||
argv[i+1]);
|
||||
}
|
||||
else if (t->isArena())
|
||||
{
|
||||
race_manager->setMinorMode(
|
||||
RaceManager::MINOR_MODE_3_STRIKES);
|
||||
}
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_3_STRIKES);
|
||||
else if(t->isSoccer())
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_SOCCER);
|
||||
}
|
||||
/*
|
||||
else
|
||||
|
||||
@@ -116,7 +116,7 @@ bool DemoWorld::updateIdleTimeAndStartDemo(float dt)
|
||||
// Remove arena tracks and internal tracks like the overworld
|
||||
// (outside the if statement above in case that
|
||||
// a user requests one of those ;) )
|
||||
while((!track || track->isArena() || track->isInternal())
|
||||
while((!track || track->isArena() || track->isSoccer() || track->isInternal())
|
||||
&& m_demo_tracks.size() > 0)
|
||||
{
|
||||
if(!track)
|
||||
|
||||
@@ -57,6 +57,7 @@ void LinearWorld::init()
|
||||
WorldWithRank::init();
|
||||
|
||||
assert(!m_track->isArena());
|
||||
assert(!m_track->isSoccer());
|
||||
|
||||
m_last_lap_sfx_played = false;
|
||||
m_last_lap_sfx_playing = false;
|
||||
|
||||
331
src/modes/soccer_world.cpp
Normal file
331
src/modes/soccer_world.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2006 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "modes/soccer_world.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <IMeshSceneNode.h>
|
||||
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_model.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/rescue_animation.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Constructor. Sets up the clock mode etc.
|
||||
*/
|
||||
SoccerWorld::SoccerWorld() : WorldWithRank()
|
||||
{
|
||||
WorldStatus::setClockMode(CLOCK_CHRONO);
|
||||
m_use_highscores = false;
|
||||
} // SoccerWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Initializes the soccer world. It sets up the data structure
|
||||
* to keep track of points etc. for each kart.
|
||||
*/
|
||||
void SoccerWorld::init()
|
||||
{
|
||||
WorldWithRank::init();
|
||||
m_display_rank = false;
|
||||
|
||||
m_can_score_points = true;
|
||||
memset(m_team_goals, 0, sizeof(m_team_goals));
|
||||
|
||||
// check for possible problems if AI karts were incorrectly added
|
||||
if(getNumKarts() > race_manager->getNumPlayers())
|
||||
{
|
||||
fprintf(stderr, "No AI exists for this game mode\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
initKartList();
|
||||
|
||||
} // SoccerWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the internal identifier for this race.
|
||||
*/
|
||||
const std::string& SoccerWorld::getIdent() const
|
||||
{
|
||||
return IDENT_SOCCER;
|
||||
} // getIdent
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Update the world and the track.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void SoccerWorld::update(float dt)
|
||||
{
|
||||
WorldWithRank::update(dt);
|
||||
WorldWithRank::updateTrack(dt);
|
||||
|
||||
// TODO
|
||||
} // update
|
||||
|
||||
void SoccerWorld::onCheckGoalTriggered(bool first_goal)
|
||||
{
|
||||
// TODO
|
||||
if(m_can_score_points)
|
||||
printf("*** GOOOOOOOOOAAAAAAALLLLLL!!!! (team: %d) ***\n", first_goal ? 0 : 1);
|
||||
|
||||
//m_check_goals_enabled = false; // TODO: remove?
|
||||
|
||||
// Reset original positions for the soccer balls
|
||||
TrackObjectManager* tom = getTrack()->getTrackObjectManager();
|
||||
assert(tom);
|
||||
|
||||
PtrVector<TrackObject>& objects = tom->getObjects();
|
||||
for(int i=0; i<objects.size(); i++)
|
||||
{
|
||||
TrackObject* obj = objects.get(i);
|
||||
if(!obj->isSoccerBall())
|
||||
continue;
|
||||
|
||||
obj->reset();
|
||||
}
|
||||
|
||||
//for(int i=0 ; i < getNumKarts() ; i++
|
||||
|
||||
/*if(World::getWorld()->getTrack()->isAutoRescueEnabled() &&
|
||||
!getKartAnimation() && fabs(getRoll())>60*DEGREE_TO_RAD &&
|
||||
fabs(getSpeed())<3.0f )
|
||||
{
|
||||
new RescueAnimation(this, true);
|
||||
}*/
|
||||
|
||||
// TODO: rescue the karts
|
||||
// TODO: score a point
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** The battle is over if only one kart is left, or no player kart.
|
||||
*/
|
||||
bool SoccerWorld::isRaceOver()
|
||||
{
|
||||
// for tests : never over when we have a single player there :)
|
||||
if (race_manager->getNumPlayers() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0;
|
||||
} // isRaceOver
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when the race finishes, i.e. after playing (if necessary) an
|
||||
* end of race animation. It updates the time for all karts still racing,
|
||||
* and then updates the ranks.
|
||||
*/
|
||||
void SoccerWorld::terminateRace()
|
||||
{
|
||||
m_can_score_points = false;
|
||||
WorldWithRank::terminateRace();
|
||||
} // terminateRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called then a battle is restarted.
|
||||
*/
|
||||
void SoccerWorld::restartRace()
|
||||
{
|
||||
WorldWithRank::restartRace();
|
||||
|
||||
m_can_score_points = true;
|
||||
memset(m_team_goals, 0, sizeof(m_team_goals));
|
||||
|
||||
initKartList();
|
||||
|
||||
} // restartRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the data to display in the race gui.
|
||||
*/
|
||||
void SoccerWorld::getKartsDisplayInfo(
|
||||
std::vector<RaceGUIBase::KartIconDisplayInfo> *info)
|
||||
{
|
||||
// TODO!!
|
||||
/*
|
||||
const unsigned int kart_amount = getNumKarts();
|
||||
for(unsigned int i = 0; i < kart_amount ; i++)
|
||||
{
|
||||
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];
|
||||
|
||||
// reset color
|
||||
rank_info.lap = -1;
|
||||
|
||||
AbstractKart* kart = getKart(i);
|
||||
switch(kart->getSoccerTeam())
|
||||
{
|
||||
case SOCCER_TEAM_BLUE:
|
||||
rank_info.r = 0.0f;
|
||||
rank_info.g = 0.0f;
|
||||
rank_info.b = 0.7f;
|
||||
break;
|
||||
case SOCCER_TEAM_RED:
|
||||
rank_info.r = 0.9f;
|
||||
rank_info.g = 0.0f;
|
||||
rank_info.b = 0.0f;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Soccer team not set to blue or red");
|
||||
rank_info.r = 0.0f;
|
||||
rank_info.g = 0.0f;
|
||||
rank_info.b = 0.0f;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} // getKartsDisplayInfo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Moves a kart to its rescue position.
|
||||
* \param kart The kart that was rescued.
|
||||
*/
|
||||
void SoccerWorld::moveKartAfterRescue(AbstractKart* kart)
|
||||
{
|
||||
// find closest point to drop kart on
|
||||
World *world = World::getWorld();
|
||||
const int start_spots_amount = world->getTrack()->getNumberOfStartPositions();
|
||||
assert(start_spots_amount > 0);
|
||||
|
||||
float largest_accumulated_distance_found = -1;
|
||||
int furthest_id_found = -1;
|
||||
|
||||
const float kart_x = kart->getXYZ().getX();
|
||||
const float kart_z = kart->getXYZ().getZ();
|
||||
|
||||
for(int n=0; n<start_spots_amount; n++)
|
||||
{
|
||||
// no need for the overhead to compute exact distance with sqrt(),
|
||||
// so using the 'manhattan' heuristic which will do fine enough.
|
||||
const btTransform &s = world->getTrack()->getStartTransform(n);
|
||||
const Vec3 &v=s.getOrigin();
|
||||
float accumulatedDistance = .0f;
|
||||
bool spawnPointClear = true;
|
||||
|
||||
for(unsigned int k=0; k<getCurrentNumKarts(); k++)
|
||||
{
|
||||
const AbstractKart *currentKart = World::getWorld()->getKart(k);
|
||||
const float currentKart_x = currentKart->getXYZ().getX();
|
||||
const float currentKartk_z = currentKart->getXYZ().getZ();
|
||||
|
||||
if(kart_x!=currentKart_x && kart_z !=currentKartk_z)
|
||||
{
|
||||
float absDistance = fabs(currentKart_x - v.getX()) +
|
||||
fabs(currentKartk_z - v.getZ());
|
||||
if(absDistance < CLEAR_SPAWN_RANGE)
|
||||
{
|
||||
spawnPointClear = false;
|
||||
break;
|
||||
}
|
||||
accumulatedDistance += absDistance;
|
||||
}
|
||||
}
|
||||
|
||||
if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear)
|
||||
{
|
||||
furthest_id_found = n;
|
||||
largest_accumulated_distance_found = accumulatedDistance;
|
||||
}
|
||||
}
|
||||
|
||||
assert(furthest_id_found != -1);
|
||||
const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found);
|
||||
const Vec3 &xyz = s.getOrigin();
|
||||
kart->setXYZ(xyz);
|
||||
kart->setRotation(s.getRotation());
|
||||
|
||||
//position kart from same height as in World::resetAllKarts
|
||||
btTransform pos;
|
||||
pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
|
||||
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) );
|
||||
|
||||
kart->getBody()->setCenterOfMassTransform(pos);
|
||||
|
||||
//project kart to surface of track
|
||||
bool kart_over_ground = m_physics->projectKartDownwards(kart);
|
||||
|
||||
if (kart_over_ground)
|
||||
{
|
||||
//add vertical offset so that the kart starts off above the track
|
||||
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
|
||||
kart->getKartHeight();
|
||||
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n",
|
||||
(kart->getIdent().c_str()), m_track->getIdent().c_str());
|
||||
}
|
||||
} // moveKartAfterRescue
|
||||
|
||||
/** Set position and team for the karts */
|
||||
void SoccerWorld::initKartList()
|
||||
{
|
||||
const unsigned int kart_amount = m_karts.size();
|
||||
|
||||
// Set kart positions, ordering them by team
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
m_karts[n]->setPosition(-1);
|
||||
}
|
||||
// TODO: remove
|
||||
/*
|
||||
const unsigned int kart_amount = m_karts.size();
|
||||
|
||||
int team_karts_amount[NB_SOCCER_TEAMS];
|
||||
memset(team_karts_amount, 0, sizeof(team_karts_amount));
|
||||
|
||||
{
|
||||
// Set the kart teams if they haven't been already set by the setup screen
|
||||
// (happens when the setup screen is skipped, with 1 player)
|
||||
SoccerTeam round_robin_team = SOCCER_TEAM_RED;
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
if(m_karts[n]->getSoccerTeam() == SOCCER_TEAM_NONE)
|
||||
m_karts[n]->setSoccerTeam(round_robin_team);
|
||||
|
||||
team_karts_amount[m_karts[n]->getSoccerTeam()]++;
|
||||
|
||||
round_robin_team = (round_robin_team==SOCCER_TEAM_RED ?
|
||||
SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
|
||||
}// next kart
|
||||
}
|
||||
|
||||
// Compute start positions for each team
|
||||
int team_cur_position[NB_SOCCER_TEAMS];
|
||||
team_cur_position[0] = 1;
|
||||
for(int i=1 ; i < (int)NB_SOCCER_TEAMS ; i++)
|
||||
team_cur_position[i] = team_karts_amount[i-1] + team_cur_position[i-1];
|
||||
|
||||
// Set kart positions, ordering them by team
|
||||
for(unsigned int n=0; n<kart_amount; n++)
|
||||
{
|
||||
SoccerTeam team = m_karts[n]->getSoccerTeam();
|
||||
m_karts[n]->setPosition(team_cur_position[team]);
|
||||
team_cur_position[team]++;
|
||||
}// next kart
|
||||
*/
|
||||
}
|
||||
80
src/modes/soccer_world.hpp
Normal file
80
src/modes/soccer_world.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SOCCER_WORLD_HPP
|
||||
#define SOCCER_WORLD_HPP
|
||||
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
|
||||
#include <IMesh.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#define CLEAR_SPAWN_RANGE 5
|
||||
|
||||
class PhysicalObject;
|
||||
|
||||
/**
|
||||
* \brief An implementation of World, to provide the soccer game mode
|
||||
* \ingroup modes
|
||||
*/
|
||||
class SoccerWorld : public WorldWithRank
|
||||
{
|
||||
private:
|
||||
/** Number of goals each team scored
|
||||
*/
|
||||
int m_team_goals[NB_SOCCER_TEAMS];
|
||||
|
||||
/** Whether or not goals can be scored (they are disabled when a point is scored
|
||||
and re-enabled when the next game can be played)*/
|
||||
bool m_can_score_points;
|
||||
|
||||
public:
|
||||
|
||||
SoccerWorld();
|
||||
virtual ~SoccerWorld() {}
|
||||
|
||||
virtual void init();
|
||||
|
||||
// clock events
|
||||
virtual bool isRaceOver();
|
||||
virtual void terminateRace();
|
||||
|
||||
// overriding World methods
|
||||
virtual void restartRace();
|
||||
|
||||
virtual bool useFastMusicNearEnd() const { return false; }
|
||||
virtual void getKartsDisplayInfo(
|
||||
std::vector<RaceGUIBase::KartIconDisplayInfo> *info);
|
||||
virtual bool raceHasLaps(){ return false; }
|
||||
virtual void moveKartAfterRescue(AbstractKart* kart);
|
||||
|
||||
virtual const std::string& getIdent() const;
|
||||
|
||||
virtual void update(float dt);
|
||||
|
||||
void onCheckGoalTriggered(bool first_goal);
|
||||
|
||||
private:
|
||||
void initKartList();
|
||||
}; // SoccerWorld
|
||||
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,14 @@
|
||||
#include <string>
|
||||
#include <irrString.h>
|
||||
|
||||
enum SoccerTeam
|
||||
{
|
||||
SOCCER_TEAM_NONE=-1,
|
||||
SOCCER_TEAM_RED=0,
|
||||
SOCCER_TEAM_BLUE=1,
|
||||
NB_SOCCER_TEAMS
|
||||
};
|
||||
|
||||
class RemoteKartInfo
|
||||
{
|
||||
std::string m_kart_name;
|
||||
@@ -29,12 +37,13 @@ class RemoteKartInfo
|
||||
int m_local_player_id;
|
||||
int m_global_player_id;
|
||||
int m_host_id;
|
||||
SoccerTeam m_soccer_team;
|
||||
|
||||
public:
|
||||
RemoteKartInfo(int player_id, const std::string& kart_name,
|
||||
const irr::core::stringw& user_name, int host_id)
|
||||
: m_kart_name(kart_name), m_user_name(user_name),
|
||||
m_local_player_id(player_id), m_host_id(host_id)
|
||||
m_local_player_id(player_id), m_host_id(host_id), m_soccer_team(SOCCER_TEAM_NONE)
|
||||
{};
|
||||
RemoteKartInfo(const std::string& kart_name)
|
||||
{m_kart_name=kart_name; m_user_name="";
|
||||
@@ -46,11 +55,15 @@ public:
|
||||
void setHostId(int id) { m_host_id = id; }
|
||||
void setLocalPlayerId(int id) { m_local_player_id = id; }
|
||||
void setGlobalPlayerId(int id) { m_global_player_id = id; }
|
||||
void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
|
||||
|
||||
int getHostId() const { return m_host_id; }
|
||||
int getLocalPlayerId() const { return m_local_player_id; }
|
||||
int getGlobalPlayerId() const { return m_global_player_id; }
|
||||
const std::string& getKartName() const { return m_kart_name; }
|
||||
const irr::core::stringw& getPlayerName() const { return m_user_name; }
|
||||
const SoccerTeam getSoccerTeam() const {return m_soccer_team; }
|
||||
|
||||
bool operator<(const RemoteKartInfo& other) const
|
||||
{
|
||||
return ((m_host_id<other.m_host_id) ||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "modes/tutorial_world.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "modes/three_strikes_battle.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "states_screens/grand_prix_lose.hpp"
|
||||
#include "states_screens/grand_prix_win.hpp"
|
||||
@@ -144,6 +145,16 @@ void RaceManager::setLocalKartInfo(unsigned int player_id,
|
||||
network_manager->getMyHostId());
|
||||
} // setLocalKartInfo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets additional information for a player to indicate which soccer team it belong to
|
||||
*/
|
||||
void RaceManager::setLocalKartSoccerTeam(unsigned int player_id, SoccerTeam team)
|
||||
{
|
||||
assert(0<=player_id && player_id <m_local_player_karts.size());
|
||||
|
||||
m_local_player_karts[player_id].setSoccerTeam(team);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns a pointer to the kart which has a given GP rank.
|
||||
* \param n The rank (1 to number of karts) to look for.
|
||||
@@ -394,6 +405,8 @@ void RaceManager::startNextRace()
|
||||
World::setWorld(new TutorialWorld());
|
||||
else if(m_minor_mode==MINOR_MODE_3_STRIKES)
|
||||
World::setWorld(new ThreeStrikesBattle());
|
||||
else if(m_minor_mode==MINOR_MODE_SOCCER)
|
||||
World::setWorld(new SoccerWorld());
|
||||
else if(m_minor_mode==MINOR_MODE_OVERWORLD)
|
||||
World::setWorld(new OverWorld());
|
||||
else if(m_minor_mode==MINOR_MODE_CUTSCENE)
|
||||
|
||||
@@ -43,6 +43,7 @@ static const std::string IDENT_TTRIAL ("STD_TIMETRIAL" );
|
||||
static const std::string IDENT_FTL ("FOLLOW_LEADER" );
|
||||
static const std::string IDENT_STRIKES ("BATTLE_3_STRIKES");
|
||||
static const std::string IDENT_EASTER ("EASTER_EGG_HUNT");
|
||||
static const std::string IDENT_SOCCER ("SOCCER" );
|
||||
static const std::string IDENT_OVERWORLD("OVERWORLD" );
|
||||
static const std::string IDENT_CUSTSCENE("CUTSCENE" );
|
||||
|
||||
@@ -111,8 +112,8 @@ public:
|
||||
MINOR_MODE_TUTORIAL = LINEAR_RACE(4, false),
|
||||
|
||||
MINOR_MODE_3_STRIKES = BATTLE_ARENA(0),
|
||||
MINOR_MODE_CUTSCENE = BATTLE_ARENA(1),
|
||||
|
||||
MINOR_MODE_SOCCER = BATTLE_ARENA(1),
|
||||
MINOR_MODE_CUTSCENE = BATTLE_ARENA(2),
|
||||
MINOR_MODE_EASTER_EGG = EASTER_EGG(0)
|
||||
};
|
||||
|
||||
@@ -138,6 +139,7 @@ public:
|
||||
case MINOR_MODE_FOLLOW_LEADER: return IDENT_FTL;
|
||||
case MINOR_MODE_3_STRIKES: return IDENT_STRIKES;
|
||||
case MINOR_MODE_EASTER_EGG: return IDENT_EASTER;
|
||||
case MINOR_MODE_SOCCER: return IDENT_SOCCER;
|
||||
default: assert(false);
|
||||
return IDENT_STD; // stop compiler warning
|
||||
}
|
||||
@@ -156,6 +158,7 @@ public:
|
||||
case MINOR_MODE_FOLLOW_LEADER: return "/gui/mode_ftl.png";
|
||||
case MINOR_MODE_3_STRIKES: return "/gui/mode_3strikes.png";
|
||||
case MINOR_MODE_EASTER_EGG: return "/gui/mode_easter.png";
|
||||
case MINOR_MODE_SOCCER: return "/gui/mode_soccer.png";
|
||||
default: assert(false); return NULL;
|
||||
}
|
||||
} // getIconOf
|
||||
@@ -176,7 +179,10 @@ public:
|
||||
case MINOR_MODE_FOLLOW_LEADER: return _("Follow the Leader");
|
||||
//I18N: Game mode
|
||||
case MINOR_MODE_3_STRIKES: return _("3 Strikes Battle");
|
||||
//I18N: Game mode
|
||||
case MINOR_MODE_EASTER_EGG: return _("Easter Egg Hunt");
|
||||
//I18N: Game mode
|
||||
case MINOR_MODE_SOCCER: return _("Soccer");
|
||||
default: assert(false); return NULL;
|
||||
}
|
||||
}
|
||||
@@ -191,6 +197,7 @@ public:
|
||||
case MINOR_MODE_FOLLOW_LEADER: return true;
|
||||
case MINOR_MODE_3_STRIKES: return false;
|
||||
case MINOR_MODE_EASTER_EGG: return false;
|
||||
case MINOR_MODE_SOCCER: return false;
|
||||
default: assert(false); return NULL;
|
||||
}
|
||||
}
|
||||
@@ -209,6 +216,7 @@ public:
|
||||
else if (name==IDENT_FTL ) return MINOR_MODE_FOLLOW_LEADER;
|
||||
else if (name==IDENT_STRIKES) return MINOR_MODE_3_STRIKES;
|
||||
else if (name==IDENT_EASTER ) return MINOR_MODE_EASTER_EGG;
|
||||
else if (name==IDENT_SOCCER) return MINOR_MODE_SOCCER;
|
||||
|
||||
assert(0);
|
||||
return MINOR_MODE_NONE;
|
||||
@@ -353,6 +361,10 @@ public:
|
||||
*/
|
||||
void setLocalKartInfo(unsigned int player_id, const std::string& kart);
|
||||
|
||||
/** Sets additional information for a player to indicate which soccer team it belong to
|
||||
*/
|
||||
void setLocalKartSoccerTeam(unsigned int player_id, SoccerTeam team);
|
||||
|
||||
/** Sets the number of local players playing on this computer (including
|
||||
* split screen).
|
||||
* \param n Number of local players.
|
||||
|
||||
@@ -63,7 +63,8 @@ void ArenasScreen::beforeAddingWidget()
|
||||
|
||||
tabs->clearAllChildren();
|
||||
|
||||
const std::vector<std::string>& groups = track_manager->getAllArenaGroups();
|
||||
bool soccer_mode = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;
|
||||
const std::vector<std::string>& groups = track_manager->getAllArenaGroups(soccer_mode);
|
||||
const int group_amount = groups.size();
|
||||
|
||||
if (group_amount > 1)
|
||||
@@ -90,8 +91,15 @@ void ArenasScreen::beforeAddingWidget()
|
||||
for (unsigned int n=0; n<track_manager->getNumberOfTracks(); n++) //iterate through tracks to find how many are arenas
|
||||
{
|
||||
Track* temp = track_manager->getTrack(n);
|
||||
if (temp->isArena()){
|
||||
num_of_arenas++;
|
||||
if (soccer_mode)
|
||||
{
|
||||
if(temp->isSoccer())
|
||||
num_of_arenas++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(temp->isArena())
|
||||
num_of_arenas++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +138,8 @@ void ArenasScreen::eventCallback(Widget* widget, const std::string& name, const
|
||||
{
|
||||
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
|
||||
assert( tabs != NULL );
|
||||
|
||||
bool soccer_mode = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;
|
||||
|
||||
std::vector<int> curr_group;
|
||||
if (tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER) == ALL_ARENA_GROUPS_ID)
|
||||
@@ -137,7 +147,7 @@ void ArenasScreen::eventCallback(Widget* widget, const std::string& name, const
|
||||
const std::vector<std::string>& groups = track_manager->getAllArenaGroups();
|
||||
for (unsigned int i = 0; i < groups.size(); i++)
|
||||
{
|
||||
const std::vector<int>& tmp_group = track_manager->getArenasInGroup(groups[i]);
|
||||
const std::vector<int>& tmp_group = track_manager->getArenasInGroup(groups[i], soccer_mode);
|
||||
// Append to our main vector
|
||||
curr_group.insert(curr_group.end(), tmp_group.begin(), tmp_group.end());
|
||||
}
|
||||
@@ -145,7 +155,7 @@ void ArenasScreen::eventCallback(Widget* widget, const std::string& name, const
|
||||
else
|
||||
{
|
||||
curr_group = track_manager->getArenasInGroup(
|
||||
tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER) );
|
||||
tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER), soccer_mode );
|
||||
}
|
||||
|
||||
RandomGenerator random;
|
||||
@@ -206,6 +216,8 @@ void ArenasScreen::buildTrackList()
|
||||
assert( tabs != NULL );
|
||||
const std::string curr_group_name = tabs->getSelectionIDString(0);
|
||||
|
||||
bool soccer_mode = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;
|
||||
|
||||
if (curr_group_name == ALL_ARENA_GROUPS_ID)
|
||||
{
|
||||
const int trackAmount = track_manager->getNumberOfTracks();
|
||||
@@ -213,7 +225,14 @@ void ArenasScreen::buildTrackList()
|
||||
for (int n=0; n<trackAmount; n++)
|
||||
{
|
||||
Track* curr = track_manager->getTrack(n);
|
||||
if (!curr->isArena()) continue;
|
||||
if (soccer_mode)
|
||||
{
|
||||
if(!curr->isSoccer()) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!curr->isArena()) continue;
|
||||
}
|
||||
|
||||
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
|
||||
{
|
||||
@@ -230,13 +249,20 @@ void ArenasScreen::buildTrackList()
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::vector<int>& currArenas = track_manager->getArenasInGroup(curr_group_name);
|
||||
const std::vector<int>& currArenas = track_manager->getArenasInGroup(curr_group_name, soccer_mode);
|
||||
const int trackAmount = currArenas.size();
|
||||
|
||||
for (int n=0; n<trackAmount; n++)
|
||||
{
|
||||
Track* curr = track_manager->getTrack(currArenas[n]);
|
||||
if (!curr->isArena()) continue;
|
||||
if (soccer_mode)
|
||||
{
|
||||
if(!curr->isSoccer()) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!curr->isArena()) continue;
|
||||
}
|
||||
|
||||
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
|
||||
{
|
||||
|
||||
@@ -605,7 +605,7 @@ public:
|
||||
|
||||
sfx_manager->quickSound( "wee" );
|
||||
|
||||
m_model_view->setRotateTo(30.0f, 150.0f);
|
||||
m_model_view->setRotateTo(30.0f, 1.0f);
|
||||
|
||||
player_id_w *= 2;
|
||||
player_name_w = 0;
|
||||
|
||||
@@ -259,7 +259,7 @@ void MinimalRaceGUI::drawGlobalMiniMap()
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
// arenas currently don't have a map.
|
||||
if(world->getTrack()->isArena()) return;
|
||||
if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
|
||||
|
||||
const video::ITexture *mini_map = world->getTrack()->getMiniMap();
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ void RaceGUI::drawGlobalMiniMap()
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
// arenas currently don't have a map.
|
||||
if(world->getTrack()->isArena()) return;
|
||||
if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
|
||||
|
||||
const video::ITexture *mini_map = world->getTrack()->getMiniMap();
|
||||
|
||||
|
||||
@@ -720,6 +720,11 @@ void RaceGUIBase::drawGlobalReadySetGo()
|
||||
*/
|
||||
void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
|
||||
{
|
||||
// For now, don't draw player icons when in soccer mode
|
||||
const RaceManager::MinorRaceModeType minor_mode = race_manager->getMinorMode();
|
||||
if(minor_mode == RaceManager::MINOR_MODE_SOCCER)
|
||||
return;
|
||||
|
||||
int x_base = 10;
|
||||
int y_base = 20;
|
||||
unsigned int y_space = UserConfigParams::m_height - bottom_margin - y_base;
|
||||
@@ -806,9 +811,9 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
|
||||
//x,y is the target position
|
||||
int lap = info.lap;
|
||||
|
||||
// In battle mode there is no distance along track etc.
|
||||
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES ||
|
||||
race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG)
|
||||
// In battle mode mode there is no distance along track etc.
|
||||
if( minor_mode==RaceManager::MINOR_MODE_3_STRIKES ||
|
||||
minor_mode==RaceManager::MINOR_MODE_EASTER_EGG)
|
||||
{
|
||||
x = x_base;
|
||||
y = previous_y+ICON_PLAYER_WIDTH+2;
|
||||
|
||||
@@ -295,7 +295,7 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
// arenas currently don't have a map.
|
||||
if(world->getTrack()->isArena()) return;
|
||||
if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
|
||||
|
||||
Track* track = world->getTrack();
|
||||
const std::vector<OverworldChallenge>& challenges =
|
||||
|
||||
@@ -22,18 +22,21 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/arenas_screen.hpp"
|
||||
#include "states_screens/soccer_setup_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/tracks_screen.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include "states_screens/race_setup_screen.hpp"
|
||||
|
||||
#define ENABLE_SOCCER_MODE
|
||||
|
||||
const int CONFIG_CODE_NORMAL = 0;
|
||||
const int CONFIG_CODE_TIMETRIAL = 1;
|
||||
const int CONFIG_CODE_FTL = 2;
|
||||
const int CONFIG_CODE_3STRIKES = 3;
|
||||
const int CONFIG_CODE_EASTER = 4;
|
||||
const int CONFIG_CODE_SOCCER = 5;
|
||||
|
||||
using namespace GUIEngine;
|
||||
DEFINE_SCREEN_SINGLETON( RaceSetupScreen );
|
||||
@@ -135,6 +138,17 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con
|
||||
race_manager->setNumKarts( race_manager->getNumLocalPlayers() ); // no AI karts;
|
||||
StateManager::get()->pushScreen( TracksScreen::getInstance() );
|
||||
}
|
||||
else if (selectedMode == IDENT_SOCCER)
|
||||
{
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_SOCCER);
|
||||
UserConfigParams::m_game_mode = CONFIG_CODE_SOCCER;
|
||||
race_manager->setNumKarts( race_manager->getNumLocalPlayers() ); // no AI karts;
|
||||
// 1 player -> no need to choose a team or determine when the match ends
|
||||
if(race_manager->getNumLocalPlayers() <= 1)
|
||||
StateManager::get()->pushScreen( ArenasScreen::getInstance() );
|
||||
else
|
||||
StateManager::get()->pushScreen( SoccerSetupScreen::getInstance() );
|
||||
}
|
||||
else if (selectedMode == "locked")
|
||||
{
|
||||
unlock_manager->playLockSound();
|
||||
@@ -236,6 +250,16 @@ void RaceSetupScreen::init()
|
||||
name4 += _("Hit others with weapons until they lose all their lives. (Only in multiplayer games)");
|
||||
w2->addItem( name4, IDENT_STRIKES, RaceManager::getIconOf(RaceManager::MINOR_MODE_3_STRIKES));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SOCCER_MODE
|
||||
{
|
||||
irr::core::stringw name5 = irr::core::stringw(
|
||||
RaceManager::getNameOf(RaceManager::MINOR_MODE_SOCCER)) + L"\n";
|
||||
name5 += _("Push the ball to the opposite cage to score goals. (Only in multiplayer games)");
|
||||
w2->addItem( name5, IDENT_SOCCER, RaceManager::getIconOf(RaceManager::MINOR_MODE_SOCCER));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EASTER_EGG_MODE
|
||||
{
|
||||
irr::core::stringw name1 = irr::core::stringw(
|
||||
@@ -247,6 +271,7 @@ void RaceSetupScreen::init()
|
||||
RaceManager::getIconOf(RaceManager::MINOR_MODE_EASTER_EGG));
|
||||
}
|
||||
#endif
|
||||
|
||||
w2->updateItemDisplay();
|
||||
|
||||
// restore saved game mode
|
||||
@@ -267,6 +292,9 @@ void RaceSetupScreen::init()
|
||||
case CONFIG_CODE_EASTER :
|
||||
w2->setSelection(IDENT_EASTER, PLAYER_ID_GAME_MASTER, true);
|
||||
break;
|
||||
case CONFIG_CODE_SOCCER :
|
||||
w2->setSelection(IDENT_SOCCER, PLAYER_ID_GAME_MASTER, true);
|
||||
break;
|
||||
}
|
||||
|
||||
m_mode_listener = new GameModeRibbonListener(this);
|
||||
|
||||
325
src/states_screens/soccer_setup_screen.cpp
Normal file
325
src/states_screens/soccer_setup_screen.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Lionel Fuentes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "states_screens/soccer_setup_screen.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/arenas_screen.hpp"
|
||||
#include "guiengine/widgets/button_widget.hpp"
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/model_view_widget.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_model.hpp"
|
||||
|
||||
using namespace GUIEngine;
|
||||
DEFINE_SCREEN_SINGLETON( SoccerSetupScreen );
|
||||
|
||||
#define KART_CONTINUOUS_ROTATION_SPEED 35.f
|
||||
#define KART_CONFIRMATION_ROTATION_SPEED 4.f
|
||||
#define KART_CONFIRMATION_TARGET_ANGLE 10.f
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SoccerSetupScreen::SoccerSetupScreen() : Screen("soccer_setup.stkgui")
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SoccerSetupScreen::loadedFromFile()
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void SoccerSetupScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
|
||||
{
|
||||
if(name == "continue")
|
||||
{
|
||||
StateManager::get()->pushScreen( ArenasScreen::getInstance() );
|
||||
}
|
||||
else if (name == "back")
|
||||
{
|
||||
StateManager::get()->escapePressed();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void SoccerSetupScreen::beforeAddingWidget()
|
||||
{
|
||||
Widget* central_div = getWidget<Widget>("central_div");
|
||||
|
||||
// Compute some dimensions
|
||||
const core::dimension2d<u32> vs_size = GUIEngine::getTitleFont()->getDimension( L"VS" );
|
||||
const int vs_width = (int)vs_size.Width;
|
||||
const int vs_height = (int)vs_size.Height;
|
||||
const int center_x = central_div->m_x + central_div->m_w/2;
|
||||
const int center_y = central_div->m_y + central_div->m_h/2;
|
||||
|
||||
// Add "VS" label at the center of the rounded box
|
||||
LabelWidget* label_vs = getWidget<LabelWidget>("vs");
|
||||
label_vs->m_x = center_x - vs_width/2;
|
||||
label_vs->m_y = center_y - vs_height/2;
|
||||
label_vs->m_w = vs_width;
|
||||
label_vs->m_h = vs_height;
|
||||
|
||||
// Add the 3D views for the karts
|
||||
int nb_players = race_manager->getNumLocalPlayers();
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
const RemoteKartInfo& kart_info = race_manager->getLocalKartInfo(i);
|
||||
const std::string& kart_name = kart_info.getKartName();
|
||||
|
||||
const KartProperties* props = kart_properties_manager->getKart(kart_name);
|
||||
const KartModel& kart_model = props->getMasterKartModel();
|
||||
|
||||
// Add the view
|
||||
ModelViewWidget* kart_view = new ModelViewWidget();
|
||||
kart_view->m_x = 0;
|
||||
kart_view->m_y = 0;
|
||||
kart_view->m_w = 200;
|
||||
kart_view->m_h = 200; // these values will be overriden by updateKartViewsLayout() anyway
|
||||
kart_view->clearModels();
|
||||
|
||||
// Add the kart model
|
||||
kart_view->addModel( kart_model.getModel(), Vec3(0,0,0),
|
||||
Vec3(35.0f, 35.0f, 35.0f),
|
||||
kart_model.getBaseFrame() );
|
||||
kart_view->addModel( kart_model.getWheelModel(0),
|
||||
kart_model.getWheelGraphicsPosition(0) );
|
||||
kart_view->addModel( kart_model.getWheelModel(1),
|
||||
kart_model.getWheelGraphicsPosition(1) );
|
||||
kart_view->addModel( kart_model.getWheelModel(2),
|
||||
kart_model.getWheelGraphicsPosition(2) );
|
||||
kart_view->addModel( kart_model.getWheelModel(3),
|
||||
kart_model.getWheelGraphicsPosition(3) );
|
||||
kart_view->setRotateContinuously( KART_CONTINUOUS_ROTATION_SPEED );
|
||||
|
||||
kart_view->update(0);
|
||||
|
||||
central_div->getChildren().push_back(kart_view);
|
||||
|
||||
// Record info about it for further update
|
||||
KartViewInfo info;
|
||||
info.view = kart_view;
|
||||
info.confirmed = false;
|
||||
info.local_player_id = i;
|
||||
info.team = i&1 ? SOCCER_TEAM_BLUE : SOCCER_TEAM_RED;
|
||||
m_kart_view_info.push_back(info);
|
||||
}
|
||||
|
||||
// Update layout
|
||||
updateKartViewsLayout();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void SoccerSetupScreen::init()
|
||||
{
|
||||
Screen::init();
|
||||
|
||||
// TODO: remember in config.xml the last number of goals
|
||||
SpinnerWidget* goalamount = getWidget<SpinnerWidget>("goalamount");
|
||||
goalamount->setValue(3);
|
||||
|
||||
// Set focus on "continue"
|
||||
ButtonWidget* bt_continue = getWidget<ButtonWidget>("continue");
|
||||
bt_continue->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
bt_continue->setDeactivated();
|
||||
|
||||
// We need players to be able to choose their teams
|
||||
input_manager->getDeviceList()->setAssignMode(ASSIGN);
|
||||
input_manager->setMasterPlayerOnly(false);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void SoccerSetupScreen::tearDown()
|
||||
{
|
||||
Widget* central_div = getWidget<Widget>("central_div");
|
||||
|
||||
// Remove all ModelViewWidgets we created manually
|
||||
PtrVector<Widget>& children = central_div->getChildren();
|
||||
for(int i = children.size()-1 ; i >= 0 ; i--)
|
||||
{
|
||||
if(children[i].getType() == WTYPE_MODEL_VIEW)
|
||||
children.erase(i);
|
||||
}
|
||||
m_kart_view_info.clear();
|
||||
|
||||
Screen::tearDown();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction action,
|
||||
int deviceID,
|
||||
const unsigned int value,
|
||||
Input::InputType type,
|
||||
int playerId)
|
||||
{
|
||||
GUIEngine::EventPropagation result = EVENT_LET;
|
||||
SoccerTeam team_switch = SOCCER_TEAM_NONE;
|
||||
int nb_players = m_kart_view_info.size();
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case PA_MENU_LEFT:
|
||||
team_switch = SOCCER_TEAM_RED;
|
||||
break;
|
||||
case PA_MENU_RIGHT:
|
||||
team_switch = SOCCER_TEAM_BLUE;
|
||||
break;
|
||||
case PA_MENU_SELECT:
|
||||
{
|
||||
// Confirm team selection
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
if(m_kart_view_info[i].local_player_id == playerId)
|
||||
{
|
||||
m_kart_view_info[i].confirmed = true;
|
||||
m_kart_view_info[i].view->setRotateTo( KART_CONFIRMATION_TARGET_ANGLE, KART_CONFIRMATION_ROTATION_SPEED );
|
||||
result = EVENT_BLOCK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PA_MENU_CANCEL:
|
||||
{
|
||||
// Un-confirm team selection
|
||||
// TODO: shouldn't trigger quitting the screen...
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
if(m_kart_view_info[i].local_player_id == playerId)
|
||||
{
|
||||
m_kart_view_info[i].confirmed = false;
|
||||
m_kart_view_info[i].view->setRotateContinuously( KART_CONTINUOUS_ROTATION_SPEED );
|
||||
result = EVENT_BLOCK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(team_switch != SOCCER_TEAM_NONE) // A player wants to change its team?
|
||||
{
|
||||
// Find the corresponding kart view, update its team and update the layout
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
if(m_kart_view_info[i].local_player_id == playerId)
|
||||
{
|
||||
// Player has already confirmed -> can't change
|
||||
if(m_kart_view_info[i].confirmed)
|
||||
break;
|
||||
m_kart_view_info[i].team = team_switch;
|
||||
updateKartViewsLayout();
|
||||
result = EVENT_BLOCK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update "continue" button state
|
||||
ButtonWidget* bt_continue = getWidget<ButtonWidget>("continue");
|
||||
if(areAllKartsConfirmed())
|
||||
{
|
||||
bt_continue->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
bt_continue->setActivated();
|
||||
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
race_manager->setLocalKartSoccerTeam(m_kart_view_info[i].local_player_id,
|
||||
m_kart_view_info[i].team);
|
||||
}
|
||||
else
|
||||
bt_continue->setDeactivated();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SoccerSetupScreen::areAllKartsConfirmed() const
|
||||
{
|
||||
bool all_confirmed = true;
|
||||
int nb_players = m_kart_view_info.size();
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
if(!m_kart_view_info[i].confirmed)
|
||||
{
|
||||
all_confirmed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return all_confirmed;
|
||||
}
|
||||
|
||||
void SoccerSetupScreen::updateKartViewsLayout()
|
||||
{
|
||||
Widget* central_div = getWidget<Widget>("central_div");
|
||||
|
||||
// Compute/get some dimensions
|
||||
LabelWidget* label_vs = getWidget<LabelWidget>("vs");
|
||||
const int vs_width = label_vs->m_w;
|
||||
const int nb_columns = 2; // two karts maximum per column
|
||||
const int kart_area_width = (central_div->m_w - vs_width) / 2; // size of one half of the screen
|
||||
const int kart_view_size = kart_area_width/nb_columns; // Size (width and height) of a kart view
|
||||
const int center_x = central_div->m_x + central_div->m_w/2;
|
||||
const int center_y = central_div->m_y + central_div->m_h/2;
|
||||
|
||||
// Count the number of karts per team
|
||||
int nb_players = m_kart_view_info.size();
|
||||
int nb_karts_per_team[2] = {0,0};
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
nb_karts_per_team[m_kart_view_info[i].team]++;
|
||||
|
||||
// - number of rows displayed for each team = ceil(nb_karts_per_team[i] / nb_columns)
|
||||
const int nb_rows_per_team[2] = { (nb_karts_per_team[0] + nb_columns - 1) / nb_columns,
|
||||
(nb_karts_per_team[1] + nb_columns - 1) / nb_columns};
|
||||
// - where to start vertically
|
||||
const int start_y[2] = {center_y - nb_rows_per_team[0] * kart_view_size / 2,
|
||||
center_y - nb_rows_per_team[1] * kart_view_size / 2};
|
||||
// - center of each half-screen
|
||||
const int center_x_per_team[2] = { ( central_div->m_x + (center_x - vs_width) ) / 2,
|
||||
( central_div->m_x+central_div->m_w + (center_x + vs_width) ) / 2,
|
||||
};
|
||||
|
||||
// Update the layout of the 3D views for the karts
|
||||
int cur_kart_per_team[2] = {0,0}; // counters
|
||||
for(int i=0 ; i < nb_players ; i++)
|
||||
{
|
||||
const KartViewInfo& view_info = m_kart_view_info[i];
|
||||
const SoccerTeam team = view_info.team;
|
||||
|
||||
// Compute the position
|
||||
const int cur_row = cur_kart_per_team[team] / nb_columns;
|
||||
const int pos_y = start_y[team] + cur_row*kart_view_size;
|
||||
|
||||
const int cur_col = cur_kart_per_team[team] % nb_columns;
|
||||
int nb_karts_in_this_row = (nb_karts_per_team[team] - cur_row*nb_columns) % nb_columns;
|
||||
if(nb_karts_in_this_row == 0)
|
||||
nb_karts_in_this_row = nb_columns; // TODO: not sure of the computation here...
|
||||
const int pos_x = center_x_per_team[team] + cur_col*kart_view_size - nb_karts_in_this_row*kart_view_size/2;
|
||||
cur_kart_per_team[team]++;
|
||||
|
||||
// Move the view
|
||||
view_info.view->move(pos_x, pos_y, kart_view_size, kart_view_size);
|
||||
}
|
||||
}
|
||||
78
src/states_screens/soccer_setup_screen.hpp
Normal file
78
src/states_screens/soccer_setup_screen.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Lionel Fuentes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_SOCCER_SETUP_SCREEN_HPP
|
||||
#define HEADER_SOCCER_SETUP_SCREEN_HPP
|
||||
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "network/remote_kart_info.hpp"
|
||||
|
||||
namespace GUIEngine { class Widget; class LabelWidget; class ModelViewWidget; }
|
||||
|
||||
/**
|
||||
* \brief Screen with soccer setup options
|
||||
* \ingroup states_screens
|
||||
*/
|
||||
class SoccerSetupScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<SoccerSetupScreen>
|
||||
{
|
||||
friend class GUIEngine::ScreenSingleton<SoccerSetupScreen>;
|
||||
|
||||
SoccerSetupScreen();
|
||||
|
||||
struct KartViewInfo
|
||||
{
|
||||
GUIEngine::ModelViewWidget* view;
|
||||
bool confirmed;
|
||||
int local_player_id;
|
||||
SoccerTeam team;
|
||||
|
||||
KartViewInfo() : view(NULL), confirmed(false), local_player_id(-1), team(SOCCER_TEAM_NONE) {}
|
||||
};
|
||||
|
||||
AlignedArray<KartViewInfo> m_kart_view_info;
|
||||
|
||||
public:
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void loadedFromFile() OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
|
||||
const int playerID) OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void beforeAddingWidget() OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void init() OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void tearDown() OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual GUIEngine::EventPropagation filterActions( PlayerAction action,
|
||||
int deviceID,
|
||||
const unsigned int value,
|
||||
Input::InputType type,
|
||||
int playerId) OVERRIDE;
|
||||
|
||||
private:
|
||||
bool areAllKartsConfirmed() const;
|
||||
void updateKartViewsLayout();
|
||||
};
|
||||
|
||||
#endif // HEADER_SOCCER_SETUP_SCREEN_HPP
|
||||
@@ -289,7 +289,7 @@ void TracksScreen::buildTrackList()
|
||||
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG
|
||||
&& !curr->hasEasterEggs())
|
||||
continue;
|
||||
if (curr->isArena()) continue;
|
||||
if (curr->isArena() || curr->isSoccer()) continue;
|
||||
if (curr->isInternal()) continue;
|
||||
|
||||
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
|
||||
@@ -320,6 +320,7 @@ void TracksScreen::buildTrackList()
|
||||
&& !curr->hasEasterEggs())
|
||||
continue;
|
||||
if (curr->isArena()) continue;
|
||||
if (curr->isSoccer()) continue;
|
||||
if (curr->isInternal()) continue;
|
||||
|
||||
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
|
||||
|
||||
128
src/tracks/check_goal.cpp
Normal file
128
src/tracks/check_goal.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "tracks/check_goal.hpp"
|
||||
|
||||
#include "io/xml_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
/** Constructor for a check goal line.
|
||||
* \param node XML node containing the parameters for this goal line.
|
||||
* \param index Index of this check structure in the check manager.
|
||||
*/
|
||||
CheckGoal::CheckGoal(const XMLNode &node, unsigned int index)
|
||||
: CheckStructure(node, index)
|
||||
{
|
||||
// Determine the team for this goal
|
||||
m_first_goal = false;
|
||||
node.get("first_goal", &m_first_goal);
|
||||
|
||||
Vec3 p1, p2;
|
||||
node.get("p1", &p1);
|
||||
node.get("p2", &p2);
|
||||
|
||||
m_line.setLine( core::vector2df(p1.getX(), p1.getZ()),
|
||||
core::vector2df(p2.getX(), p2.getZ()) );
|
||||
} // CheckGoal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* Checks the soccer balls to see if they crossed the line and trigger the goal accordingly.
|
||||
*/
|
||||
void CheckGoal::update(float dt)
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
assert(world);
|
||||
|
||||
Track* track = world->getTrack();
|
||||
assert(track);
|
||||
|
||||
TrackObjectManager* tom = track->getTrackObjectManager();
|
||||
assert(tom);
|
||||
|
||||
PtrVector<TrackObject>& objects = tom->getObjects();
|
||||
int ball_index = 0;
|
||||
for(int i=0; i<objects.size(); i++)
|
||||
{
|
||||
TrackObject* obj = objects.get(i);
|
||||
if(!obj->isSoccerBall())
|
||||
continue;
|
||||
|
||||
const Vec3 &xyz = obj->getNode()->getPosition();
|
||||
if(isTriggered(m_previous_position[ball_index], xyz, ball_index))
|
||||
{
|
||||
if(UserConfigParams::m_check_debug)
|
||||
printf("CHECK: Goal check structure %d triggered for object %s.\n",
|
||||
m_index, obj->getDebugName());
|
||||
trigger(ball_index);
|
||||
}
|
||||
m_previous_position[ball_index] = xyz;
|
||||
ball_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called when the check line is triggered. This function creates a cannon
|
||||
* animation object and attaches it to the kart.
|
||||
* \param kart_index The index of the kart that triggered the check line.
|
||||
*/
|
||||
void CheckGoal::trigger(unsigned int kart_index)
|
||||
{
|
||||
SoccerWorld* world = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
if(!world)
|
||||
{
|
||||
fprintf(stderr, "WARNING: no soccer world found, cannot count the points\n");
|
||||
return;
|
||||
}
|
||||
|
||||
world->onCheckGoalTriggered(m_first_goal);
|
||||
} // CheckGoal
|
||||
|
||||
bool CheckGoal::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx)
|
||||
{
|
||||
core::vector2df cross_point;
|
||||
|
||||
// Check if the finite line was actually crossed:
|
||||
return m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
|
||||
new_pos.toIrrVector2d()),
|
||||
cross_point);
|
||||
|
||||
} // isTriggered
|
||||
|
||||
void CheckGoal::reset(const Track &track)
|
||||
{
|
||||
const TrackObjectManager* tom = track.getTrackObjectManager();
|
||||
assert(tom);
|
||||
|
||||
m_previous_position.clear();
|
||||
|
||||
const PtrVector<TrackObject>& objects = tom->getObjects();
|
||||
for(int i=0; i<objects.size(); i++)
|
||||
{
|
||||
const TrackObject* obj = objects.get(i);
|
||||
if(!obj->isSoccerBall())
|
||||
continue;
|
||||
|
||||
const Vec3 &xyz = obj->getNode()->getPosition();
|
||||
|
||||
m_previous_position.push_back(xyz);
|
||||
}
|
||||
} // reset
|
||||
55
src/tracks/check_goal.hpp
Normal file
55
src/tracks/check_goal.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2012 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_CHECK_GOAL_HPP
|
||||
#define HEADER_CHECK_GOAL_HPP
|
||||
|
||||
#include "tracks/check_structure.hpp"
|
||||
#include "utils/cpp2011.h"
|
||||
#include <line2d.h>
|
||||
using namespace irr;
|
||||
|
||||
class CheckManager;
|
||||
class XMLNode;
|
||||
class Track;
|
||||
|
||||
/**
|
||||
* \brief Implements a simple checkline that will score a point when the
|
||||
* soccer ball crosses it.
|
||||
*
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class CheckGoal : public CheckStructure
|
||||
{
|
||||
private:
|
||||
/** Which team is this goal for? */
|
||||
bool m_first_goal;
|
||||
|
||||
/** The line that is tested for being crossed. */
|
||||
core::line2df m_line;
|
||||
|
||||
public:
|
||||
CheckGoal(const XMLNode &node, unsigned int index);
|
||||
virtual ~CheckGoal() {}
|
||||
virtual void update(float dt) OVERRIDE;
|
||||
virtual void trigger(unsigned int kart_index);
|
||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx) OVERRIDE;
|
||||
virtual void reset(const Track &track) OVERRIDE;
|
||||
}; // CheckLine
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "io/xml_node.hpp"
|
||||
#include "tracks/ambient_light_sphere.hpp"
|
||||
#include "tracks/check_cannon.hpp"
|
||||
#include "tracks/check_goal.hpp"
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_line.hpp"
|
||||
#include "tracks/check_structure.hpp"
|
||||
@@ -48,10 +49,14 @@ void CheckManager::load(const XMLNode &node)
|
||||
{
|
||||
m_all_checks.push_back(new CheckLap(*check_node, i));
|
||||
}
|
||||
else if(type=="cannon")
|
||||
{
|
||||
m_all_checks.push_back(new CheckCannon(*check_node, i));
|
||||
}
|
||||
else if(type=="cannon")
|
||||
{
|
||||
m_all_checks.push_back(new CheckCannon(*check_node, i));
|
||||
}
|
||||
else if(type=="goal")
|
||||
{
|
||||
m_all_checks.push_back(new CheckGoal(*check_node, i));
|
||||
}
|
||||
else if(type=="check-sphere")
|
||||
{
|
||||
AmbientLightSphere *cs = new AmbientLightSphere(*check_node,
|
||||
|
||||
@@ -65,8 +65,8 @@ CheckStructure::CheckStructure(const XMLNode &node, unsigned int index)
|
||||
== m_same_group.end())
|
||||
m_same_group.push_back(m_index);
|
||||
|
||||
// As a default, only lap lines and cannons are activated
|
||||
m_active_at_reset= m_check_type==CT_NEW_LAP || m_check_type==CT_CANNON;
|
||||
// As a default, only lap lines, cannons and goals are activated
|
||||
m_active_at_reset= m_check_type==CT_NEW_LAP || m_check_type==CT_CANNON || m_check_type==CT_GOAL;
|
||||
node.get("active", &m_active_at_reset);
|
||||
} // CheckStructure
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ class CheckManager;
|
||||
* CT_TOGGLE: Toggles the specified other check structures (active to
|
||||
* inactive and vice versa.
|
||||
* CT_CANNON: A check line that 'shoots' the kart to a specified location.
|
||||
* CT_GOAL: A goal line in soccer mode.
|
||||
* Each check structure can be active or inactive. Only lap counters are
|
||||
* initialised to be active, all other check structures are inactive.
|
||||
*
|
||||
@@ -54,7 +55,8 @@ public:
|
||||
* the state that check structure is in)
|
||||
* TOGGLE: Switches (inverts) the state of another check structure.
|
||||
* NEW_LAP: On crossing a new lap is counted.
|
||||
* CANNON: Causes the kart to be shot to a specified point.
|
||||
* CANNON: Causes the kart to be shot to a specified point.
|
||||
* GOAL: Causes a point to be scored when a soccer ball crosses its line
|
||||
* AMBIENT_SPHERE: Modifies the ambient color.
|
||||
* A combination of an activate and new_lap line are used to
|
||||
* avoid shortcuts: a new_lap line is deactivated after crossing it, and
|
||||
@@ -62,7 +64,7 @@ public:
|
||||
* enabling you to count the lap again.
|
||||
*/
|
||||
enum CheckType {CT_NEW_LAP, CT_ACTIVATE, CT_TOGGLE, CT_CANNON,
|
||||
CT_AMBIENT_SPHERE};
|
||||
CT_GOAL, CT_AMBIENT_SPHERE};
|
||||
|
||||
protected:
|
||||
/** Stores the previous position of all karts. This is needed to detect
|
||||
@@ -75,13 +77,13 @@ protected:
|
||||
/** True if this check structure should be activated at a reset. */
|
||||
bool m_active_at_reset;
|
||||
|
||||
private:
|
||||
/** The type of this checkline. */
|
||||
CheckType m_check_type;
|
||||
|
||||
/** Stores the index of this check structure. This is only used for
|
||||
* debugging (use --check-debug option). */
|
||||
unsigned int m_index;
|
||||
|
||||
private:
|
||||
/** The type of this checkline. */
|
||||
CheckType m_check_type;
|
||||
|
||||
/** Contains the indices of the corresponding check structures that
|
||||
* get their state changed (activated or switched). */
|
||||
|
||||
@@ -99,6 +99,7 @@ Track::Track(const std::string &filename)
|
||||
m_reverse_available = false;
|
||||
m_is_arena = false;
|
||||
m_has_easter_eggs = false;
|
||||
m_is_soccer = false;
|
||||
m_is_cutscene = false;
|
||||
m_camera_far = 1000.0f;
|
||||
m_mini_map = NULL;
|
||||
@@ -328,6 +329,7 @@ void Track::loadTrackInfo()
|
||||
getMusicInformation(filenames, m_music);
|
||||
root->get("screenshot", &m_screenshot);
|
||||
root->get("gravity", &m_gravity);
|
||||
root->get("soccer", &m_is_soccer);
|
||||
root->get("arena", &m_is_arena);
|
||||
root->get("cutscene", &m_is_cutscene);
|
||||
root->get("groups", &m_groups);
|
||||
@@ -335,13 +337,14 @@ void Track::loadTrackInfo()
|
||||
root->get("reverse", &m_reverse_available);
|
||||
root->get("push-back", &m_enable_push_back);
|
||||
|
||||
// Make the default for auto-rescue in battle mode to be false
|
||||
if(m_is_arena)
|
||||
// Make the default for auto-rescue in battle mode and soccer mode to be false
|
||||
if(m_is_arena || m_is_soccer)
|
||||
m_enable_auto_rescue = false;
|
||||
root->get("auto-rescue", & m_enable_auto_rescue);
|
||||
root->get("smooth-normals", &m_smooth_normals);
|
||||
// Reverse is meaningless in arena
|
||||
m_reverse_available = !m_is_arena && m_reverse_available;
|
||||
if(m_is_arena || m_is_soccer)
|
||||
m_reverse_available = false;
|
||||
|
||||
|
||||
for(unsigned int i=0; i<root->getNumNodes(); i++)
|
||||
@@ -1345,7 +1348,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// the race gui was created. The race gui is needed since it stores
|
||||
// the information about the size of the texture to render the mini
|
||||
// map to.
|
||||
if (!m_is_arena && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
||||
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
||||
|
||||
ItemManager::create();
|
||||
|
||||
@@ -1364,7 +1367,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
default_start->get("upwards-distance", &upwards_distance );
|
||||
default_start->get("karts-per-row", &karts_per_row );
|
||||
}
|
||||
if(!m_is_arena && !m_is_cutscene)
|
||||
if(!m_is_arena && !m_is_soccer && !m_is_cutscene)
|
||||
{
|
||||
m_start_transforms.resize(race_manager->getNumberOfKarts());
|
||||
QuadGraph::get()->setDefaultStartPositions(&m_start_transforms,
|
||||
|
||||
@@ -227,9 +227,10 @@ private:
|
||||
Vec3 m_aabb_max;
|
||||
/** True if this track is an arena. */
|
||||
bool m_is_arena;
|
||||
|
||||
/** True if this track has easter eggs. */
|
||||
bool m_has_easter_eggs;
|
||||
/** True if this track is a soccer arena. */
|
||||
bool m_is_soccer;
|
||||
|
||||
bool m_is_cutscene;
|
||||
|
||||
@@ -413,6 +414,11 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this track has easter eggs. */
|
||||
bool hasEasterEggs() const { return m_has_easter_eggs; }
|
||||
bool isSoccer () const { return m_is_soccer; }
|
||||
// ------------------------------------------------------------------------
|
||||
void loadTrackModel (World* parent,
|
||||
bool reverse_track = false,
|
||||
unsigned int mode_id=0);
|
||||
// ------------------------------------------------------------------------
|
||||
void addMusic (MusicInformation* mi)
|
||||
{m_music.push_back(mi); }
|
||||
@@ -533,7 +539,7 @@ public:
|
||||
/** Returns true if the normals of this track can be smoothed. */
|
||||
bool smoothNormals() const { return m_smooth_normals; }
|
||||
// ------------------------------------------------------------------------
|
||||
TrackObjectManager* getTrackObjectManager() {return m_track_object_manager;}
|
||||
TrackObjectManager* getTrackObjectManager() const {return m_track_object_manager;}
|
||||
|
||||
/** Get list of challenges placed on that world. Works only for overworld. */
|
||||
const std::vector<OverworldChallenge>& getChallengeList() const
|
||||
|
||||
@@ -128,7 +128,9 @@ void TrackManager::loadTrackList()
|
||||
m_track_group_names.clear();
|
||||
m_track_groups.clear();
|
||||
m_arena_group_names.clear();
|
||||
m_soccer_arena_group_names.clear();
|
||||
m_arena_groups.clear();
|
||||
m_soccer_arena_groups.clear();
|
||||
m_track_avail.clear();
|
||||
m_tracks.clear();
|
||||
|
||||
@@ -223,11 +225,16 @@ void TrackManager::removeTrack(const std::string &ident)
|
||||
int index = it - m_tracks.begin();
|
||||
|
||||
// Remove the track from all groups it belongs to
|
||||
Group2Indices &group_2_indices = track->isArena() ? m_arena_groups
|
||||
: m_track_groups;
|
||||
std::vector<std::string> &group_names = track->isArena()
|
||||
? m_arena_group_names
|
||||
: m_track_group_names;
|
||||
Group2Indices &group_2_indices =
|
||||
(track->isArena() ? m_arena_groups :
|
||||
(track->isSoccer() ? m_soccer_arena_groups :
|
||||
m_track_groups));
|
||||
|
||||
std::vector<std::string> &group_names =
|
||||
(track->isArena() ? m_arena_group_names :
|
||||
(track->isSoccer() ? m_soccer_arena_group_names :
|
||||
m_track_group_names));
|
||||
|
||||
const std::vector<std::string>& groups=track->getGroups();
|
||||
for(unsigned int i=0; i<groups.size(); i++)
|
||||
{
|
||||
@@ -253,9 +260,11 @@ void TrackManager::removeTrack(const std::string &ident)
|
||||
// Adjust all indices of tracks with an index number higher than
|
||||
// the removed track, since they have been moved down. This must
|
||||
// be done for all tracks and all arenas
|
||||
for(unsigned int i=0; i<2; i++) // i=0: arenas, i=1: tracks
|
||||
for(unsigned int i=0; i<2; i++) // i=0: soccer arenas, i=0: arenas, i=1: tracks
|
||||
{
|
||||
Group2Indices &g2i = i==0 ? m_arena_groups : m_track_groups;
|
||||
Group2Indices &g2i = (i==0 ? m_soccer_arena_groups :
|
||||
(i==1 ? m_arena_groups :
|
||||
m_track_groups));
|
||||
Group2Indices::iterator j;
|
||||
for(j=g2i.begin(); j!=g2i.end(); j++)
|
||||
{
|
||||
@@ -280,11 +289,15 @@ void TrackManager::updateGroups(const Track* track)
|
||||
|
||||
const std::vector<std::string>& new_groups = track->getGroups();
|
||||
|
||||
Group2Indices &group_2_indices = track->isArena() ? m_arena_groups
|
||||
: m_track_groups;
|
||||
std::vector<std::string> &group_names = track->isArena()
|
||||
? m_arena_group_names
|
||||
: m_track_group_names;
|
||||
Group2Indices &group_2_indices =
|
||||
(track->isArena() ? m_arena_groups :
|
||||
(track->isSoccer() ? m_soccer_arena_groups :
|
||||
m_track_groups));
|
||||
|
||||
std::vector<std::string> &group_names =
|
||||
(track->isArena() ? m_arena_group_names :
|
||||
(track->isSoccer() ? m_soccer_arena_group_names :
|
||||
m_track_group_names));
|
||||
|
||||
const unsigned int groups_amount = new_groups.size();
|
||||
for(unsigned int i=0; i<groups_amount; i++)
|
||||
|
||||
@@ -50,6 +50,9 @@ private:
|
||||
/** List of all arena groups. */
|
||||
Group2Indices m_arena_groups;
|
||||
|
||||
/** List of all soccer arena groups. */
|
||||
Group2Indices m_soccer_arena_groups;
|
||||
|
||||
/** List of all groups (for both normal tracks and arenas) */
|
||||
//std::vector<std::string> m_all_group_names;
|
||||
|
||||
@@ -58,6 +61,9 @@ private:
|
||||
|
||||
/** List of the names of all groups containing arenas */
|
||||
std::vector<std::string> m_arena_group_names;
|
||||
|
||||
/** List of the names of all groups containing soccer arenas */
|
||||
std::vector<std::string> m_soccer_arena_group_names;
|
||||
|
||||
/** Flag if this track is available or not. Tracks are set unavailable
|
||||
* if they are not available on all clients (applies only to network mode)
|
||||
@@ -99,11 +105,12 @@ public:
|
||||
} // getAllTrackGroups
|
||||
// ------------------------------------------------------------------------
|
||||
/** \brief Returns a list of the names of all used arena groups. */
|
||||
const std::vector<std::string>& getAllArenaGroups() const
|
||||
const std::vector<std::string>&
|
||||
getAllArenaGroups(bool soccer_arena=false) const
|
||||
{
|
||||
return m_arena_group_names;
|
||||
} // getAllArenaGRoups
|
||||
// ------------------------------------------------------------------------
|
||||
return soccer_arena ? m_soccer_arena_group_names : m_arena_group_names;
|
||||
} // getAllArenaGroups
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of tracks. */
|
||||
size_t getNumberOfTracks() const { return m_tracks.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -124,11 +131,12 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a list of all arenas in a given group.
|
||||
* \param g Name of the group. */
|
||||
const std::vector<int>& getArenasInGroup(const std::string& g)
|
||||
const std::vector<int>&
|
||||
getArenasInGroup(const std::string& g, bool soccer_arena=false)
|
||||
{
|
||||
return m_arena_groups[g];
|
||||
// getArenasInGroup}
|
||||
}
|
||||
return soccer_arena ? m_soccer_arena_groups[g] : m_arena_groups[g];
|
||||
} // getArenasInGroup
|
||||
|
||||
}; // TrackManager
|
||||
|
||||
extern TrackManager* track_manager;
|
||||
|
||||
@@ -75,6 +75,9 @@ TrackObject::TrackObject(const XMLNode &xml_node)
|
||||
xml_node.get("interaction", &m_interaction);
|
||||
xml_node.get("lod_group", &m_lod_group);
|
||||
|
||||
m_soccer_ball = false;
|
||||
xml_node.get("soccer_ball", &m_soccer_ball);
|
||||
|
||||
std::string type;
|
||||
xml_node.get("type", &type );
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ protected:
|
||||
|
||||
LODNode* m_lod_emitter_node;
|
||||
|
||||
bool m_soccer_ball;
|
||||
|
||||
public:
|
||||
TrackObject(const XMLNode &xml_node);
|
||||
TrackObject();
|
||||
@@ -133,11 +135,12 @@ public:
|
||||
}
|
||||
|
||||
m_node = node;
|
||||
if (node->getType() == irr::scene::ESNT_LOD_NODE)
|
||||
|
||||
if (m_node->getType() == irr::scene::ESNT_LOD_NODE)
|
||||
{
|
||||
((LODNode*)node)->setNodesPosition(m_init_xyz);
|
||||
((LODNode*)node)->setNodesRotation(m_init_hpr);
|
||||
((LODNode*)node)->setNodesScale(m_init_scale);
|
||||
((LODNode*)m_node)->setNodesPosition(m_init_xyz);
|
||||
((LODNode*)m_node)->setNodesRotation(m_init_hpr);
|
||||
((LODNode*)m_node)->setNodesScale(m_init_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -151,6 +154,8 @@ public:
|
||||
|
||||
const std::string& getType() const { return m_type; }
|
||||
|
||||
bool isSoccerBall() const { return m_soccer_ball; }
|
||||
|
||||
/** Currently used for sound effects only, in cutscenes only atm */
|
||||
const std::string& getTriggerCondition() const { return m_trigger_condition; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user