diff --git a/data/gui/materials.xml b/data/gui/materials.xml
index 16927e83e..8b9a7fb69 100644
--- a/data/gui/materials.xml
+++ b/data/gui/materials.xml
@@ -4,5 +4,7 @@
+
+
\ No newline at end of file
diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp
index 04bdc7aa6..8bb0b230b 100644
--- a/src/graphics/irr_driver.cpp
+++ b/src/graphics/irr_driver.cpp
@@ -850,12 +850,14 @@ PerCameraNode *IrrDriver::addPerCameraMesh(scene::IMesh* mesh,
*/
scene::ISceneNode *IrrDriver::addBillboard(const core::dimension2d< f32 > size,
video::ITexture *texture,
- scene::ISceneNode* parent)
+ scene::ISceneNode* parent, bool alphaTesting)
{
scene::IBillboardSceneNode* node =
m_scene_manager->addBillboardSceneNode(parent, size);
assert(node->getMaterialCount() > 0);
node->setMaterialTexture(0, texture);
+ if(alphaTesting)
+ node->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
return node;
} // addMesh
diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp
index a7d6b3082..125fa9f60 100644
--- a/src/graphics/irr_driver.hpp
+++ b/src/graphics/irr_driver.hpp
@@ -159,7 +159,7 @@ public:
scene::ISceneNode *parent = NULL);
scene::ISceneNode *addBillboard(const core::dimension2d< f32 > size,
video::ITexture *texture,
- scene::ISceneNode* parent=NULL);
+ scene::ISceneNode* parent=NULL, bool alphaTesting = false);
scene::IParticleSystemSceneNode
*addParticleNode(bool default_emitter=true);
diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp
index 814f64ede..730dbb549 100644
--- a/src/karts/kart_model.cpp
+++ b/src/karts/kart_model.cpp
@@ -278,39 +278,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models)
lod_node->add(500, static_model, true);
m_animated_node = static_cast(node);
- m_hat_node = NULL;
- if(m_hat_name.size()>0)
- {
- scene::IBoneSceneNode *bone = m_animated_node->getJointNode("Head");
- if(!bone)
- bone = m_animated_node->getJointNode("head");
- if(bone)
- {
-
- // Till we have all models fixed, accept Head and head as bone naartme
- scene::IMesh *hat_mesh =
- irr_driver->getAnimatedMesh(
- file_manager->getModelFile(m_hat_name));
- m_hat_node = irr_driver->addMesh(hat_mesh);
- bone->addChild(m_hat_node);
- m_animated_node->setCurrentFrame((float)m_animation_frame[AF_STRAIGHT]);
- m_animated_node->OnAnimate(0);
- bone->updateAbsolutePosition();
-
- // With the hat node attached to the head bone, we have to
- // reverse the transformation of the bone, so that the hat
- // is still properly placed. Esp. the hat offset needs
- // to be rotated.
- const core::matrix4 mat = bone->getAbsoluteTransformation();
- core::matrix4 inv;
- mat.getInverse(inv);
- core::vector3df rotated_offset;
- inv.rotateVect(rotated_offset, m_hat_offset);
- m_hat_node->setPosition(rotated_offset);
- m_hat_node->setScale(inv.getScale());
- m_hat_node->setRotation(inv.getRotationDegrees());
- } // if bone
- } // if(m_hat_name)
+ attachHat();
#ifdef DEBUG
std::string debug_name = m_model_filename+" (animated-kart-model)";
@@ -704,4 +672,40 @@ void KartModel::update(float rotation_dt, float steer, const float suspension[4]
m_animated_node->setCurrentFrame(frame);
} // update
+//-----------------------------------------------------------------------------
+void KartModel::attachHat(){
+ m_hat_node = NULL;
+ if(m_hat_name.size()>0)
+ {
+ scene::IBoneSceneNode *bone = m_animated_node->getJointNode("Head");
+ if(!bone)
+ bone = m_animated_node->getJointNode("head");
+ if(bone)
+ {
+
+ // Till we have all models fixed, accept Head and head as bone naartme
+ scene::IMesh *hat_mesh =
+ irr_driver->getAnimatedMesh(
+ file_manager->getModelFile(m_hat_name));
+ m_hat_node = irr_driver->addMesh(hat_mesh);
+ bone->addChild(m_hat_node);
+ m_animated_node->setCurrentFrame((float)m_animation_frame[AF_STRAIGHT]);
+ m_animated_node->OnAnimate(0);
+ bone->updateAbsolutePosition();
+
+ // With the hat node attached to the head bone, we have to
+ // reverse the transformation of the bone, so that the hat
+ // is still properly placed. Esp. the hat offset needs
+ // to be rotated.
+ const core::matrix4 mat = bone->getAbsoluteTransformation();
+ core::matrix4 inv;
+ mat.getInverse(inv);
+ core::vector3df rotated_offset;
+ inv.rotateVect(rotated_offset, m_hat_offset);
+ m_hat_node->setPosition(rotated_offset);
+ m_hat_node->setScale(inv.getScale());
+ m_hat_node->setRotation(inv.getRotationDegrees());
+ } // if bone
+ } // if(m_hat_name)
+}
diff --git a/src/karts/kart_model.hpp b/src/karts/kart_model.hpp
index 326f7bcca..9fdb3eea9 100644
--- a/src/karts/kart_model.hpp
+++ b/src/karts/kart_model.hpp
@@ -231,9 +231,15 @@ public:
// ------------------------------------------------------------------------
/** Name of the hat mesh to use. */
void setHatMeshName(const std::string &name) {m_hat_name = name; }
+ // ------------------------------------------------------------------------
+ void attachHat();
// ------------------------------------------------------------------------
/** Returns the array of wheel nodes. */
scene::ISceneNode** getWheelNodes() { return m_wheel_node; }
+ // ------------------------------------------------------------------------
+ scene::IAnimatedMeshSceneNode* getAnimatedNode(){ return m_animated_node; }
+ // ------------------------------------------------------------------------
+ core::vector3df getHatOffset() { return m_hat_offset; }
}; // KartModel
#endif
diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp
index 0d05351e6..621ce2acb 100644
--- a/src/modes/soccer_world.cpp
+++ b/src/modes/soccer_world.cpp
@@ -1,242 +1,411 @@
-// 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
-#include
-
-#include "audio/music_manager.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;
-
- // 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);
- }
-} // init
-
-//-----------------------------------------------------------------------------
-/** Called then a battle is restarted.
- */
-void SoccerWorld::reset()
-{
- WorldWithRank::reset();
-
- m_can_score_points = true;
- memset(m_team_goals, 0, sizeof(m_team_goals));
-
- initKartList();
-} // reset
-
-//-----------------------------------------------------------------------------
-/** 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& objects = tom->getObjects();
- for(int i=0; iisSoccerBall())
- 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
-} // onCheckGoalTriggered
-
-//-----------------------------------------------------------------------------
-/** 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
-
-//-----------------------------------------------------------------------------
-/** Returns the data to display in the race gui.
- */
-void SoccerWorld::getKartsDisplayInfo(
- std::vector *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
-
-// ----------------------------------------------------------------------------
-/** 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; nsetPosition(-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; ngetSoccerTeam() == 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; ngetSoccerTeam();
- m_karts[n]->setPosition(team_cur_position[team]);
- team_cur_position[team]++;
- }// next kart
-*/
-}
+// 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
+#include
+
+#include "audio/music_manager.hpp"
+#include "io/file_manager.hpp"
+#include "karts/abstract_kart.hpp"
+#include "karts/kart.hpp"
+#include "karts/kart_model.hpp"
+#include "karts/kart_properties.hpp"
+#include "karts/rescue_animation.hpp"
+#include "karts/controller/player_controller.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;
+
+ // 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);
+ }
+ m_goal_target = race_manager->getMaxGoal();
+ printf("Max Goal: %d\n", m_goal_target);
+} // init
+
+//-----------------------------------------------------------------------------
+/** Called then a battle is restarted.
+ */
+void SoccerWorld::reset()
+{
+ WorldWithRank::reset();
+
+ m_can_score_points = true;
+ memset(m_team_goals, 0, sizeof(m_team_goals));
+
+ initKartList();
+} // reset
+
+//-----------------------------------------------------------------------------
+/** 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_team_goals[first_goal]++;
+ printf("Score:\nTeam One %d : %d Team Two\n", m_team_goals[0], m_team_goals[1]);
+ }
+
+ //m_check_goals_enabled = false; // TODO: remove?
+
+ // Reset original positions for the soccer balls
+ TrackObjectManager* tom = getTrack()->getTrackObjectManager();
+ assert(tom);
+
+ PtrVector& objects = tom->getObjects();
+ for(int i=0; iisSoccerBall())
+ continue;
+
+ obj->reset();
+ obj->getPhysics()->reset();
+ }
+
+ //Resetting the ball triggers the goal check line one more time.
+ //This ensures that only one goal is counted, and the second is ignored.
+ m_can_score_points = !m_can_score_points;
+
+ //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
+} // onCheckGoalTriggered
+
+//-----------------------------------------------------------------------------
+/** 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;
+ }
+ // One team scored the target goals ...
+ else if(getScore(0) >= m_goal_target ||
+ getScore(1) >= m_goal_target){
+ return true;
+ }
+ // 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
+
+//-----------------------------------------------------------------------------
+/** Returns the data to display in the race gui.
+ */
+void SoccerWorld::getKartsDisplayInfo(
+ std::vector *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; ngetTrack()->getStartTransform(n);
+ const Vec3 &v=s.getOrigin();
+ float accumulatedDistance = .0f;
+ bool spawnPointClear = true;
+
+ for(unsigned int k=0; kgetKart(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_track->findGround(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; nsetPosition(-1);
+ }
+ // TODO: remove
+
+ 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; ngetLocalKartInfo(n).getSoccerTeam() == SOCCER_TEAM_NONE)
+ race_manager->setLocalKartSoccerTeam(
+ race_manager->getLocalKartInfo(n).getLocalPlayerId(),round_robin_team);
+
+ team_karts_amount[race_manager->getLocalKartInfo(n).getSoccerTeam()]++;
+
+ round_robin_team = (round_robin_team==SOCCER_TEAM_RED ?
+ SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
+ }// next kart
+ }
+
+ //Loading the indicator textures
+ irr::video::ITexture *redTeamTexture = irr_driver->getTexture(
+ file_manager->getTextureFile("soccer_player_red.png"));
+ irr::video::ITexture *blueTeamTexture = irr_driver->getTexture(
+ file_manager->getTextureFile("soccer_player_blue.png"));
+ //Assigning indicators
+ for(int i=0; igetLocalKartInfo(i).getSoccerTeam() == SOCCER_TEAM_RED)
+ hatNode = irr_driver->addBillboard(core::dimension2d(0.3,0.3)
+ ,redTeamTexture,m_karts[i]->getNode(), true);
+ else
+ hatNode = irr_driver->addBillboard(core::dimension2d(0.3,0.3)
+ ,blueTeamTexture,m_karts[i]->getNode(),true);
+ hatNode->setPosition(m_karts[i]->getKartModel()->getHatOffset());
+ }
+
+ // 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; ngetLocalKartInfo(n).getSoccerTeam();
+ m_karts[n]->setPosition(team_cur_position[team]);
+ team_cur_position[team]++;
+ }// next kart
+}
+//-----------------------------------------------------------------------------
+int SoccerWorld::getScore(unsigned int i){
+ return m_team_goals[i];
+}
+//-----------------------------------------------------------------------------
+int SoccerWorld::getTeamLeader(unsigned int team){
+ for(int i = 0; i< m_karts.size(); i++){
+ if(race_manager->getLocalKartInfo(i).getSoccerTeam() == (SoccerTeam) team)
+ return i;
+ }
+ return -1;
+ }
+//-----------------------------------------------------------------------------
+AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
+ int local_player_id, int global_player_id,
+ RaceManager::KartType kart_type)
+{
+ int posIndex = index;
+ if(race_manager->getLocalKartInfo(index).getSoccerTeam() == SOCCER_TEAM_RED){
+ if(index % 2 != 0) posIndex += 1;
+ }
+ else if(race_manager->getLocalKartInfo(index).getSoccerTeam() == SOCCER_TEAM_BLUE){
+ if(index % 2 != 1) posIndex += 1;
+ }
+ int position = index+1;
+ btTransform init_pos = m_track->getStartTransform(posIndex);
+ AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos);
+ new_kart->init(race_manager->getKartType(index));
+ Controller *controller = NULL;
+ switch(kart_type)
+ {
+ case RaceManager::KT_PLAYER:
+ controller = new PlayerController(new_kart,
+ StateManager::get()->getActivePlayer(local_player_id),
+ local_player_id);
+ m_num_players ++;
+ break;
+ case RaceManager::KT_NETWORK_PLAYER:
+ break; // Avoid compiler warning about enum not handled.
+ //controller = new NetworkController(kart_ident, position, init_pos,
+ // global_player_id);
+ //m_num_players++;
+ //break;
+ case RaceManager::KT_AI:
+ controller = loadAIController(new_kart);
+ break;
+ case RaceManager::KT_GHOST:
+ break;
+ case RaceManager::KT_LEADER:
+ break;
+ }
+
+ new_kart->setController(controller);
+
+ return new_kart;
+} // createKart
\ No newline at end of file
diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp
index 591c0659a..ff09af2a2 100644
--- a/src/modes/soccer_world.hpp
+++ b/src/modes/soccer_world.hpp
@@ -1,79 +1,94 @@
-//
-// 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
-
-#include
-
-#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 reset();
-
- virtual bool useFastMusicNearEnd() const { return false; }
- virtual void getKartsDisplayInfo(
- std::vector *info);
- virtual bool raceHasLaps(){ return false; }
-
- virtual const std::string& getIdent() const;
-
- virtual void update(float dt);
-
- void onCheckGoalTriggered(bool first_goal);
-
-private:
- void initKartList();
-}; // SoccerWorld
-
-
-#endif
+//
+// 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
+
+#include
+
+#define CLEAR_SPAWN_RANGE 5
+
+class PhysicalObject;
+class AbstractKart;
+class Controller;
+
+/**
+ * \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];
+ /** Number of goals needed to win
+ */
+ int m_goal_target;
+ /** 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;
+
+ /** Team karts */
+
+
+public:
+
+ SoccerWorld();
+ virtual ~SoccerWorld() {}
+
+ virtual void init();
+
+ // clock events
+ virtual bool isRaceOver();
+ virtual void terminateRace();
+
+ // overriding World methods
+ virtual void reset();
+
+ virtual bool useFastMusicNearEnd() const { return false; }
+ virtual void getKartsDisplayInfo(
+ std::vector *info);
+ int getScore(unsigned int i);
+ 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);
+ int getTeamLeader(unsigned int i);
+
+private:
+ void initKartList();
+protected:
+ virtual AbstractKart *createKart(const std::string &kart_ident, int index,
+ int local_player_id, int global_player_id,
+ RaceManager::KartType type);
+}; // SoccerWorld
+
+
+#endif
diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp
index 6f3207bd9..887ca1028 100644
--- a/src/modes/world_with_rank.hpp
+++ b/src/modes/world_with_rank.hpp
@@ -76,6 +76,7 @@ public:
virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE;
+
}; // WorldWithRank
#endif
diff --git a/src/network/remote_kart_info.hpp b/src/network/remote_kart_info.hpp
index 507458d08..cde5cda72 100644
--- a/src/network/remote_kart_info.hpp
+++ b/src/network/remote_kart_info.hpp
@@ -55,7 +55,7 @@ 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; }
+ const void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
int getHostId() const { return m_host_id; }
int getLocalPlayerId() const { return m_local_player_id; }
diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp
index 82028b227..57be3b6e4 100644
--- a/src/race/race_manager.hpp
+++ b/src/race/race_manager.hpp
@@ -331,6 +331,7 @@ private:
int m_coin_target;
bool m_has_time_target;
float m_time_target;
+ int m_goal_target;
void startNextRace(); // start a next race
@@ -390,6 +391,10 @@ public:
bool hasTimeTarget() const { return m_has_time_target; }
+ void setMaxGoal(int maxGoal){ m_goal_target = maxGoal; }
+
+ int getMaxGoal(){ return m_goal_target; }
+
/** Sort karts and update the m_gp_rank KartStatus member, in preparation
* for future calls to RaceManager::getKartGPRank or
* RaceManager::getKartWithGPRank
diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp
index d3cc53344..f8f89e93b 100644
--- a/src/states_screens/race_gui.cpp
+++ b/src/states_screens/race_gui.cpp
@@ -44,6 +44,7 @@ using namespace irr;
#include "modes/follow_the_leader.hpp"
#include "modes/linear_world.hpp"
#include "modes/world.hpp"
+#include "modes/soccer_world.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@@ -191,6 +192,8 @@ void RaceGUI::renderGlobal(float dt)
{
drawGlobalPlayerIcons(m_map_height);
}
+
+ if(world->getTrack()->isSoccer()) drawScores();
} // renderGlobal
//-----------------------------------------------------------------------------
@@ -226,6 +229,63 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt)
RaceGUIBase::renderPlayerView(camera, dt);
} // renderPlayerView
+//-----------------------------------------------------------------------------
+void RaceGUI::drawScores()
+{
+ SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
+ int offsetY = 5;
+ int offsetX = 5;
+ gui::ScalableFont* font = GUIEngine::getFont();
+ static video::SColor color = video::SColor(255,255,255,255);
+
+ //Draw kart icons above score(denoting teams)
+ irr::video::ITexture *red_team = irr_driver->getTexture(
+ file_manager->getTextureFile("soccer_ball_red.png"));
+ irr::video::ITexture *blue_team = irr_driver->getTexture(
+ file_manager->getTextureFile("soccer_ball_blue.png"));
+
+ core::rect indicatorPos(offsetX-6, offsetY,
+ offsetX -6 + red_team->getSize().Width/8,
+ offsetY + red_team->getSize().Height/8);
+ core::rect sourceRect(core::position2d(0,0),
+ red_team->getOriginalSize());
+ irr_driver->getVideoDriver()->draw2DImage(red_team,indicatorPos,sourceRect,
+ NULL,NULL,true);
+
+
+ for(unsigned int i=0; igetNumKarts(); i++){
+ int j = soccerWorld->getTeamLeader(i);
+ if(j < 0) break;
+
+ core::rect source(j*m_marker_rendered_size, 0,
+ (j+1)*m_marker_rendered_size,m_marker_rendered_size);
+ core::recti position(offsetX, offsetY,
+ offsetX + 2*m_marker_player_size, offsetY + 2*m_marker_player_size);
+ irr_driver->getVideoDriver()->draw2DImage(m_marker, position, source,
+ NULL, NULL, true);
+ core::stringw score = StringUtils::toWString(soccerWorld->getScore(i));
+ int stringWidth =
+ GUIEngine::getFont()->getDimension(score.c_str()).Width;
+ int stringHeight =
+ GUIEngine::getFont()->getDimension(score.c_str()).Height;
+ core::recti pos(position.UpperLeftCorner.X + 5,
+ position.LowerRightCorner.Y + offsetY,
+ position.LowerRightCorner.X,
+ position.LowerRightCorner.Y + stringHeight);
+
+ font->draw(score.c_str(),pos,color);
+ offsetX += position.LowerRightCorner.X;
+ }
+ offsetX = 80;
+ offsetY = 5;
+ indicatorPos = core::rect(offsetX, offsetY,
+ offsetX + blue_team->getSize().Width/8,
+ offsetY + blue_team->getSize().Height/8);
+ sourceRect = core::rect (core::position2d(0,0),
+ blue_team->getOriginalSize());
+ irr_driver->getVideoDriver()->draw2DImage(blue_team,indicatorPos,sourceRect,
+ NULL,NULL,true);
+}
//-----------------------------------------------------------------------------
/** Displays the racing time on the screen.s
*/
diff --git a/src/states_screens/race_gui.hpp b/src/states_screens/race_gui.hpp
index bfd687bae..a159ded1e 100644
--- a/src/states_screens/race_gui.hpp
+++ b/src/states_screens/race_gui.hpp
@@ -105,6 +105,8 @@ private:
/** Display items that are shown once only (for all karts). */
void drawGlobalMiniMap ();
void drawGlobalTimer ();
+ void drawScores();
+
public:
diff --git a/src/states_screens/soccer_setup_screen.cpp b/src/states_screens/soccer_setup_screen.cpp
index ce7ab72b1..8805236de 100644
--- a/src/states_screens/soccer_setup_screen.cpp
+++ b/src/states_screens/soccer_setup_screen.cpp
@@ -56,6 +56,7 @@ void SoccerSetupScreen::eventCallback(Widget* widget, const std::string& name, c
if(name == "continue")
{
StateManager::get()->pushScreen( ArenasScreen::getInstance() );
+ race_manager->setMaxGoal(getWidget("goalamount")->getValue());
}
else if (name == "back")
{
@@ -221,7 +222,7 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti
break;
}
- if(team_switch != SOCCER_TEAM_NONE) // A player wants to change its team?
+ if(team_switch != SOCCER_TEAM_NONE) // A player wants to change his team?
{
// Find the corresponding kart view, update its team and update the layout
for(int i=0 ; i < nb_players ; i++)