Merged changes from trunk.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/battleAI@14293 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
nixt
2013-10-23 01:09:18 +00:00
parent d3f92542df
commit 3f9bf2ec47
63 changed files with 894 additions and 271 deletions

Binary file not shown.

View File

@@ -12,7 +12,7 @@
<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"/>
<spinner id="goalamount" proportion="1" height="100%" min_value="1" max_value="10" wrap_around="true"/>
</div>
<spacer height="25" width="25"/>

View File

@@ -11,7 +11,7 @@
<material name="stk_mod_nitroBottle.png" />
<material name="stk_mod_nitroLogo.png" compositing="additive" light="N" disable-z-write="Y" />
<material name="bubblegum_shield.png" compositing="blend" sphere="Y"/>
<material name="bubblegum_shield.png" compositing="blend" disable-z-write="Y"/>
<material name="parachute.png" backface-culling="n" ignore="Y"/>
<material name="zipper.png" light="N" zipper="Y"/>
<material name="zipper_collect.png" light="N" zipper="Y"/>

View File

@@ -253,6 +253,8 @@
disable-slipstream-usage: even if the AI is not trying to use slipstream,
it can get a lot of bonus, esp. on easy since the AI creates trains.
Set this to true to make sure AI does not get any slipstream bonus.
shield-incoming-radius: Radius at which projectiles will be detected and
trigger a shield usage.
false-start-probability: Probability of a false start.
min/max-start-delay: Minimum and maximum start delay.
See http://www.humanbenchmark.com/tests/reactiontime/stats.php
@@ -316,6 +318,7 @@
straight-length-for-zipper="35"
use-slipstream="false"
disable-slipstream-usage="true"
shield-incoming-radius="0"
false-start-probability="0.08"
min-start-delay="0.3" max-start-delay="0.5"
nitro-usage="none"
@@ -333,6 +336,7 @@
straight-length-for-zipper="35"
use-slipstream="false"
disable-slipstream-usage="false"
shield-incoming-radius="10"
false-start-probability="0.04"
min-start-delay="0.25" max-start-delay="0.4"
nitro-usage="some"
@@ -350,6 +354,7 @@
straight-length-for-zipper="35"
use-slipstream="true"
disable-slipstream-usage="false"
shield-incoming-radius="10"
false-start-probability="0.01"
min-start-delay="0.15" max-start-delay="0.28"
nitro-usage="all"
@@ -367,6 +372,7 @@
straight-length-for-zipper="35"
use-slipstream="true"
disable-slipstream-usage="false"
shield-incoming-radius="10"
false-start-probability="0.0"
min-start-delay="0.15" max-start-delay="0.2"
nitro-usage="all"
@@ -477,6 +483,11 @@
<rear-right position="0.38 0 -0.6" />
<rear-left position="-0.38 0 -0.6"/>
</wheels>
<!-- Parameters for the speed-weighted objects:
a bigger value for strength-factor leads to the speed of the kart more quickly affecting
the strength of the animation (up to a maximum value that corresponds to the original animation) -->
<speed-weighted strength-factor="0.05" speed-factor="5.0"/>
<!-- friction: slip used for bullet skidding. A high value
(like 10000000) disables bullet skidding. -->

View File

@@ -15,7 +15,7 @@ endif()
add_definitions(-DNDEBUG=1 -DIRRLICHT_EXPORTS=1 -DPNG_THREAD_UNSAFE_OK -DPNG_NO_MMX_CODE -DPNG_NO_MNG_FEATURES)
if(MSVC)
add_definitions(/D_IRR_STATIC_LIB_)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" /MTd)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MTd")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fno-rtti -fstrict-aliasing -fexpensive-optimizations -I/usr/X11R6/include")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fno-rtti -fstrict-aliasing -fexpensive-optimizations -I/usr/X11R6/include")

View File

@@ -86,6 +86,14 @@ namespace scene
/** \return Frames per second played. */
virtual f32 getAnimationSpeed() const =0;
//! Sets the animation strength (how important the animation is)
/** \param strength: The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual void setAnimationStrength(f32 strength) =0;
//! Gets the animation strength (how important the animation is)
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual f32 getAnimationStrength() const =0;
//! Creates shadow volume scene node as child of this node.
/** The shadow can be rendered using the ZPass or the zfail
method. ZPass is a little bit faster because the shadow volume

View File

@@ -69,7 +69,7 @@ namespace scene
virtual void animateMesh(f32 frame, f32 blend)=0;
//! Preforms a software skin on this mesh based of joint positions
virtual void skinMesh() = 0;
virtual void skinMesh(f32 strength=1.f) = 0;
//! converts the vertex type of all meshbuffers to tangents.
/** E.g. used for bump mapping. */

View File

@@ -33,7 +33,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
const core::vector3df& scale)
: IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
CurrentFrameNr(0.f), LastTimeMs(0),
CurrentFrameNr(0.f), AnimationStrength(1.f), LastTimeMs(0),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointMode(EJUOR_NONE), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
@@ -210,7 +210,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
// Update the skinned mesh for the current joint transforms.
skinnedMesh->skinMesh();
skinnedMesh->skinMesh(AnimationStrength);
if (JointMode == EJUOR_READ)//read from mesh
{
@@ -516,6 +516,21 @@ f32 CAnimatedMeshSceneNode::getAnimationSpeed() const
}
//! Sets the animation strength (how important the animation is)
/** \param strength: The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
void CAnimatedMeshSceneNode::setAnimationStrength(f32 strength)
{
AnimationStrength = strength;
}
//! Gets the animation strength (how important the animation is)
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
f32 CAnimatedMeshSceneNode::getAnimationStrength() const
{
return AnimationStrength;
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const
{

View File

@@ -66,6 +66,14 @@ namespace scene
//! gets the speed with which the animation is played
virtual f32 getAnimationSpeed() const;
//! Sets the animation strength (how important the animation is)
/** \param strength: The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual void setAnimationStrength(f32 strength);
//! Gets the animation strength (how important the animation is)
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual f32 getAnimationStrength() const;
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
@@ -183,6 +191,8 @@ namespace scene
f32 FramesPerSecond;
f32 CurrentFrameNr;
f32 AnimationStrength;
u32 LastTimeMs;
u32 TransitionTime; //Transition time in millisecs
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)

View File

@@ -445,7 +445,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
//--------------------------------------------------------------------------
//! Preforms a software skin on this mesh based of joint positions
void CSkinnedMesh::skinMesh()
void CSkinnedMesh::skinMesh(f32 strength)
{
if (!HasAnimation || SkinnedLastFrame)
return;
@@ -478,7 +478,7 @@ void CSkinnedMesh::skinMesh()
//skin starting with the root joints
for (i=0; i<RootJoints.size(); ++i)
skinJoint(RootJoints[i], 0);
skinJoint(RootJoints[i], 0, strength);
for (i=0; i<SkinningBuffers->size(); ++i)
(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
@@ -486,8 +486,7 @@ void CSkinnedMesh::skinMesh()
updateBoundingBox();
}
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
{
if (joint->Weights.size())
{
@@ -510,6 +509,14 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
if (AnimateNormals)
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
// Apply animation strength
if(strength != 1.f)
{
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
if(AnimateNormals)
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
}
if (! (*(weight.Moved)) )
{
*(weight.Moved) = true;
@@ -537,7 +544,7 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
//Skin all children
for (u32 j=0; j<joint->Children.size(); ++j)
skinJoint(joint->Children[j], joint);
skinJoint(joint->Children[j], joint, strength);
}

View File

@@ -52,7 +52,7 @@ namespace scene
virtual void animateMesh(f32 frame, f32 blend);
//! Preforms a software skin on this mesh based of joint positions
virtual void skinMesh();
virtual void skinMesh(f32 strength=1.f);
//! returns amount of mesh buffers.
virtual u32 getMeshBufferCount() const;
@@ -176,7 +176,7 @@ private:
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
void skinJoint(SJoint *Joint, SJoint *ParentJoint);
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
void calculateTangents(core::vector3df& normal,
core::vector3df& tangent, core::vector3df& binormal,

View File

@@ -616,8 +616,8 @@ bool CIrrDeviceMacOSX::createWindow()
// we need to check where the exceptions may happen and work at them
// for now we will just catch them to be able to avoid an app exit
@try
{
//@try
//{
if (!CreationParams.Fullscreen)
{
if(!CreationParams.WindowId) //create another window when WindowId is null
@@ -858,12 +858,12 @@ bool CIrrDeviceMacOSX::createWindow()
}
}
}
}
@catch (NSException *exception)
{
closeDevice();
result = false;
}
//}
//@catch (NSException *exception)
//{
// closeDevice();
// result = false;
//}
if (result)
{

View File

@@ -101,6 +101,8 @@ src/karts/abstract_kart_animation.cpp
src/karts/abstract_kart.cpp
src/karts/cannon_animation.cpp
src/karts/controller/ai_base_controller.cpp
src/karts/controller/ai_base_lap_controller.cpp
src/karts/controller/battle_ai.cpp
src/karts/controller/ai_properties.cpp
src/karts/controller/controller.cpp
src/karts/controller/end_controller.cpp
@@ -352,6 +354,8 @@ src/karts/abstract_kart_animation.hpp
src/karts/abstract_kart.hpp
src/karts/cannon_animation.hpp
src/karts/controller/ai_base_controller.hpp
src/karts/controller/ai_base_lap_controller.hpp
src/karts/controller/battle_ai.hpp
src/karts/controller/ai_properties.hpp
src/karts/controller/controller.hpp
src/karts/controller/end_controller.hpp

View File

@@ -1139,7 +1139,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = NO
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client

View File

@@ -1202,7 +1202,7 @@ MATHJAX_EXTENSIONS =
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = NO
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client

View File

@@ -19,6 +19,7 @@
#include "config/saved_grand_prix.hpp"
#include "karts/kart_properties_manager.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/string_utils.hpp"
@@ -145,10 +146,12 @@ void SavedGrandPrix::loadKarts(std::vector<RaceManager::KartStatus> & kart_list)
int aikarts = 0;
for(int i = 0; i < m_karts.size(); i++)
{
const KartProperties *kp = kart_properties_manager->getKart(m_karts[i].m_ident);
if(m_karts[i].m_local_player_id == -1)
{
//AI kart found
kart_list[aikarts].m_ident = m_karts[i].m_ident;
if(kp) kart_list[aikarts].m_ident = m_karts[i].m_ident;
kart_list[aikarts].m_score = m_karts[i].m_score;
kart_list[aikarts].m_overall_time = m_karts[i].m_overall_time;
aikarts++;

View File

@@ -994,9 +994,9 @@ void IrrDriver::removeTexture(video::ITexture *t)
/** Adds an animated mesh to the scene.
* \param mesh The animated mesh to add.
*/
scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *mesh)
scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *mesh, scene::ISceneNode* parent)
{
return m_scene_manager->addAnimatedMeshSceneNode(mesh, NULL, -1,
return m_scene_manager->addAnimatedMeshSceneNode(mesh, parent, -1,
core::vector3df(0,0,0),
core::vector3df(0,0,0),
core::vector3df(1,1,1),

View File

@@ -171,7 +171,7 @@ public:
void removeMeshFromCache(scene::IMesh *mesh);
void removeTexture(video::ITexture *t);
scene::IAnimatedMeshSceneNode
*addAnimatedMesh(scene::IAnimatedMesh *mesh);
*addAnimatedMesh(scene::IAnimatedMesh *mesh, scene::ISceneNode* parent=NULL);
scene::ICameraSceneNode
*addCameraSceneNode();
Camera *addCamera(unsigned int index, AbstractKart *kart);

View File

@@ -778,7 +778,6 @@ void Material::install(bool is_full_path, bool complain_if_not_found)
{
fprintf(stderr, "Applying mask failed for '%s'!\n",
m_texname.c_str());
return;
}
}
m_texture->grab();
@@ -938,8 +937,9 @@ void Material::initParticlesEffect(const XMLNode *node)
/** Adjusts the pitch of the given sfx depending on the given speed.
* \param sfx The sound effect to adjust.
* \param speed The speed of the kart.
* \param should_be_paused Pause for other reasons, i.e. kart is rescued.
*/
void Material::setSFXSpeed(SFXBase *sfx, float speed) const
void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const
{
// Still make a sound when driving backwards on the material.
if (speed < 0) speed = -speed;
@@ -947,14 +947,14 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed) const
// If we paused it due to too low speed earlier, we can continue now.
if (sfx->getStatus() == SFXManager::SFX_PAUSED)
{
if (speed<m_sfx_min_speed) return;
if (speed<m_sfx_min_speed || should_be_paused == 1) return;
// TODO: Do we first need to stop the sound completely so it
// starts over?
sfx->play();
}
else if (sfx->getStatus() == SFXManager::SFX_PLAYING)
{
if (speed<m_sfx_min_speed)
if (speed<m_sfx_min_speed || should_be_paused == 1)
{
// Pausing it to differentiate with sounds that ended etc
sfx->pause();

View File

@@ -253,7 +253,7 @@ public:
bool complain_if_not_found=true);
~Material ();
void setSFXSpeed(SFXBase *sfx, float speed) const;
void setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const;
void setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* mb);
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m, bool use_fog) const;

View File

@@ -37,10 +37,20 @@ SkidMarks::SkidMarks(const AbstractKart& kart, float width) : m_kart(kart)
{
m_width = width;
m_material = new video::SMaterial();
m_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
m_material->MaterialType = video::EMT_ONETEXTURE_BLEND;
m_material->MaterialTypeParam =
pack_textureBlendFunc(video::EBF_SRC_ALPHA,
video::EBF_ONE_MINUS_SRC_ALPHA,
video::EMFN_MODULATE_1X,
video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
m_material->AmbientColor = video::SColor(128, 0, 0, 0);
m_material->DiffuseColor = video::SColor(128, 16, 16, 16);
//m_material->AmbientColor = video::SColor(255, 255, 255, 255);
//m_material->DiffuseColor = video::SColor(255, 255, 255, 255);
m_material->setFlag(video::EMF_ANISOTROPIC_FILTER, true);
m_material->setFlag(video::EMF_ZWRITE_ENABLE, false);
m_material->Shininess = 0;
m_material->TextureLayer[0].Texture = irr_driver->getTexture("skidmarks.png");
m_skid_marking = false;
m_current = -1;
} // SkidMark
@@ -133,10 +143,19 @@ void SkidMarks::update(float dt, bool force_skid_marks,
delta.normalize();
delta *= m_width;
float distance = 0.0f;
Vec3 start = m_left[m_current]->getCenterStart();
Vec3 newPoint = (raycast_left.m_contactPointWS + raycast_right.m_contactPointWS)/2;
// this linear distance does not account for the kart turning, it's true,
// but it produces good enough results
distance = (newPoint - start).length();
m_left [m_current]->add(raycast_left.m_contactPointWS,
raycast_left.m_contactPointWS + delta);
raycast_left.m_contactPointWS + delta,
distance);
m_right[m_current]->add(raycast_right.m_contactPointWS-delta,
raycast_right.m_contactPointWS);
raycast_right.m_contactPointWS,
distance);
// Adjust the boundary box of the mesh to include the
// adjusted aabb of its buffers.
core::aabbox3df aabb=m_nodes[m_current]->getMesh()
@@ -219,6 +238,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
video::SColor* custom_color)
: scene::SMeshBuffer()
{
m_center_start = (left + right)/2;
m_z_offset = z_offset;
m_fade_out = 0.0f;
@@ -230,7 +250,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
Material = *material;
m_aabb = core::aabbox3df(left.toIrrVector());
add(left, right);
add(left, right, 0.0f);
} // SkidMarkQuads
@@ -240,7 +260,8 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
* \param left,right Left and right coordinates.
*/
void SkidMarks::SkidMarkQuads::add(const Vec3 &left,
const Vec3 &right)
const Vec3 &right,
float distance)
{
// The skid marks must be raised slightly higher, otherwise it blends
// too much with the track.
@@ -248,13 +269,25 @@ void SkidMarks::SkidMarkQuads::add(const Vec3 &left,
video::S3DVertex v;
v.Color = m_start_color;
v.Color.setAlpha(m_start_alpha);
v.Color.setAlpha(0); // initially create all vertices at alpha=0...
// then when adding a new set of vertices, make the previous 2 opaque.
// this ensures that the last two vertices are always at alpha=0,
// producing a fade-out effect
if (n > 4)
{
Vertices[n - 1].Color.setAlpha(m_start_alpha);
Vertices[n - 2].Color.setAlpha(m_start_alpha);
}
v.Pos = left.toIrrVector();
v.Pos.Y += m_z_offset;
v.Normal = core::vector3df(0, 1, 0);
v.TCoords = core::vector2df(0.0f, distance*0.5f);
Vertices.push_back(v);
v.Pos = right.toIrrVector();
v.Pos.Y += m_z_offset;
v.TCoords = core::vector2df(1.0f, distance*0.5f);
Vertices.push_back(v);
// Out of the box Irrlicht only supports triangle meshes and not
// triangle strips. Since this is a strip it would be more efficient
@@ -292,7 +325,8 @@ void SkidMarks::SkidMarkQuads::fade(float f)
a -= (a < m_fade_out ? a : (int)m_fade_out);
c.setAlpha(a);
for(unsigned int i=0; i<Vertices.size(); i++)
// the first 2 and last 2 already have alpha=0 for fade-in and fade-out
for(unsigned int i=2; i<Vertices.size() - 2; i++)
{
Vertices[i].Color.setAlpha(a);
}

View File

@@ -79,15 +79,20 @@ private:
video::SColor m_start_color;
/** Vector marking the start of the skidmarks (located between left and right wheel) */
Vec3 m_center_start;
public:
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
video::SMaterial *material, float z_offset,
video::SColor* custom_color = NULL);
void add (const Vec3 &left,
const Vec3 &right);
const Vec3 &right,
float distance);
void fade (float f);
/** Returns the aabb of this skid mark quads. */
const core::aabbox3df &getAABB() { return m_aabb; }
const Vec3& getCenterStart() const { return m_center_start; }
}; // SkidMarkQuads
// ------------------------------------------------------------------------
@@ -102,7 +107,7 @@ private:
static float m_avoid_z_fighting;
public:
SkidMarks(const AbstractKart& kart, float width=0.2f);
SkidMarks(const AbstractKart& kart, float width=0.32f);
~SkidMarks();
void update (float dt, bool force_skid_marks=false,
video::SColor* custom_color = NULL);

View File

@@ -1017,10 +1017,12 @@ namespace GUIEngine
// normal text will range from 0.2, in 640x* resolutions (won't scale
// below that) to 0.4, in 1024x* resolutions, and linearly up
const int screen_width = irr_driver->getFrameSize().Width;
const float normal_text_scale =
0.7f + 0.2f*std::max(0, screen_width - 640)/564.0f;
const float title_text_scale =
0.2f + 0.2f*std::max(0, screen_width - 640)/564.0f;
const int screen_height = irr_driver->getFrameSize().Height;
float scale = std::max(0, screen_width - 640)/564.0f;
if (screen_height < 700) scale = std::min(scale, 0.25f); // attempt to compensate for small screens
float normal_text_scale = 0.7f + 0.2f*scale;
float title_text_scale = 0.2f + 0.2f*scale;
ScalableFont* sfont =
new ScalableFont(g_env,

View File

@@ -38,7 +38,7 @@ ListWidget::ListWidget() : Widget(WTYPE_LIST)
m_icons = NULL;
m_listener = NULL;
m_selected_column = NULL;
m_sort_desc = true;
m_sort_desc = false;
m_sort_default = true;
}
@@ -300,7 +300,7 @@ void ListWidget::elementRemoved()
}
m_header_elements.clearAndDeleteAll();
m_selected_column = NULL;
m_sort_desc = true;
m_sort_desc = false;
m_sort_default = true;
}
@@ -378,8 +378,8 @@ EventPropagation ListWidget::transmitEvent(Widget* w,
}
else
{
m_sort_default = m_sort_desc && !m_sort_default;
if (!m_sort_default) m_sort_desc = !m_sort_desc;
m_sort_default = !m_sort_desc && !m_sort_default;
}
m_sort_col = originator[(m_properties[PROP_ID] + "_column_").size()] - '0';

View File

@@ -231,6 +231,7 @@
<ClCompile Include="..\..\karts\cannon_animation.cpp" />
<ClCompile Include="..\..\karts\controller\ai_base_controller.cpp" />
<ClCompile Include="..\..\karts\controller\ai_properties.cpp" />
<ClCompile Include="..\..\karts\controller\battle_ai.cpp" />
<ClCompile Include="..\..\karts\controller\skidding_ai.cpp" />
<ClCompile Include="..\..\karts\explosion_animation.cpp" />
<ClCompile Include="..\..\karts\ghost_kart.cpp" />

View File

@@ -35,12 +35,6 @@
<Filter Include="Header Files\physics">
<UniqueIdentifier>{1298df87-da0e-462e-b074-a496598571d8}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\karts">
<UniqueIdentifier>{11a7d573-5959-4be8-8a3f-d455d7833333}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\karts\controller">
<UniqueIdentifier>{d477b64b-eb9c-4059-a647-98f3a2f7203a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\graphics">
<UniqueIdentifier>{2f186570-85e9-4cea-88dc-0f716c6e141a}</UniqueIdentifier>
</Filter>
@@ -154,6 +148,12 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header Files\items\karts">
<UniqueIdentifier>{11a7d573-5959-4be8-8a3f-d455d7833333}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\items\karts\controller">
<UniqueIdentifier>{d477b64b-eb9c-4059-a647-98f3a2f7203a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\main.cpp">
@@ -885,6 +885,9 @@
<ClCompile Include="..\..\karts\controller\ai_base_controller.cpp">
<Filter>Source Files\karts\controller</Filter>
</ClCompile>
<ClCompile Include="..\..\karts\controller\battle_ai.cpp">
<Filter>Source Files\karts\controller</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\main_loop.hpp">
@@ -1158,34 +1161,34 @@
<Filter>Header Files\physics</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_control.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_model.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_properties.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_properties_manager.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\max_speed.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\moveable.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\controller.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\end_controller.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\player_controller.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\graphics\camera.hpp">
<Filter>Header Files\graphics</Filter>
@@ -1539,7 +1542,7 @@
<Filter>Header Files\graphics</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_with_stats.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\tracks\track_sector.hpp">
<Filter>Header Files\tracks</Filter>
@@ -1575,7 +1578,7 @@
<Filter>Header Files\states_screens</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\kart_gfx.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\states_screens\dialogs\select_challenge.hpp">
<Filter>Header Files\states_screens\dialogs</Filter>
@@ -1590,28 +1593,28 @@
<Filter>Header Files\replay</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\ghost_kart.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\skidding.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\skidding_properties.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\explosion_animation.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\abstract_kart_animation.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\abstract_kart.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\cannon_animation.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\rescue_animation.hpp">
<Filter>Header Files\karts</Filter>
<Filter>Header Files\items\karts</Filter>
</ClInclude>
<ClInclude Include="..\..\modes\demo_world.hpp">
<Filter>Header Files\modes</Filter>
@@ -1626,7 +1629,7 @@
<Filter>Header Files\graphics</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\skidding_ai.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\modes\cutscene_world.hpp">
<Filter>Header Files\modes</Filter>
@@ -1638,7 +1641,7 @@
<Filter>Header Files\addons</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\ai_properties.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\interpolation_array.hpp">
<Filter>Header Files\utils</Filter>
@@ -1689,10 +1692,10 @@
<Filter>Header Files\tracks</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\ai_base_lap_controller.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
<ClInclude Include="..\..\karts\controller\ai_base_controller.hpp">
<Filter>Header Files\karts\controller</Filter>
<Filter>Header Files\items\karts\controller</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -306,7 +306,8 @@ int WiimoteManager::askUserToConnectWiimotes()
{
new MessageDialog(
_("Press the buttons 1+2 simultaneously on your wiimote to put "
"it in discovery mode, then click on OK."),
"it in discovery mode, then click on Yes."
"Detailed instructions at supertuxkart.net/Wiimote"),
MessageDialog::MESSAGE_DIALOG_CONFIRM,
new WiimoteDialogListener(), true);

View File

@@ -329,9 +329,15 @@ void Attachment::hitBanana(Item *item, int new_attachment)
void Attachment::handleCollisionWithKart(AbstractKart *other)
{
Attachment *attachment_other=other->getAttachment();
if(getType()==Attachment::ATTACH_BOMB)
{
// Don't attach a bomb when the kart is shielded
if(other->isShielded())
{
other->decreaseShieldTime();
return;
}
// If both karts have a bomb, explode them immediately:
if(attachment_other->getType()==Attachment::ATTACH_BOMB)
{
@@ -356,6 +362,12 @@ void Attachment::handleCollisionWithKart(AbstractKart *other)
else if(attachment_other->getType()==Attachment::ATTACH_BOMB &&
(attachment_other->getPreviousOwner()!=m_kart || World::getWorld()->getNumKarts() <= 2))
{
// Don't attach a bomb when the kart is shielded
if(m_kart->isShielded())
{
m_kart->decreaseShieldTime();
return;
}
set(ATTACH_BOMB, other->getAttachment()->getTimeLeft()+
stk_config->m_bomb_time_increase, other);
other->getAttachment()->clear();

View File

@@ -18,6 +18,8 @@
#include "items/bowling.hpp"
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "graphics/hit_sfx.hpp"
#include "graphics/material.hpp"
#include "io/xml_node.hpp"
@@ -74,8 +76,22 @@ Bowling::Bowling(AbstractKart *kart)
// should not live forever, auto-destruct after 20 seconds
m_max_lifespan = 20;
m_roll_sfx = sfx_manager->createSoundSource("bowling_roll");
m_roll_sfx->play();
m_roll_sfx->setLoop(true);
} // Bowling
// ----------------------------------------------------------------------------
/** Destructor, removes any playing sfx.
*/
Bowling::~Bowling()
{
if(m_roll_sfx->getStatus()==SFXManager::SFX_PLAYING)
m_roll_sfx->stop();
sfx_manager->deleteSFX(m_roll_sfx);
} // ~RubberBall
// -----------------------------------------------------------------------------
/** Initialises this object with data from the power.xml file.
* \param node XML Node
@@ -200,6 +216,10 @@ bool Bowling::updateAndDelete(float dt)
hit(NULL);
return true;
}
if (m_roll_sfx->getStatus()==SFXManager::SFX_PLAYING)
m_roll_sfx->position(getXYZ());
return false;
} // updateAndDelete
// -----------------------------------------------------------------------------
@@ -237,5 +257,6 @@ HitEffect* Bowling::getHitEffect() const
{
if(m_has_hit_kart)
return new HitSFX(getXYZ(), "strike");
return NULL;
else
return new HitSFX(getXYZ(), "crash");
} // getHitEffect

View File

@@ -29,6 +29,7 @@ using namespace irr;
#include "items/flyable.hpp"
class XMLNode;
class SFXBase;
/**
* \ingroup items
@@ -45,8 +46,12 @@ private:
* kart was hit. */
bool m_has_hit_kart;
/** A sound effect for rolling ball. */
SFXBase *m_roll_sfx;
public:
Bowling(AbstractKart* kart);
Bowling(AbstractKart* kart);
virtual ~Bowling();
static void init(const XMLNode &node, scene::IMesh *bowling);
virtual bool updateAndDelete(float dt);
virtual const core::stringw getHitString(const AbstractKart *kart) const;

View File

@@ -515,4 +515,9 @@ HitEffect* Flyable::getHitEffect() const
return new Explosion(getXYZ(), "explosion", "explosion_cake.xml");
} // getHitEffect
// ----------------------------------------------------------------------------
unsigned int Flyable::getOwnerId()
{
return m_owner->getWorldKartId();
}
/* EOF */

View File

@@ -208,6 +208,8 @@ public:
* call, or if the inheriting object will update TerrainInfo itself
* (or perhaps not at all if it is not needed). */
void setDoTerrainInfo(bool d) { m_do_terrain_info = d; }
// ------------------------------------------------------------------------
unsigned int getOwnerId();
}; // Flyable
#endif

View File

@@ -152,7 +152,7 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
break ;
case PowerupManager::POWERUP_BOWLING:
m_sound_use = sfx_manager->createSoundSource("bowling_roll");
m_sound_use = sfx_manager->createSoundSource("bowling_shoot");
break ;
case PowerupManager::POWERUP_ANVIL:
@@ -264,7 +264,7 @@ void Powerup::use()
Powerup::adjustSound();
m_sound_use->play();
projectile_manager->newProjectile(m_owner, world->getTrack(), m_type);
projectile_manager->newProjectile(m_owner, m_type);
break ;
case PowerupManager::POWERUP_SWATTER:

View File

@@ -156,8 +156,13 @@ void ProjectileManager::updateClient(float dt)
} // for i in m_active_projectiles
} // updateClient
// -----------------------------------------------------------------------------
Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
/** Creates a new projectile of the given type.
* \param kart The kart which shoots the projectile.
* \param type Type of projectile.
*/
Flyable *ProjectileManager::newProjectile(AbstractKart *kart,
PowerupManager::PowerupType type)
{
Flyable *f;
@@ -173,3 +178,22 @@ Flyable *ProjectileManager::newProjectile(AbstractKart *kart, Track* track,
m_active_projectiles.push_back(f);
return f;
} // newProjectile
// -----------------------------------------------------------------------------
/** Returns true if a projectile is within the given distance of the specified
* kart.
* \param kart The kart for which the test is done.
* \param radius Distance within which the projectile must be.
*/
bool ProjectileManager::projectileIsClose(const AbstractKart * const kart,
float radius)
{
float r2 = radius*radius;
for(Projectiles::iterator i = m_active_projectiles.begin();
i != m_active_projectiles.end(); i++)
{
float dist2 = (*i)->getXYZ().distance2(kart->getXYZ());
if(dist2<r2) return true;
}
return false;
} // projectileIsClose

View File

@@ -61,10 +61,12 @@ public:
void loadData ();
void cleanup ();
void update (float dt);
Flyable* newProjectile (AbstractKart *kart, Track* track,
Flyable* newProjectile (AbstractKart *kart,
PowerupManager::PowerupType type);
void Deactivate (Flyable *p) {}
void removeTextures ();
bool projectileIsClose(const AbstractKart * const kart,
float radius);
// ------------------------------------------------------------------------
/** Adds a special hit effect to be shown.
* \param hit_effect The hit effect to be added. */

View File

@@ -87,6 +87,10 @@ RubberBall::RubberBall(AbstractKart *kart)
m_delete_timer = -1.0f;
m_tunnel_count = 0;
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return;
computeTarget();
// initialises the current graph node
@@ -141,8 +145,6 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
void RubberBall::computeTarget()
{
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return;
for(unsigned int p = race_manager->getFinishedKarts()+1;
p < world->getNumKarts()+1; p++)
@@ -190,13 +192,11 @@ unsigned int RubberBall::getSuccessorToHitTarget(unsigned int node_index,
{
int succ = 0;
LinearWorld *lin_world = dynamic_cast<LinearWorld*>(World::getWorld());
// FIXME: what does the rubber ball do in case of battle mode??
if(lin_world)
{
unsigned int sect =
lin_world->getSectorForKart(m_target);
succ = QuadGraph::get()->getNode(node_index).getSuccessorToReach(sect);
}
unsigned int sect =
lin_world->getSectorForKart(m_target);
succ = QuadGraph::get()->getNode(node_index).getSuccessorToReach(sect);
if(dist)
*dist += QuadGraph::get()->getNode(node_index)
.getDistanceToSuccessor(succ);
@@ -322,6 +322,10 @@ const core::stringw RubberBall::getHitString(const AbstractKart *kart) const
*/
bool RubberBall::updateAndDelete(float dt)
{
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return true;
if(m_delete_timer>0)
{
m_delete_timer -= dt;
@@ -629,7 +633,6 @@ float RubberBall::getMaxTerrainHeight(const Vec3 &vertical_offset) const
void RubberBall::updateDistanceToTarget()
{
const LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
if(!world) return; // FIXME battle mode
float target_distance =
world->getDistanceDownTrackForKart(m_target->getWorldKartId());

View File

@@ -137,7 +137,7 @@ void RubberBand::updatePosition()
*/
void RubberBand::update(float dt)
{
if(m_owner->isEliminated() || m_owner->isShielded())
if(m_owner->isEliminated())
{
// Rubber band snaps
m_plunger->hit(NULL);

View File

@@ -55,6 +55,7 @@ AbstractKart::AbstractKart(const std::string& ident,
m_kart_length = m_kart_model->getLength();
m_wheel_graphics_position = m_kart_model->getWheelsGraphicsPosition();
m_nitro_emitter_position = m_kart_model->getNitroEmittersPositon();
m_has_nitro_emitter = m_kart_model->hasNitroEmitters();
} // AbstractKart
// ----------------------------------------------------------------------------

View File

@@ -55,6 +55,8 @@ private:
const Vec3* m_wheel_graphics_position;
/** The position of all nitro emitters in the 3d model */
const Vec3* m_nitro_emitter_position;
/** True if kart has nitro emitters */
bool m_has_nitro_emitter;
/** Index of kart in world. */
unsigned int m_world_kart_id;
@@ -161,6 +163,10 @@ public:
/** Returns the position of a nitro emitter relative to the kart */
const Vec3& getNitroEmitterPosition(int i) const
{assert(i>=0 && i<2); return m_nitro_emitter_position[i];}
// ------------------------------------------------------------------------
/** Returns true if kart has nitro emitters */
const bool hasNitroEmitter() const
{return m_has_nitro_emitter;}
// ========================================================================
// Emergency animation related functions.

View File

@@ -157,6 +157,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_engine_sound = sfx_manager->createSoundSource(m_kart_properties->getEngineSfxType());
m_beep_sound = sfx_manager->createSoundSource( "horn" );
m_crash_sound = sfx_manager->createSoundSource( "crash" );
m_boing_sound = sfx_manager->createSoundSource( "boing" );
m_goo_sound = sfx_manager->createSoundSource( "goo" );
m_skid_sound = sfx_manager->createSoundSource( "skid" );
m_terrain_sound = NULL;
@@ -181,6 +182,7 @@ void Kart::init(RaceManager::KartType type)
m_goo_sound->volume( 1.0f / factor );
m_skid_sound->volume( 1.0f / factor );
m_crash_sound->volume( 1.0f / factor );
m_boing_sound->volume( 1.0f / factor );
m_beep_sound->volume( 1.0f / factor );
}
else
@@ -189,6 +191,7 @@ void Kart::init(RaceManager::KartType type)
m_skid_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_crash_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_beep_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_boing_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
}
}
@@ -244,6 +247,7 @@ Kart::~Kart()
sfx_manager->deleteSFX(m_skid_sound );
sfx_manager->deleteSFX(m_goo_sound );
sfx_manager->deleteSFX(m_beep_sound );
sfx_manager->deleteSFX(m_boing_sound );
delete m_kart_gfx;
if(m_terrain_sound) sfx_manager->deleteSFX(m_terrain_sound);
if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound);
@@ -1032,6 +1036,7 @@ void Kart::eliminate()
m_stars_effect->update(1);
}
m_kart_gfx->setCreationRateAbsolute(KartGFX::KGFX_TERRAIN, 0);
m_eliminated = true;
m_node->setVisible(false);
@@ -1171,6 +1176,7 @@ void Kart::update(float dt)
m_engine_sound->position ( getXYZ() );
m_crash_sound->position ( getXYZ() );
m_skid_sound->position ( getXYZ() );
m_boing_sound->position ( getXYZ() );
// Check if a kart is (nearly) upside down and not moving much --> automatic rescue
if(World::getWorld()->getTrack()->isAutoRescueEnabled() &&
@@ -1405,6 +1411,7 @@ void Kart::handleMaterialSFX(const Material *material)
m_terrain_sound = NULL;
}
}
if(m_previous_terrain_sound &&
m_previous_terrain_sound->getStatus()==SFXManager::SFX_STOPPED)
{
@@ -1414,15 +1421,19 @@ void Kart::handleMaterialSFX(const Material *material)
sfx_manager->deleteSFX(m_previous_terrain_sound);
m_previous_terrain_sound = NULL;
}
bool m_schedule_pause = m_flying ||
dynamic_cast<RescueAnimation*>(getKartAnimation()) ||
dynamic_cast<ExplosionAnimation*>(getKartAnimation());
// terrain sound is not necessarily a looping sound so check its status before
// setting its speed, to avoid 'ressuscitating' sounds that had already stopped
if(m_terrain_sound
&& (m_terrain_sound->getStatus() == SFXManager::SFX_PLAYING
|| m_terrain_sound->getStatus() == SFXManager::SFX_PAUSED))
if(m_terrain_sound &&
(m_terrain_sound->getStatus()==SFXManager::SFX_PLAYING ||
m_terrain_sound->getStatus()==SFXManager::SFX_PAUSED))
{
m_terrain_sound->position(getXYZ());
material->setSFXSpeed(m_terrain_sound, m_speed);
material->setSFXSpeed(m_terrain_sound, m_speed, m_schedule_pause);
}
} // handleMaterialSFX
@@ -1668,7 +1679,7 @@ void Kart::crashed(AbstractKart *k, bool update_attachments)
getAttachment()->handleCollisionWithKart(k);
}
m_controller->crashed(k);
crashed();
crashed(NULL, k);
} // crashed(Kart, update_attachments
// -----------------------------------------------------------------------------
@@ -1808,13 +1819,15 @@ void Kart::crashed(const Material *m, const Vec3 &normal)
} // if(m && m->getCollisionReaction() != Material::NORMAL &&
// !getKartAnimation())
m_controller->crashed(m);
crashed();
crashed(m, NULL);
} // crashed(Material)
// -----------------------------------------------------------------------------
/** Common code used when a kart or a material was hit.
* @param m The material collided into, or NULL if none
* @param k The kart collided into, or NULL if none
*/
void Kart::crashed()
void Kart::crashed(const Material* m, AbstractKart *k)
{
if(World::getWorld()->getTime()-m_time_last_crash < 0.5f) return;
@@ -1828,8 +1841,16 @@ void Kart::crashed()
{
// In case that the sfx is longer than 0.5 seconds, only play it if
// it's not already playing.
if(m_crash_sound->getStatus() != SFXManager::SFX_PLAYING)
m_crash_sound->play();
if (isShielded() || (k != NULL && k->isShielded()))
{
if (m_boing_sound->getStatus() != SFXManager::SFX_PLAYING)
m_boing_sound->play();
}
else
{
if(m_crash_sound->getStatus() != SFXManager::SFX_PLAYING)
m_crash_sound->play();
}
}
m_bounce_back_time = 0.1f;
@@ -2368,7 +2389,7 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
wheel_up_axis[i] = m_default_suspension_length[i]
- m_vehicle->getWheelInfo(i).m_raycastInfo.m_suspensionLength;
}
m_kart_model->update(m_wheel_rotation_dt, getSteerPercent(), wheel_up_axis);
m_kart_model->update(m_wheel_rotation_dt, getSteerPercent(), wheel_up_axis, m_speed);
Vec3 center_shift = m_kart_properties->getGravityCenterShift();
float y = m_vehicle->getWheelInfo(0).m_chassisConnectionPointCS.getY()

View File

@@ -130,7 +130,7 @@ private:
/** Current leaning of the kart. */
float m_current_lean;
/** If > 0 then bubble gum effect is on */
/** If > 0 then bubble gum effect is on. This is the sliding when hitting a gum on the floor, not the shield. */
float m_bubblegum_time;
/** The torque to apply after hitting a bubble gum. */
@@ -211,6 +211,7 @@ private:
SFXBase *m_previous_terrain_sound;
SFXBase *m_skid_sound;
SFXBase *m_goo_sound;
SFXBase *m_boing_sound;
float m_time_last_crash;
/** To prevent using nitro in too short bursts */
@@ -225,7 +226,7 @@ private:
void updateEngineSFX();
void updateNitro(float dt);
float getActualWheelForce();
void crashed();
void crashed(const Material* m, AbstractKart *k);
void loadData(RaceManager::KartType type, bool animatedModel);
public:

View File

@@ -50,13 +50,16 @@ KartGFX::KartGFX(const AbstractKart *kart)
*/
Vec3 rear_left(kart->getWheelGraphicsPosition(3).toIrrVector().X, (kart->getKartHeight()-0.6f)*0.35f,
kart->getWheelGraphicsPosition(3).toIrrVector().Z);
Vec3 rear_right(kart->getWheelGraphicsPosition(2).toIrrVector().X, (kart->getKartHeight()-0.6f)*0.35f,
kart->getWheelGraphicsPosition(2).toIrrVector().Z);
Vec3 rear_left(kart->getWheelGraphicsPosition(3).toIrrVector().X, 0.05f,
kart->getWheelGraphicsPosition(3).toIrrVector().Z-0.1f);
Vec3 rear_right(kart->getWheelGraphicsPosition(2).toIrrVector().X, 0.05f,
kart->getWheelGraphicsPosition(2).toIrrVector().Z-0.1f);
Vec3 rear_center(0, kart->getKartHeight()*0.35f,
-kart->getKartLength()*0.35f);
Vec3 rear_nitro_center(0, kart->getKartHeight()*0.2f,
-kart->getKartLength()*0.1f);
// FIXME Used to match the emitter as seen in blender
const float delta = 0.6f;
@@ -67,6 +70,8 @@ KartGFX::KartGFX(const AbstractKart *kart)
Vec3 rear_nitro_left(kart->getNitroEmitterPosition(1).toIrrVector().X,
kart->getNitroEmitterPosition(1).toIrrVector().Y,
kart->getNitroEmitterPosition(1).toIrrVector().Z + delta);
if (!kart->hasNitroEmitter())
rear_nitro_right = rear_nitro_left = rear_nitro_center;
// Create all effects. Note that they must be created
// in the order of KartGFXType.

View File

@@ -89,6 +89,7 @@ KartModel::KartModel(bool is_master)
m_wheel_filename[1] = "";
m_wheel_filename[2] = "";
m_wheel_filename[3] = "";
m_speed_weighted_objects.clear();
m_animated_node = NULL;
m_mesh = NULL;
for(unsigned int i=AF_BEGIN; i<=AF_END; i++)
@@ -123,6 +124,8 @@ void KartModel::loadInfo(const XMLNode &node)
animation_node->get("start-jump", &m_animation_frame[AF_JUMP_START]);
animation_node->get("start-jump-loop",&m_animation_frame[AF_JUMP_LOOP] );
animation_node->get("end-jump", &m_animation_frame[AF_JUMP_END] );
animation_node->get("start-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_START] );
animation_node->get("end-speed-weighted", &m_animation_frame[AF_SPEED_WEIGHTED_END] );
animation_node->get("speed", &m_animation_speed );
}
@@ -135,13 +138,22 @@ void KartModel::loadInfo(const XMLNode &node)
}
m_nitro_emitter_position[0] = Vec3 (0,0.1f,0);
m_nitro_emitter_position[1] = Vec3 (0,0.1f,0);
m_has_nitro_emitter = false;
if(const XMLNode *nitroEmitter_node=node.getNode("nitro-emitter"))
{
loadNitroEmitterInfo(*nitroEmitter_node, "nitro-emitter-a", 0);
loadNitroEmitterInfo(*nitroEmitter_node, "nitro-emitter-b", 1);
m_has_nitro_emitter = true;
}
if(const XMLNode *speedWeighted_node=node.getNode("speed-weighted"))
{
for(unsigned int i=0 ; i < speedWeighted_node->getNumNodes() ; i++)
{
loadSpeedWeightedInfo(speedWeighted_node->getNode(i));
}
}
if(const XMLNode *hat_node=node.getNode("hat"))
@@ -184,6 +196,22 @@ KartModel::~KartModel()
}
}
for(size_t i=0; i<m_speed_weighted_objects.size(); i++)
{
if(m_speed_weighted_objects[i].m_node)
{
// Master KartModels should never have a speed weighted object attached.
assert(!m_is_master);
m_speed_weighted_objects[i].m_node->drop();
}
if(m_is_master && m_speed_weighted_objects[i].m_model)
{
irr_driver->dropAllTextures(m_speed_weighted_objects[i].m_model);
irr_driver->removeMeshFromCache(m_speed_weighted_objects[i].m_model);
}
}
if(m_is_master && m_mesh)
{
m_mesh->drop();
@@ -231,6 +259,7 @@ KartModel* KartModel::makeCopy()
km->m_nitro_emitter_position[0] = m_nitro_emitter_position[0];
km->m_nitro_emitter_position[1] = m_nitro_emitter_position[1];
km->m_has_nitro_emitter = m_has_nitro_emitter;
for(unsigned int i=0; i<4; i++)
{
@@ -245,6 +274,17 @@ KartModel* KartModel::makeCopy()
km->m_max_suspension[i] = m_max_suspension[i];
km->m_dampen_suspension_amplitude[i]= m_dampen_suspension_amplitude[i];
}
km->m_speed_weighted_objects.resize(m_speed_weighted_objects.size());
for(size_t i=0; i<m_speed_weighted_objects.size(); i++)
{
km->m_speed_weighted_objects[i].m_model = m_speed_weighted_objects[i].m_model;
// Master should not have any speed weighted nodes.
assert(!m_speed_weighted_objects[i].m_node);
km->m_speed_weighted_objects[i].m_name = m_speed_weighted_objects[i].m_name;
km->m_speed_weighted_objects[i].m_position = m_speed_weighted_objects[i].m_position;
}
for(unsigned int i=AF_BEGIN; i<=AF_END; i++)
km->m_animation_frame[i] = m_animation_frame[i];
@@ -297,6 +337,13 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models)
if(!m_wheel_model[i]) continue;
m_wheel_node[i]->setParent(lod_node);
}
// Become the owner of the speed weighted objects
for(size_t i=0; i<m_speed_weighted_objects.size(); i++)
{
if(!m_speed_weighted_objects[i].m_node) continue;
m_speed_weighted_objects[i].m_node->setParent(lod_node);
}
}
else
{
@@ -314,6 +361,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models)
std::string debug_name = m_model_filename+" (kart-model)";
node->setName(debug_name.c_str());
#endif
// Attach the wheels
for(unsigned int i=0; i<4; i++)
{
if(!m_wheel_model[i]) continue;
@@ -325,6 +374,27 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models)
#endif
m_wheel_node[i]->setPosition(m_wheel_graphics_position[i].toIrrVector());
}
// Attach the speed weighted objects + set the animation state
for(size_t i=0 ; i < m_speed_weighted_objects.size() ; i++)
{
SpeedWeightedObject& obj = m_speed_weighted_objects[i];
obj.m_node = NULL;
if(obj.m_model)
{
obj.m_node = irr_driver->addAnimatedMesh(obj.m_model, node);
obj.m_node->grab();
obj.m_node->setAnimationStrength(0.0f);
obj.m_node->setFrameLoop(m_animation_frame[AF_SPEED_WEIGHTED_START], m_animation_frame[AF_SPEED_WEIGHTED_END]);
#ifdef DEBUG
std::string debug_name = obj.m_name+" (speed-weighted)";
obj.m_node->setName(debug_name.c_str());
#endif
obj.m_node->setPosition(obj.m_position.toIrrVector());
}
}
}
return node;
} // attachModel
@@ -348,10 +418,31 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
m_mesh->grab();
irr_driver->grabAllTextures(m_mesh);
Vec3 min, max;
MeshTools::minMax3D(m_mesh->getMesh(m_animation_frame[AF_STRAIGHT]), &min, &max);
Vec3 kart_min, kart_max;
MeshTools::minMax3D(m_mesh->getMesh(m_animation_frame[AF_STRAIGHT]), &kart_min, &kart_max);
Vec3 size = max-min;
// Load the speed weighted object models. We need to do that now because it can affect the dimensions of the kart
for(size_t i=0 ; i < m_speed_weighted_objects.size() ; i++)
{
SpeedWeightedObject& obj = m_speed_weighted_objects[i];
std::string full_name =
kart_properties.getKartDir()+obj.m_name;
obj.m_model = irr_driver->getAnimatedMesh(full_name);
// Grab all textures. This is done for the master only, so
// the destructor will only free the textures if a master
// copy is freed.
irr_driver->grabAllTextures(obj.m_model);
// Update min/max
Vec3 obj_min, obj_max;
MeshTools::minMax3D(obj.m_model, &obj_min, &obj_max);
obj_min += obj.m_position;
obj_max += obj.m_position;
kart_min.min(obj_min);
kart_max.min(obj_max);
}
Vec3 size = kart_max-kart_min;
m_kart_width = size.getX();
m_kart_height = size.getY();
m_kart_length = size.getZ();
@@ -416,6 +507,18 @@ void KartModel::loadNitroEmitterInfo(const XMLNode &node,
emitter_node->get("position", &m_nitro_emitter_position[index]);
} // loadNitroEmitterInfo
/** Loads a single speed weighted node. */
void KartModel::loadSpeedWeightedInfo(const XMLNode* speed_weighted_node)
{
SpeedWeightedObject obj;
speed_weighted_node->get("position", &obj.m_position);
speed_weighted_node->get("model", &obj.m_name);
if(!obj.m_name.empty())
m_speed_weighted_objects.push_back(obj);
}
// ----------------------------------------------------------------------------
/** Loads a single wheel node. Currently this is the name of the wheel model
* and the position of the wheel relative to the kart.
@@ -486,7 +589,7 @@ void KartModel::reset()
{
// Reset the wheels
const float suspension[4]={0,0,0,0};
update(0, 0.0f, suspension);
update(0, 0.0f, suspension, 0.0f);
// Stop any animations currently being played.
setAnimation(KartModel::AF_DEFAULT);
@@ -592,12 +695,14 @@ void KartModel::OnAnimationEnd(scene::IAnimatedMeshSceneNode *node)
} // OnAnimationEnd
// ----------------------------------------------------------------------------
/** Rotates and turns the wheels appropriately, and adjust for suspension.
/** Rotates and turns the wheels appropriately, and adjust for suspension
+ updates the speed-weighted objects' animations.
* \param rotation_dt How far the wheels have rotated since last time.
* \param steer The actual steer settings.
* \param suspension Suspension height for all four wheels.
* \param speed The speed of the kart in meters/sec, used for the speed-weighted objects' animations
*/
void KartModel::update(float rotation_dt, float steer, const float suspension[4])
void KartModel::update(float rotation_dt, float steer, const float suspension[4], float speed)
{
float clamped_suspension[4];
// Clamp suspension to minimum and maximum suspension length, so that
@@ -653,6 +758,18 @@ void KartModel::update(float rotation_dt, float steer, const float suspension[4]
// If animations are disabled, stop here
if (m_animated_node == NULL) return;
// Update the speed-weighted objects' animations
for(size_t i=0 ; i < m_speed_weighted_objects.size() ; i++)
{
SpeedWeightedObject& obj = m_speed_weighted_objects[i];
float strength = speed * m_kart->getKartProperties()->getSpeedWeightedStrengthFactor();
btClamp<float>(strength, 0.0f, 1.0f);
obj.m_node->setAnimationStrength(strength);
float anim_speed = speed * m_kart->getKartProperties()->getSpeedWeightedSpeedFactor();
obj.m_node->setAnimationSpeed(anim_speed);
}
// Check if the end animation is being played, if so, don't
// play steering animation.
if(m_current_animation!=AF_DEFAULT) return;
@@ -708,4 +825,3 @@ void KartModel::attachHat(){
} // if bone
} // if(m_hat_name)
}

View File

@@ -20,6 +20,7 @@
#define HEADER_KART_MODEL_HPP
#include <string>
#include <vector>
#include <IAnimatedMeshSceneNode.h>
namespace irr
@@ -36,6 +37,23 @@ class AbstractKart;
class KartProperties;
class XMLNode;
struct SpeedWeightedObject
{
SpeedWeightedObject() : m_model(NULL), m_node(NULL), m_position(), m_name() {}
/** Model */
scene::IAnimatedMesh * m_model;
/** The scene node the speed weighted model is attached to */
scene::IAnimatedMeshSceneNode * m_node;
/** The position of the "speed weighted" objects relative to the kart */
Vec3 m_position;
/** Filename of the "speed weighted" object */
std::string m_name;
};
typedef std::vector<SpeedWeightedObject> SpeedWeightedObjectList;
/**
* \brief This class stores a 3D kart model.
* It takes especially care of attaching
@@ -66,7 +84,9 @@ public:
AF_WIN_START, // Begin of win animation
AF_WIN_LOOP_START, // Begin of win loop animation
AF_WIN_END, // End of win animation
AF_END=AF_WIN_END, // Last animation frame
AF_SPEED_WEIGHTED_START, // Start of speed-weighted animation
AF_SPEED_WEIGHTED_END, // End of speed-weighted animation
AF_END=AF_SPEED_WEIGHTED_END, // Last animation frame
AF_COUNT}; // Number of entries here
private:
/** Which frame number starts/end which animation. */
@@ -120,6 +140,12 @@ private:
/** The position of the nitro emitters */
Vec3 m_nitro_emitter_position[2];
/** True if kart has nitro emitters */
bool m_has_nitro_emitter;
/** The speed weighted objects. */
SpeedWeightedObjectList m_speed_weighted_objects;
/** Minimum suspension length. If the displayed suspension is
* shorter than this, the wheel would look wrong. */
float m_min_suspension[4];
@@ -151,6 +177,8 @@ private:
void loadNitroEmitterInfo(const XMLNode &node,
const std::string &emitter_name, int index);
void loadSpeedWeightedInfo(const XMLNode* speed_weighted_node);
void OnAnimationEnd(scene::IAnimatedMeshSceneNode *node);
/** Pointer to the kart object belonging to this kart model. */
@@ -164,7 +192,7 @@ public:
void loadInfo(const XMLNode &node);
bool loadModels(const KartProperties &kart_properties);
void update(float rotation_dt, float steer,
const float suspension[4]);
const float suspension[4], float speed);
void setDefaultPhysicsPosition(const Vec3 &center_shift,
float wheel_radius);
void finishedRace();
@@ -214,6 +242,19 @@ public:
const Vec3* getNitroEmittersPositon() const
{return m_nitro_emitter_position;}
// ------------------------------------------------------------------------
/** Returns true if kart has nitro emitters */
const bool hasNitroEmitters() const
{return m_has_nitro_emitter;}
// ------------------------------------------------------------------------
/** Returns the number of speed weighted objects for this kart */
size_t getSpeedWeightedObjectsCount() const
{return m_speed_weighted_objects.size();}
// ------------------------------------------------------------------------
/** Returns the position of a speed weighted object relative to the kart.
* \param i Index of the object */
const SpeedWeightedObject& getSpeedWeightedObject(int i) const
{return m_speed_weighted_objects[i];}
// ------------------------------------------------------------------------
/** Returns the length of the kart model. */
float getLength () const {return m_kart_length; }
// ------------------------------------------------------------------------

View File

@@ -68,7 +68,8 @@ KartProperties::KartProperties(const std::string &filename)
m_nitro_max_speed_increase = m_nitro_duration = m_nitro_fade_out_time =
m_suspension_stiffness = m_wheel_damping_relaxation = m_wheel_base =
m_wheel_damping_compression = m_friction_slip = m_roll_influence =
m_wheel_radius = m_chassis_linear_damping = m_max_suspension_force =
m_wheel_radius = m_speed_weighted_strength_factor = m_speed_weighted_speed_factor =
m_chassis_linear_damping = m_max_suspension_force =
m_chassis_angular_damping = m_suspension_rest =
m_max_speed_reverse_ratio = m_rescue_vert_offset =
m_upright_tolerance = m_collision_terrain_impulse =
@@ -426,6 +427,12 @@ void KartProperties::getAllData(const XMLNode * root)
wheels_node->get("radius", &m_wheel_radius );
}
if(const XMLNode *speed_weighted_node = root->getNode("speed-weighted"))
{
speed_weighted_node->get("strength-factor", &m_speed_weighted_strength_factor);
speed_weighted_node->get("speed-factor", &m_speed_weighted_speed_factor);
}
if(const XMLNode *friction_node = root->getNode("friction"))
friction_node->get("slip", &m_friction_slip);
@@ -626,6 +633,8 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_time_reset_steer, "turn time-reset-steer" );
CHECK_NEG(m_wheel_damping_relaxation, "wheels damping-relaxation" );
CHECK_NEG(m_wheel_damping_compression, "wheels damping-compression" );
CHECK_NEG(m_speed_weighted_strength_factor, "speed-weighted strength-factor" );
CHECK_NEG(m_speed_weighted_speed_factor, "speed-weighted speed-factor" );
CHECK_NEG(m_wheel_radius, "wheels radius" );
CHECK_NEG(m_friction_slip, "friction slip" );
CHECK_NEG(m_roll_influence, "stability roll-influence" );

View File

@@ -264,6 +264,10 @@ private:
float m_roll_influence;
float m_wheel_radius;
// Parameters for speed-weighted objects
float m_speed_weighted_strength_factor;
float m_speed_weighted_speed_factor;
/** An impulse pushing the kart down which is proportional to speed. So
* the actual impulse is speed * m_downward_impulse_factor. Set it to
* 0 to disable completely. Based on
@@ -528,6 +532,14 @@ public:
/** Returns wheel radius. */
float getWheelRadius () const {return m_wheel_radius; }
// ------------------------------------------------------------------------
/** Returns animation strength factor for speed-weighted objects */
float getSpeedWeightedStrengthFactor() const {return m_speed_weighted_strength_factor;}
// ------------------------------------------------------------------------
/** Returns animation speed factor for speed-weighted objects */
float getSpeedWeightedSpeedFactor() const {return m_speed_weighted_speed_factor;}
// ------------------------------------------------------------------------
/** Returns the wheel base (distance front to rear axis). */
float getWheelBase () const {return m_wheel_base; }

View File

@@ -53,6 +53,8 @@ void SoccerWorld::init()
{
WorldWithRank::init();
m_display_rank = false;
m_goal_timer = 0.f;
m_lastKartToHitBall = -1;
// check for possible problems if AI karts were incorrectly added
if(getNumKarts() > race_manager->getNumPlayers())
@@ -61,7 +63,6 @@ void SoccerWorld::init()
exit(1);
}
m_goal_target = race_manager->getMaxGoal();
printf("Max Goal: %d\n", m_goal_target);
m_goal_sound = sfx_manager->createSoundSource("goal_scored");
} // init
@@ -79,7 +80,11 @@ void SoccerWorld::reset()
// Reset original positions for the soccer balls
TrackObjectManager* tom = getTrack()->getTrackObjectManager();
assert(tom);
m_redScorers.clear();
m_redScoreTimes.clear();
m_blueScorers.clear();
m_blueScoreTimes.clear();
m_lastKartToHitBall = -1;
PtrVector<TrackObject>& objects = tom->getObjects();
for(int i=0; i<objects.size(); i++)
{
@@ -90,9 +95,6 @@ void SoccerWorld::reset()
obj->reset();
obj->getPhysics()->reset();
}
World *world = World::getWorld();
world->setClockMode(World::CLOCK_NONE);
initKartList();
} // reset
@@ -111,9 +113,22 @@ const std::string& SoccerWorld::getIdent() const
*/
void SoccerWorld::update(float dt)
{
World *world = World::getWorld();
WorldWithRank::update(dt);
WorldWithRank::updateTrack(dt);
if (world->getPhase() == World::GOAL_PHASE)
{
m_goal_timer += dt;
if (m_goal_timer > 3.0f)
{
world->setPhase(WorldStatus::RACE_PHASE);
m_goal_timer = 0;
}
}
// TODO
} // update
@@ -131,8 +146,18 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
//printf("Score:\nTeam One %d : %d Team Two\n", m_team_goals[0], m_team_goals[1]);
World *world = World::getWorld();
world->setPhase(WorldStatus::GOAL_PHASE);
world->setClockMode(World::CLOCK_COUNTDOWN, 1.0);
m_goal_sound->play();
if(m_lastKartToHitBall != -1)
{
if(first_goal){
m_redScorers.push_back(m_lastKartToHitBall);
m_redScoreTimes.push_back(world->getTime());
}
else{
m_blueScorers.push_back(m_lastKartToHitBall);
m_blueScoreTimes.push_back(world->getTime());
}
}
}
//m_check_goals_enabled = false; // TODO: remove?
@@ -168,6 +193,13 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
// TODO: rescue the karts
} // onCheckGoalTriggered
//-----------------------------------------------------------------------------
/** Sets the last kart that hit the ball, to be able to
* identify the scorer later.
*/
void SoccerWorld::setLastKartTohitBall(unsigned int kartId){
m_lastKartToHitBall = kartId;
}
//-----------------------------------------------------------------------------
/** The battle is over if only one kart is left, or no player kart.
*/
@@ -361,7 +393,7 @@ void SoccerWorld::initKartList()
for(unsigned int i=0; i<kart_amount; i++)
{
scene::ISceneNode *arrowNode;
float arrow_pos_height = m_karts[i]->getKartModel()->getHeight()+0.5;
float arrow_pos_height = m_karts[i]->getKartModel()->getHeight()+0.5f;
if(race_manager->getLocalKartInfo(i).getSoccerTeam() == SOCCER_TEAM_RED)
arrowNode = irr_driver->addBillboard(core::dimension2d<irr::f32>(0.3f,0.3f),
@@ -450,8 +482,4 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
} // createKart
//-----------------------------------------------------------------------------
void SoccerWorld::countdownReachedZero()
{
World *world = World::getWorld();
world->setPhase(World::RACE_PHASE);
} // countdownReachedZero

View File

@@ -49,7 +49,13 @@ private:
and re-enabled when the next game can be played)*/
bool m_can_score_points;
SFXBase *m_goal_sound;
/** Timer for displaying goal text*/
float m_goal_timer;
int m_lastKartToHitBall;
std::vector<int> m_redScorers;
std::vector<float> m_redScoreTimes;
std::vector<int> m_blueScorers;
std::vector<float> m_blueScoreTimes;
public:
SoccerWorld();
@@ -75,10 +81,23 @@ public:
virtual void update(float dt);
virtual void countdownReachedZero();
void onCheckGoalTriggered(bool first_goal);
int getTeamLeader(unsigned int i);
void setLastKartTohitBall(unsigned int kartId);
std::vector<int> getScorers(unsigned int team)
{
if(team == 0)
return m_redScorers;
else
return m_blueScorers;
}
std::vector<float> getScoreTimes(unsigned int team)
{
if(team == 0)
return m_redScoreTimes;
else
return m_blueScoreTimes;
}
private:
void initKartList();

View File

@@ -327,7 +327,7 @@ Controller* World::loadAIController(AbstractKart *kart)
{
Controller *controller;
int turn=0;
// If different AIs should be used, adjust turn (or switch randomly
// If different AIs 8should be used, adjust turn (or switch randomly
// or dependent on difficulty)
switch(turn)
{

View File

@@ -132,7 +132,7 @@ void WorldStatus::update(const float dt)
case SETUP_PHASE:
m_auxiliary_timer = 0.0f;
m_phase = TRACK_INTRO_PHASE;
if (UserConfigParams::m_music && m_play_racestart_sounds)
if (m_play_racestart_sounds)
{
m_track_intro_sound->play();
}
@@ -148,6 +148,9 @@ void WorldStatus::update(const float dt)
if(m_track_intro_sound->getStatus()==SFXManager::SFX_PLAYING
&& m_auxiliary_timer<3.5f)
return;
// Wait before ready phase if sounds are disabled
if(!UserConfigParams::m_sfx && m_auxiliary_timer<3.0f)
return;
m_auxiliary_timer = 0.0f;
if (m_play_racestart_sounds) m_prestart_sound->play();
m_phase = READY_PHASE;

View File

@@ -528,6 +528,11 @@ void PhysicalObject::handleExplosion(const Vec3& pos, bool direct_hit)
} // handleExplosion
// ----------------------------------------------------------------------------
bool PhysicalObject::isSoccerBall()
{
return m_object->isSoccerBall();
}
// ----------------------------------------------------------------------------
/* EOF */

View File

@@ -27,6 +27,7 @@
#include "utils/vec3.hpp"
#include "utils/leak_check.hpp"
class XMLNode;
class TrackObject;
@@ -138,6 +139,7 @@ public:
virtual void handleExplosion(const Vec3& pos, bool directHit);
void update (float dt);
void init ();
bool isSoccerBall();
// ------------------------------------------------------------------------
/** Returns the rigid body of this physical object. */

View File

@@ -32,6 +32,7 @@
#include "physics/stk_dynamics_world.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/track.hpp"
#include "modes/soccer_world.hpp"
// ----------------------------------------------------------------------------
/** Initialise physics.
@@ -188,6 +189,12 @@ void Physics::update(float dt)
const KartProperties* kp = kart->getKartProperties();
kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
}
else if(obj->isSoccerBall())
{
int kartId = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
soccerWorld->setLastKartTohitBall(kartId);
}
continue;
}
@@ -228,6 +235,13 @@ void Physics::update(float dt)
// -------------------------------
p->getUserPointer(0)->getPointerFlyable()
->hit(NULL, p->getUserPointer(1)->getPointerPhysicalObject());
PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
if(obj->isSoccerBall())
{
int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
soccerWorld->setLastKartTohitBall(kartId);
}
}
else if(p->getUserPointer(1)->is(UserPointer::UP_KART))

View File

@@ -136,7 +136,7 @@ void AddonsScreen::init()
m_reloading = false;
m_sort_desc = true;
m_sort_desc = false;
m_sort_default = true;
m_sort_col = 0;
@@ -389,8 +389,8 @@ void AddonsScreen::onColumnClicked(int column_id)
}
else
{
m_sort_default = m_sort_desc && !m_sort_default;
if (!m_sort_default) m_sort_desc = !m_sort_desc;
m_sort_default = !m_sort_desc && !m_sort_default;
}
m_sort_col = column_id;

View File

@@ -330,7 +330,7 @@ void FeatureUnlockedCutScene::init()
m_unlocked_stuff[n].m_root_gift_node = kart_model->attachModel(true);
kart_model->setAnimation(KartModel::AF_DEFAULT);
float susp[4]={0,0,0,0};
kart_model->update(0.0f, 0.0f, susp);
kart_model->update(0.0f, 0.0f, susp, 0.0f);
#ifdef DEBUG
m_unlocked_stuff[n].m_root_gift_node->setName("unlocked kart");

View File

@@ -340,7 +340,7 @@ void GrandPrixLose::setKarts(std::vector<std::string> ident_arg)
kart_main_node->updateAbsolutePosition();
kart_main_node->setRotation(vector3df(0, 90, 0));
float susp[4]={0,0,0,0};
kart_model->update(0.0f, 0.0f, susp);
kart_model->update(0.0f, 0.0f, susp, 0.0f);
}
else
{

View File

@@ -451,7 +451,7 @@ void GrandPrixWin::setKarts(const std::string idents_arg[3])
m_kart_z[n]) );
kart_main_node->setScale( core::vector3df(0.4f, 0.4f, 0.4f) );
float susp[4]={0,0,0,0};
kart_model->update(0.0f, 0.0f, susp);
kart_model->update(0.0f, 0.0f, susp, 0.0f);
}
else
{

View File

@@ -392,6 +392,11 @@ public:
kart_model.getWheelGraphicsPosition(2) );
m_model_view->addModel( kart_model.getWheelModel(3),
kart_model.getWheelGraphicsPosition(3) );
for(size_t i=0 ; i < kart_model.getSpeedWeightedObjectsCount() ; i++)
{
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject(i);
m_model_view->addModel(obj.m_model, obj.m_position);
}
m_model_view->setRotateContinuously( 35.0f );
// ---- Kart name label
@@ -954,6 +959,11 @@ public:
kart_model.getWheelGraphicsPosition(2) );
w3->addModel( kart_model.getWheelModel(3),
kart_model.getWheelGraphicsPosition(3) );
for(size_t i=0 ; i < kart_model.getSpeedWeightedObjectsCount() ; i++)
{
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject(i);
w3->addModel(obj.m_model, obj.m_position);
}
w3->update(0);
m_parent->m_kart_widgets[playerID].m_kart_name

View File

@@ -275,8 +275,8 @@ void RaceGUI::drawScores()
default: break;
}
core::rect<s32> indicatorPos(offsetX, offsetY,
offsetX + m_marker_player_size/1.25,
offsetY + m_marker_player_size/1.25);
offsetX + (int)(m_marker_player_size/1.25f),
offsetY + (int)(m_marker_player_size/1.25f));
core::rect<s32> sourceRect(core::position2d<s32>(0,0),
team_icon->getOriginalSize());
irr_driver->getVideoDriver()->draw2DImage(team_icon,indicatorPos,sourceRect,

View File

@@ -44,6 +44,7 @@
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
#include "utils/string_utils.hpp"
#include <algorithm>
DEFINE_SCREEN_SINGLETON( RaceResultGUI );
@@ -80,6 +81,12 @@ void RaceResultGUI::tearDown()
{
Screen::tearDown();
m_font->setMonospaceDigits(m_was_monospace);
if (m_finish_sound != NULL &&
m_finish_sound->getStatus() == SFXManager::SFX_PLAYING)
{
m_finish_sound->stop();
}
} // tearDown
//-----------------------------------------------------------------------------
@@ -298,14 +305,6 @@ void RaceResultGUI::onConfirm()
*/
void RaceResultGUI::determineTableLayout()
{
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
{
redTeamTexture = irr_driver->getTexture(
file_manager->getTextureFile("soccer_ball_red.png"));
blueTeamTexture = irr_driver->getTexture(
file_manager->getTextureFile("soccer_ball_blue.png"));
}
GUIEngine::Widget *table_area = getWidget("result-table");
m_font = GUIEngine::getFont();
@@ -520,6 +519,8 @@ void RaceResultGUI::onUpdate(float dt, irr::video::IVideoDriver*)
*/
void RaceResultGUI::renderGlobal(float dt)
{
bool isSoccerWorld = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;
m_timer += dt;
assert(World::getWorld()->getPhase()==WorldStatus::RESULT_DISPLAY_PHASE);
unsigned int num_karts = m_all_row_infos.size();
@@ -625,49 +626,54 @@ void RaceResultGUI::renderGlobal(float dt)
// Second phase: update X and Y positions for the various animations
// =================================================================
float v = 0.9f*UserConfigParams::m_width/m_time_single_scroll;
for(unsigned int i=0; i<m_all_row_infos.size(); i++)
if(!isSoccerWorld)
{
RowInfo *ri = &(m_all_row_infos[i]);
float x = ri->m_x_pos;
float y = ri->m_y_pos;
switch(m_animation_state)
for(unsigned int i=0; i<m_all_row_infos.size(); i++)
{
// Both states use the same scrolling:
case RR_INIT: break; // Remove compiler warning
case RR_RACE_RESULT:
case RR_OLD_GP_RESULTS:
if(m_timer > ri->m_start_at)
{ // if active
ri->m_x_pos -= dt*v;
if(ri->m_x_pos<m_leftmost_column)
ri->m_x_pos = (float)m_leftmost_column;
x = ri->m_x_pos;
}
break;
case RR_INCREASE_POINTS:
ri->m_current_displayed_points +=
dt*race_manager->getPositionScore(1)/m_time_for_points;
if(ri->m_current_displayed_points>ri->m_new_overall_points)
RowInfo *ri = &(m_all_row_infos[i]);
float x = ri->m_x_pos;
float y = ri->m_y_pos;
switch(m_animation_state)
{
ri->m_current_displayed_points =
(float)ri->m_new_overall_points;
}
ri->m_new_points -=
dt*race_manager->getPositionScore(1)/m_time_for_points;
if(ri->m_new_points<0)
ri->m_new_points = 0;
break;
case RR_RESORT_TABLE:
x = ri->m_x_pos
- ri->m_radius*sin(m_timer/m_time_rotation*M_PI);
y = ri->m_centre_point
+ ri->m_radius*cos(m_timer/m_time_rotation*M_PI);
break;
case RR_WAIT_TILL_END:
break;
} // switch
displayOneEntry((unsigned int)x, (unsigned int)y, i, true);
} // for i
// Both states use the same scrolling:
case RR_INIT: break; // Remove compiler warning
case RR_RACE_RESULT:
case RR_OLD_GP_RESULTS:
if(m_timer > ri->m_start_at)
{ // if active
ri->m_x_pos -= dt*v;
if(ri->m_x_pos<m_leftmost_column)
ri->m_x_pos = (float)m_leftmost_column;
x = ri->m_x_pos;
}
break;
case RR_INCREASE_POINTS:
ri->m_current_displayed_points +=
dt*race_manager->getPositionScore(1)/m_time_for_points;
if(ri->m_current_displayed_points>ri->m_new_overall_points)
{
ri->m_current_displayed_points =
(float)ri->m_new_overall_points;
}
ri->m_new_points -=
dt*race_manager->getPositionScore(1)/m_time_for_points;
if(ri->m_new_points<0)
ri->m_new_points = 0;
break;
case RR_RESORT_TABLE:
x = ri->m_x_pos
- ri->m_radius*sin(m_timer/m_time_rotation*M_PI);
y = ri->m_centre_point
+ ri->m_radius*cos(m_timer/m_time_rotation*M_PI);
break;
case RR_WAIT_TILL_END:
break;
} // switch
displayOneEntry((unsigned int)x, (unsigned int)y, i, true);
} // for i
}
else
displaySoccerResults();
// Display highscores
if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX ||
@@ -744,12 +750,6 @@ void RaceResultGUI::determineGPLayout()
void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
unsigned int n, bool display_points)
{
SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
bool isSoccerMode = race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER;
int m_team_goals[2] = {soccerWorld->getScore(0), soccerWorld->getScore(1)};
if (isSoccerMode && n > 0) return;
RowInfo *ri = &(m_all_row_infos[n]);
video::SColor color = ri->m_is_player_kart
? video::SColor(255,255,0, 0 )
@@ -770,73 +770,29 @@ void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
// First draw the icon
// -------------------
if (!isSoccerMode)
if(ri->m_kart_icon)
{
if(ri->m_kart_icon)
{
core::recti source_rect(core::vector2di(0,0),
ri->m_kart_icon->getSize());
core::recti dest_rect(current_x, y,
current_x+m_width_icon, y+m_width_icon);
irr_driver->getVideoDriver()->draw2DImage(ri->m_kart_icon, dest_rect,
source_rect, NULL, NULL,
true);
}
current_x += m_width_icon + m_width_column_space;
core::recti source_rect(core::vector2di(0,0),
ri->m_kart_icon->getSize());
core::recti dest_rect(current_x, y,
current_x+m_width_icon, y+m_width_icon);
irr_driver->getVideoDriver()->draw2DImage(ri->m_kart_icon, dest_rect,
source_rect, NULL, NULL,
true);
}
current_x += m_width_icon + m_width_column_space;
// Draw the name
// -------------
if (!isSoccerMode)
{
core::recti pos_name(current_x, y,
UserConfigParams::m_width, y+m_distance_between_rows);
m_font->draw(ri->m_kart_name, pos_name, color, false, false, NULL,
true /* ignoreRTL */);
current_x += m_width_kart_name + m_width_column_space;
}
// Draw icon, name of team which won in soccer mode and score
// ----------------------------------------------------------
if (isSoccerMode)
{
core::stringw text;
irr::video::ITexture *team_icon;
if (m_team_goals[0] > m_team_goals[1])
{
text = core::stringw(_("Red team won"));
team_icon = redTeamTexture;
}
else if (m_team_goals[0] < m_team_goals[1])
{
text = core::stringw(_("Blue team won"));
team_icon = blueTeamTexture;
}
else
text = core::stringw(_("Draw"));
core::recti pos_name(current_x, y,
UserConfigParams::m_width, y+m_distance_between_rows);
m_font->draw(ri->m_kart_name, pos_name, color, false, false, NULL,
true /* ignoreRTL */);
current_x += m_width_kart_name + m_width_column_space;
core::recti source_rect(core::vector2di(0,0), team_icon->getSize());
core::recti dest_rect(current_x, y, current_x+m_width_icon, y+m_width_icon);
irr_driver->getVideoDriver()->draw2DImage(team_icon, dest_rect,
source_rect, NULL, NULL,
true);
current_x += m_width_icon + m_width_column_space;
core::recti pos_name(current_x, y,
UserConfigParams::m_width, y+m_distance_between_rows);
m_font->draw(text, pos_name, color, false, false, NULL, true /* ignoreRTL */);
core::dimension2du rect = m_font->getDimension(text.c_str());
current_x += rect.Width + 2*m_width_column_space;
text = core::stringw(m_team_goals[0]) + " : " + core::stringw(m_team_goals[1]);
dest_rect = core::recti(current_x, y, current_x+100, y+10);
m_font->draw(text, dest_rect, color, false, false, NULL, true /* ignoreRTL */);
rect = m_font->getDimension(text.c_str());
current_x += rect.Width + 2*m_width_column_space;
}
// Draw the time except in FTL mode
// --------------------------------
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER)
@@ -882,6 +838,145 @@ void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
}
} // displayOneEntry
//-----------------------------------------------------------------------------
void RaceResultGUI::displaySoccerResults()
{
//Draw win text
core::stringw resultText;
static video::SColor color = video::SColor(255, 255, 255, 255);
gui::IGUIFont* font = GUIEngine::getTitleFont();
int currX = UserConfigParams::m_width/2;
RowInfo *ri = &(m_all_row_infos[0]);
int currY = (int)ri->m_y_pos;
SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
int teamScore[2] = {soccerWorld->getScore(0), soccerWorld->getScore(1)};
GUIEngine::Widget *table_area = getWidget("result-table");
int height = table_area->m_h + table_area->m_y;
if(teamScore[0] > teamScore[1])
{
resultText = _("Red Team Wins");
}
else if(teamScore[1] > teamScore[0])
{
resultText = _("Blue Team Wins");
}
else
{
//Cannot really happen now. Only in time limited matches.
resultText = _("It's a draw");
}
core::rect<s32> pos(currX, currY, currX, currY);
font->draw(resultText.c_str(), pos, color, true, true);
core::dimension2du rect = m_font->getDimension(resultText.c_str());
//Draw team scores:
currY += rect.Height;
currX /= 2;
irr::video::ITexture* redTeamIcon = irr_driver->getTexture(
file_manager->getTextureFile("soccer_ball_red.png"));
irr::video::ITexture* blueTeamIcon = irr_driver->getTexture(
file_manager->getTextureFile("soccer_ball_blue.png"));
core::recti sourceRect(core::vector2di(0,0), redTeamIcon->getSize());
core::recti destRect(currX, currY, currX+redTeamIcon->getSize().Width/2,
currY+redTeamIcon->getSize().Height/2);
irr_driver->getVideoDriver()->draw2DImage(redTeamIcon, destRect,sourceRect,
NULL,NULL, true);
currX += UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
destRect = core::recti(currX, currY, currX+redTeamIcon->getSize().Width/2,
currY+redTeamIcon->getSize().Height/2);
irr_driver->getVideoDriver()->draw2DImage(blueTeamIcon,destRect,sourceRect,
NULL, NULL, true);
resultText = StringUtils::toWString(teamScore[1]);
rect = m_font->getDimension(resultText.c_str());
currX += redTeamIcon->getSize().Width/4;
currY += redTeamIcon->getSize().Height/2 + rect.Height/4;
pos = core::rect<s32>(currX, currY, currX, currY);
color = video::SColor(255,255,255,255);
font->draw(resultText.c_str(), pos, color, true, false);
currX -= UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
resultText = StringUtils::toWString(teamScore[0]);
pos = core::rect<s32>(currX,currY,currX,currY);
font->draw(resultText.c_str(), pos, color, true, false);
int centerX = UserConfigParams::m_width/2;
pos = core::rect<s32>(centerX, currY, centerX, currY);
font->draw("-", pos, color, true, false);
//Draw goal scorers:
//The red scorers:
currY += rect.Height/2 + rect.Height/4;
font = GUIEngine::getSmallFont();
std::vector<int> scorers = soccerWorld->getScorers(0);
std::vector<float> scoreTimes = soccerWorld->getScoreTimes(0);
irr::video::ITexture* scorerIcon;
int prevY = currY;
for(unsigned int i=0; i<scorers.size(); i++)
{
resultText = soccerWorld->getKart(scorers.at(i))->
getKartProperties()->getName();
resultText.append(" ");
resultText.append(StringUtils::timeToString(scoreTimes.at(i)).c_str());
rect = m_font->getDimension(resultText.c_str());
if(height-prevY < ((short)scorers.size()+1)*(short)rect.Height)
currY += (height-prevY)/((short)scorers.size()+1);
else
currY += rect.Height;
if(currY > height) break;
pos = core::rect<s32>(currX,currY,currX,currY);
font->draw(resultText,pos, color, true, false);
scorerIcon = soccerWorld->getKart(scorers.at(i))->
getKartProperties()->getIconMaterial()->getTexture();
sourceRect = core::recti(core::vector2di(0,0), scorerIcon->getSize());
irr::u32 offsetX = GUIEngine::getFont()->getDimension(resultText.c_str()).Width/2;
destRect = core::recti(currX-offsetX-30, currY, currX-offsetX, currY+ 30);
irr_driver->getVideoDriver()->draw2DImage(scorerIcon, destRect, sourceRect,
NULL, NULL, true);
}
//The blue scorers:
currY = prevY;
currX += UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
scorers = soccerWorld->getScorers(1);
scoreTimes = soccerWorld->getScoreTimes(1);
for(unsigned int i=0; i<scorers.size(); i++)
{
resultText = soccerWorld->getKart(scorers.at(i))->
getKartProperties()->getName();
resultText.append(" ");
resultText.append(StringUtils::timeToString(scoreTimes.at(i)).c_str());
rect = m_font->getDimension(resultText.c_str());
if(height-prevY < ((short)scorers.size()+1)*(short)rect.Height)
currY += (height-prevY)/((short)scorers.size()+1);
else
currY += rect.Height;
if(currY > height) break;
pos = core::rect<s32>(currX,currY,currX,currY);
font->draw(resultText,pos, color, true, false);
scorerIcon = soccerWorld->getKart(scorers.at(i))->
getKartProperties()->getIconMaterial()->getTexture();
sourceRect = core::recti(core::vector2di(0,0), scorerIcon->getSize());
irr::u32 offsetX = GUIEngine::getFont()->getDimension(resultText.c_str()).Width/2;
destRect = core::recti(currX-offsetX-30, currY, currX-offsetX, currY+ 30);
irr_driver->getVideoDriver()->draw2DImage(scorerIcon, destRect, sourceRect,
NULL, NULL, true);
}
}
//-----------------------------------------------------------------------------
void RaceResultGUI::clearHighscores()

View File

@@ -110,8 +110,6 @@ private:
}; // Rowinfo
/** The team icons. */
video::ITexture *redTeamTexture;
video::ITexture *blueTeamTexture;
std::vector<RowInfo> m_all_row_infos;
@@ -198,6 +196,7 @@ private:
void displayGPProgress();
void cleanupGPProgress();
void displayHighScores();
void displaySoccerResults();
public:
RaceResultGUI();

View File

@@ -35,7 +35,7 @@ using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( SoccerSetupScreen );
#define KART_CONTINUOUS_ROTATION_SPEED 35.f
#define KART_CONFIRMATION_ROTATION_SPEED 0.f
#define KART_CONFIRMATION_ROTATION_SPEED 4.f
#define KART_CONFIRMATION_TARGET_ANGLE 10.f
// -----------------------------------------------------------------------------
@@ -56,7 +56,7 @@ void SoccerSetupScreen::eventCallback(Widget* widget, const std::string& name, c
if(name == "continue")
{
StateManager::get()->pushScreen( ArenasScreen::getInstance() );
race_manager->setMaxGoal(getWidget<SpinnerWidget>("goalamount")->getValue());
race_manager->setMaxGoal(getWidget<SpinnerWidget>("goalamount")->getValue());
input_manager->setMasterPlayerOnly(true);
}
else if (name == "back")
@@ -184,12 +184,28 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti
switch(action)
{
case PA_MENU_LEFT:
if (bt_continue->isFocusedForPlayer(PLAYER_ID_GAME_MASTER))
if (bt_continue->isFocusedForPlayer(PLAYER_ID_GAME_MASTER) &&
m_kart_view_info[playerId].confirmed == false)
{
team_switch = SOCCER_TEAM_RED;
for(int i=0 ; i < nb_players ; i++)
{
m_kart_view_info[i].view->unsetBadge(BAD_BADGE);
}
}
break;
case PA_MENU_RIGHT:
if (bt_continue->isFocusedForPlayer(PLAYER_ID_GAME_MASTER))
if (bt_continue->isFocusedForPlayer(PLAYER_ID_GAME_MASTER) &&
m_kart_view_info[playerId].confirmed == false)
{
team_switch = SOCCER_TEAM_BLUE;
for(int i=0 ; i < nb_players ; i++)
{
m_kart_view_info[i].view->unsetBadge(BAD_BADGE);
}
}
break;
case PA_MENU_UP:
if (playerId != PLAYER_ID_GAME_MASTER)
@@ -204,13 +220,28 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti
if (!bt_continue->isFocusedForPlayer(PLAYER_ID_GAME_MASTER) || areAllKartsConfirmed())
return result;
if (getNumConfirmedKarts() > nb_players-2 &&
(getNumKartsInTeam(SOCCER_TEAM_RED) == 0 ||
getNumKartsInTeam(SOCCER_TEAM_BLUE) == 0))
{
if (!m_kart_view_info[playerId].confirmed)
{
sfx_manager->quickSound( "anvil" );
m_kart_view_info[playerId].view->setBadge(BAD_BADGE);
}
return EVENT_BLOCK;
}
// Confirm team selection
for(int i=0 ; i < nb_players ; i++)
{
if(m_kart_view_info[i].local_player_id == playerId)
if(m_kart_view_info[i].local_player_id == playerId &&
m_kart_view_info[i].confirmed == false)
{
m_kart_view_info[i].confirmed = true;
m_kart_view_info[i].view->setRotateTo( KART_CONFIRMATION_TARGET_ANGLE, KART_CONFIRMATION_ROTATION_SPEED );
m_kart_view_info[i].view->setBadge(OK_BADGE);
sfx_manager->quickSound( "wee" );
break;
}
}
@@ -230,8 +261,9 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti
{
m_kart_view_info[i].confirmed = false;
m_kart_view_info[i].view->setRotateContinuously( KART_CONTINUOUS_ROTATION_SPEED );
break;
m_kart_view_info[i].view->unsetBadge(OK_BADGE);
}
m_kart_view_info[i].view->unsetBadge(BAD_BADGE);
}
result = EVENT_BLOCK;
break;
@@ -239,7 +271,7 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti
default:
break;
}
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
@@ -288,6 +320,30 @@ bool SoccerSetupScreen::areAllKartsConfirmed() const
return all_confirmed;
}
int SoccerSetupScreen::getNumKartsInTeam(int team)
{
int karts_in_team = 0;
int nb_players = m_kart_view_info.size();
for(int i=0 ; i < nb_players ; i++)
{
if(m_kart_view_info[i].team == team)
karts_in_team++;
}
return karts_in_team;
}
int SoccerSetupScreen::getNumConfirmedKarts()
{
int confirmed_karts = 0;
int nb_players = m_kart_view_info.size();
for(int i=0 ; i < nb_players ; i++)
{
if(m_kart_view_info[i].confirmed == true)
confirmed_karts++;
}
return confirmed_karts;
}
void SoccerSetupScreen::updateKartViewsLayout()
{
Widget* central_div = getWidget<Widget>("central_div");

View File

@@ -72,6 +72,8 @@ public:
private:
bool areAllKartsConfirmed() const;
int getNumKartsInTeam(int team);
int getNumConfirmedKarts();
void updateKartViewsLayout();
};