Solving a challenge will now actually show the features you unlocked. Adapted the feature unlocked screen to be able to show many unlocked features at once. Show unlocked text in feature screen.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4896 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2010-03-02 01:25:29 +00:00
parent 7519e3d550
commit 8d2d755490
7 changed files with 250 additions and 162 deletions

View File

@ -31,6 +31,44 @@
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
const irr::core::stringw UnlockableFeature::getUnlockedMessage() const
{
switch (type)
{
case UNLOCK_TRACK:
{ // {} avoids compiler warning
Track* track = track_manager->getTrack( name );
return StringUtils::insertValues(_("New track '%s' now available"),
track->getName().c_str() );
break;
}
case UNLOCK_MODE:
{
return StringUtils::insertValues(_("New game mode '%s' now available"),
user_name.c_str());
}
case UNLOCK_GP:
{
const irr::core::stringw& gp_user_name = grand_prix_manager->getGrandPrix(name)->getName();
return StringUtils::insertValues(_("New Grand Prix '%s' now available"),
gp_user_name.c_str());
}
case UNLOCK_DIFFICULTY:
{
return StringUtils::insertValues(_("New difficulty\n'%s' now available"),
user_name.c_str());
}
case UNLOCK_KART:
{
const KartProperties *kp=kart_properties_manager->getKart( name );
return StringUtils::insertValues( _("New kart\n'%s' now available"),
kp->getName().c_str());
}
default:
assert(false);
return L"";
} // switch
}
//-----------------------------------------------------------------------------
void Challenge::addUnlockTrackReward(const std::string &track_name)
@ -85,61 +123,6 @@ void Challenge::addUnlockKartReward(const std::string &internal_name,
m_feature.push_back(feature);
}
//-----------------------------------------------------------------------------
const irr::core::stringw Challenge::getUnlockedMessage() const
{
irr::core::stringw unlocked_message;
const unsigned int amount = (unsigned int)m_feature.size();
for(unsigned int n=0; n<amount; n++)
{
// add line break if we are showing multiple messages
if(n>0) unlocked_message+='\n';
irr::core::stringw message;
// write message depending on feature type
switch(m_feature[n].type)
{
case UNLOCK_TRACK:
{ // {} avoids compiler warning
Track* track = track_manager->getTrack( m_feature[n].name );
message = StringUtils::insertValues(
_("New track '%s'\nnow available"),
track->getName().c_str() );
break;
}
case UNLOCK_MODE:
message = StringUtils::insertValues(
_("New game mode\n'%s'\nnow available"),
m_feature[n].user_name.c_str());
break;
case UNLOCK_GP:
{
const irr::core::stringw& gp_user_name = grand_prix_manager->getGrandPrix(m_feature[n].name)->getName();
message = StringUtils::insertValues(
_("New Grand Prix '%s'\nnow available"),
gp_user_name.c_str());
break;
}
case UNLOCK_DIFFICULTY:
message = StringUtils::insertValues(
_("New difficulty\n'%s'\nnow available"),
m_feature[n].user_name.c_str());
break;
case UNLOCK_KART:
const KartProperties *kp=kart_properties_manager->getKart(m_feature[n].name );
message = StringUtils::insertValues(
_("New kart\n'%s'\nnow available"),
kp->getName().c_str());
break;
} // switch
unlocked_message += message;
} // for n
return unlocked_message;
}
//-----------------------------------------------------------------------------
/** Loads the state for a challenge object (esp. m_state), and calls the
* virtual function loadAdditionalInfo for additional information

View File

@ -39,6 +39,8 @@ struct UnlockableFeature
std::string name; // internal name
irr::core::stringw user_name; // not all types of feature have one
REWARD_TYPE type;
const irr::core::stringw getUnlockedMessage() const;
};
// A base class for all challenges
@ -70,7 +72,6 @@ public:
void addUnlockKartReward(const std::string &internal_name,
const irr::core::stringw &user_name);
const irr::core::stringw getUnlockedMessage() const;
const std::vector<UnlockableFeature>&
getFeatures() const { return m_feature; }
void setChallengeDescription(const irr::core::stringw& d)

View File

@ -227,7 +227,7 @@ void ChallengeData::getUnlocks(const XMLNode *root, const std:: string type,
if (prop == NULL)
{
std::cerr << "Challenge refers to kart " << attrib <<
", which is unknown. Ignoring challenge.\n";
", which is unknown. Ignoring reward.\n";
break;
}
irr::core::stringw user_name = prop->getName();

View File

@ -524,23 +524,26 @@ scene::IMesh *IrrDriver::createTexturedQuadMesh(const video::SMaterial *material
{
scene::SMeshBuffer *buffer = new scene::SMeshBuffer();
const float w_2 = (float)w/2.0f;
const float h_2 = (float)h/2.0f;
video::S3DVertex v1;
v1.Pos = core::vector3df(0,0,0);
v1.Pos = core::vector3df(-w_2,-h_2,0);
v1.Normal = core::vector3df(1/sqrt(2.0f), 1/sqrt(2.0f), 0); // I hope normals are ok...
v1.TCoords = core::vector2d<f32>(0,1);
video::S3DVertex v2;
v2.Pos = core::vector3df((float)w,0,0);
v2.Pos = core::vector3df(w_2,-h_2,0);
v2.Normal = core::vector3df(1/sqrt(2.0f), 1/sqrt(2.0f), 0);
v2.TCoords = core::vector2d<f32>(1,1);
video::S3DVertex v3;
v3.Pos = core::vector3df((float)w,(float)h,0);
v3.Pos = core::vector3df(w_2,h_2,0);
v3.Normal = core::vector3df(1/sqrt(2.0f), 1/sqrt(2.0f), 0);
v3.TCoords = core::vector2d<f32>(1,0);
video::S3DVertex v4;
v4.Pos = core::vector3df(0,(float)h,0);
v4.Pos = core::vector3df(-w_2,h_2,0);
v4.Normal = core::vector3df(1/sqrt(2.0f), 1/sqrt(2.0f), 0);
v4.TCoords = core::vector2d<f32>(0,0);

View File

@ -376,34 +376,73 @@ GUIEngine::EventPropagation RaceOverDialog::processEvent(const std::string& even
unlock_manager->clearUnlocked();
FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance();
/*
scene->addUnlockedKart( const_cast<KartProperties*>(kart_properties_manager->getKart("gnu")),
_("Unlocked gnu kart") );
scene->addUnlockedPicture(
irr_driver->getTexture(track_manager->getTrack("beach")->getScreenshotFile().c_str()),
_("Unlocked beach track"));
scene->addUnlockedPicture(
irr_driver->getTexture(track_manager->getTrack("lighthouse")->getScreenshotFile().c_str()),
_("Unlocked lighthouse track"));
//scene->addUnlockedPicture( irr_driver->getTexture(track_manager->getTrack("canyon")->getScreenshotFile().c_str()) );
*/
assert(unlocked.size() > 0);
for (unsigned int n=0; n<unlocked.size(); n++)
{
//FIXME: this is only a placeholder
const bool unlocked_kart = true;
const bool unlocked_track = false;
const bool unlocked_game_mode = false;
const std::vector<UnlockableFeature>& unlockedFeatures = unlocked[n]->getFeatures();
assert(unlockedFeatures.size() > 0);
for (unsigned int i=0; i<unlockedFeatures.size(); i++)
{
switch (unlockedFeatures[i].type)
{
case UNLOCK_TRACK:
{
Track* track = track_manager->getTrack(unlockedFeatures[i].name);
assert(track != NULL);
const std::string sshot = track->getScreenshotFile();
scene->addUnlockedPicture( irr_driver->getTexture(sshot.c_str()),
unlockedFeatures[i].getUnlockedMessage() );
break;
}
case UNLOCK_GP:
{
//TODO
break;
}
case UNLOCK_MODE:
{
//TODO
break;
}
case UNLOCK_KART:
{
const KartProperties* kart = kart_properties_manager->getKart(unlockedFeatures[i].name);
assert(kart != NULL);
// the passed kart will not be modified, that's why I allow myself to use const_cast
scene->addUnlockedKart( const_cast<KartProperties*>(kart),
unlockedFeatures[i].getUnlockedMessage() );
break;
}
case UNLOCK_DIFFICULTY:
{
//TODO
break;
}
default:
{
assert(false);
}
}
} // next feature
} // next challenge
//FIXME: update the feature unlocked scene to be able to handle when many features are unlocked
if (unlocked_kart)
{
// the passed kart will not be modified, that's why I allow myself to use const_cast
scene->setUnlockedKart( const_cast<KartProperties*>(kart_properties_manager->getKart("gnu")) );
}
else if (unlocked_track)
{
scene->setUnlockedPicture( irr_driver->getTexture(track_manager->getTrack("beach")->getScreenshotFile().c_str()) );
}
else if (unlocked_game_mode)
{
//TODO!
assert(false);
}
else
{
assert(false);
}
}
ModalDialog::dismiss();
// clear the race (FIXME: is this the right way to go?)

View File

@ -23,27 +23,23 @@ FeatureUnlockedCutScene::FeatureUnlockedCutScene() : Screen("feature_unlocked.st
setNeeds3D(true);
throttleFPS = false;
m_unlocked_kart = NULL;
m_unlocked_thing_picture = NULL;
}
// -------------------------------------------------------------------------------------
void FeatureUnlockedCutScene::setUnlockedKart(KartProperties* unlocked_kart)
void FeatureUnlockedCutScene::addUnlockedKart(KartProperties* unlocked_kart, irr::core::stringw msg)
{
assert(unlocked_kart != NULL);
m_unlocked_kart = unlocked_kart;
m_unlocked_thing_picture = NULL;
m_unlocked_stuff.push_back( new UnlockedThing(unlocked_kart, msg) );
}
// -------------------------------------------------------------------------------------
void FeatureUnlockedCutScene::setUnlockedPicture(irr::video::ITexture* picture)
void FeatureUnlockedCutScene::addUnlockedPicture(irr::video::ITexture* picture, irr::core::stringw msg)
{
assert(picture != NULL);
m_unlocked_kart = NULL;
m_unlocked_thing_picture = picture;
m_unlocked_stuff.push_back( new UnlockedThing(picture, msg) );
}
// -------------------------------------------------------------------------------------
@ -85,47 +81,54 @@ void FeatureUnlockedCutScene::init()
m_light->getLightData().DiffuseColor = irr::video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
m_light->getLightData().SpecularColor = irr::video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
if (m_unlocked_kart != NULL)
const int unlockedStuffCount = m_unlocked_stuff.size();
if (unlockedStuffCount == 0) std::cerr << "There is nothing in the unlock chest!!!\n";
for (int n=0; n<unlockedStuffCount; n++)
{
KartModel* kartModel = m_unlocked_kart->getKartModel();
scene::ISceneNode* kart_node = irr_driver->getSceneManager()->addMeshSceneNode(kartModel->getModel());
for (int n=0; n<4; n++)
if (m_unlocked_stuff[n].m_unlocked_kart != NULL)
{
scene::ISceneNode* wheel = irr_driver->getSceneManager()->addMeshSceneNode(kartModel->getWheelModel(n), kart_node);
wheel->setPosition( kartModel->getWheelGraphicsPosition(n).toIrrVector() );
wheel->updateAbsolutePosition();
KartModel* kartModel = m_unlocked_stuff[n].m_unlocked_kart->getKartModel();
scene::ISceneNode* kart_node = irr_driver->getSceneManager()->addMeshSceneNode(kartModel->getModel());
for (int w=0; w<4; w++)
{
scene::ISceneNode* wheel = irr_driver->getSceneManager()->addMeshSceneNode(kartModel->getWheelModel(w), kart_node);
wheel->setPosition( kartModel->getWheelGraphicsPosition(w).toIrrVector() );
wheel->updateAbsolutePosition();
}
m_unlocked_stuff[n].m_root_gift_node = kart_node;
}
m_root_gift_node = kart_node;
}
else if (m_unlocked_thing_picture != NULL)
{
video::SMaterial m;
m.BackfaceCulling = false;
m.setTexture(0, m_unlocked_thing_picture);
m.AmbientColor = SColor(255,255,255,255);
m.DiffuseColor = SColor(255,255,255,255);
m.SpecularColor = SColor(0,0,0,0);
m.GouraudShading = false;
m.Shininess = 0;
//m.setFlag(video::EMF_TEXTURE_WRAP, false);
#if (IRRLICHT_VERSION_MAJOR == 1) && (IRRLICHT_VERSION_MINOR >= 7)
m.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
m.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
#else
m.TextureLayer[0].TextureWrap = video::ETC_CLAMP_TO_EDGE;
#endif
else if (m_unlocked_stuff[n].m_picture != NULL)
{
video::SMaterial m;
m.BackfaceCulling = false;
m.setTexture(0, m_unlocked_stuff[n].m_picture);
m.AmbientColor = SColor(255,255,255,255);
m.DiffuseColor = SColor(255,255,255,255);
m.SpecularColor = SColor(0,0,0,0);
m.GouraudShading = false;
m.Shininess = 0;
//m.setFlag(video::EMF_TEXTURE_WRAP, false);
#if (IRRLICHT_VERSION_MAJOR == 1) && (IRRLICHT_VERSION_MINOR >= 7)
m.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
m.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
#else
m.TextureLayer[0].TextureWrap = video::ETC_CLAMP_TO_EDGE;
#endif
scene::IMesh* mesh = irr_driver->createTexturedQuadMesh(&m, 1.0, 0.75);
m_root_gift_node = irr_driver->addMesh(mesh);
scene::IMesh* mesh = irr_driver->createTexturedQuadMesh(&m, 1.0, 0.75);
m_unlocked_stuff[n].m_root_gift_node = irr_driver->addMesh(mesh);
}
else
{
std::cerr << "There is nothing in the chest!!!\n";
}
else
{
std::cerr << "Malformed unlocked goody!!!\n";
}
}
}
@ -149,11 +152,7 @@ void FeatureUnlockedCutScene::tearDown()
irr_driver->removeNode(m_light);
m_light = NULL;
if (m_root_gift_node != NULL)
{
irr_driver->removeNode(m_root_gift_node);
m_root_gift_node = NULL;
}
m_unlocked_stuff.clearAndDeleteAll();
}
// -------------------------------------------------------------------------------------
@ -197,24 +196,43 @@ void FeatureUnlockedCutScene::onUpdate(float dt, irr::video::IVideoDriver* drive
const int GIFT_EXIT_FROM = (int)ANIM_TO;
const int GIFT_EXIT_TO = GIFT_EXIT_FROM + 12;
if (m_global_time > GIFT_EXIT_FROM && m_global_time < GIFT_EXIT_TO && m_root_gift_node != NULL)
{
core::vector3df pos = m_root_gift_node->getPosition();
pos.Y = sin( (float)((m_global_time - GIFT_EXIT_FROM)*M_PI*1.2/GIFT_EXIT_TO) )*30.0f;
pos.X += 2*dt;
pos.Z += 5*dt;
const int unlockedStuffCount = m_unlocked_stuff.size();
m_root_gift_node->setPosition(pos);
core::vector3df scale = m_root_gift_node->getScale();
scale.X += 2*dt;
scale.Y += 2*dt;
scale.Z += 2*dt;
m_root_gift_node->setScale(scale);
if (m_global_time > GIFT_EXIT_FROM && m_global_time < GIFT_EXIT_TO)
{
for (int n=0; n<unlockedStuffCount; n++)
{
if (m_unlocked_stuff[n].m_root_gift_node == NULL) continue;
core::vector3df pos = m_unlocked_stuff[n].m_root_gift_node->getPosition();
pos.Y = sin( (float)((m_global_time - GIFT_EXIT_FROM)*M_PI*1.2/GIFT_EXIT_TO) )*30.0f;
// when there are more than 1 unlocked items, make sure they each have their own path when they move
if (unlockedStuffCount > 1)
{
if (n % 2 == 0) pos.X -= 2.2f*dt*float( int((n + 1)/2) );
else pos.X += 2.2f*dt*float( int((n + 1)/2) );
//std::cout << "Object " << n << " moving by " << (n % 2 == 0 ? -4.0f : 4.0f)*float( n/2 + 1 ) << std::endl;
}
else
{
pos.X += 2*dt;
}
pos.Z += 5*dt;
m_unlocked_stuff[n].m_root_gift_node->setPosition(pos);
core::vector3df scale = m_unlocked_stuff[n].m_root_gift_node->getScale();
scale.X += 2*dt;
scale.Y += 2*dt;
scale.Z += 2*dt;
m_unlocked_stuff[n].m_root_gift_node->setScale(scale);
}
core::vector3df campos = m_camera->getPosition();
campos.X += 5*dt;
campos.X += 2*dt;
campos.Z += 5*dt;
m_camera->setPosition(campos);
@ -226,9 +244,11 @@ void FeatureUnlockedCutScene::onUpdate(float dt, irr::video::IVideoDriver* drive
sin((1.0f-m_key_angle)*M_PI/8 + M_PI/4)*70.0f) );
}
if (m_root_gift_node != NULL)
assert(m_unlocked_stuff.size() > 0);
if (m_unlocked_stuff[0].m_root_gift_node != NULL)
{
m_camera->setTarget( m_root_gift_node->getPosition() + core::vector3df(0.0f, 10.0f, 0.0f) );
m_camera->setTarget( m_unlocked_stuff[0].m_root_gift_node->getPosition() +
core::vector3df(0.0f, 10.0f, 0.0f) );
m_camera->updateAbsolutePosition();
}
else
@ -241,12 +261,28 @@ void FeatureUnlockedCutScene::onUpdate(float dt, irr::video::IVideoDriver* drive
static const int h = irr_driver->getFrameSize().Height;
const irr::video::SColor color(255, 255, 255, 255);
static int test_y = 0;
GUIEngine::getTitleFont()->draw(_("Feature Unlocked"),
core::rect< s32 >( 0, test_y, w, h/10 ),
core::rect< s32 >( 0, 0, w, h/10 ),
color,
true/* center h */, true /* center v */ );
if (m_global_time > GIFT_EXIT_TO)
{
const irr::video::SColor color2(255, 255, 126, 21);
const int fontH = GUIEngine::getFontHeight();
const int MARGIN = 10;
int message_y = h - fontH*3 - MARGIN;
for (int n=0; n<unlockedStuffCount; n++)
{
GUIEngine::getFont()->draw(m_unlocked_stuff[n].m_unlock_message,
core::rect< s32 >( 0, message_y, w, message_y + fontH ),
color2,
true /* center h */, true /* center v */ );
message_y -= (fontH + MARGIN);
}
}
}
// -------------------------------------------------------------------------------------

View File

@ -2,6 +2,7 @@
#define HEADER_FEATURE_UNLOCKED_HPP
#include "guiengine/screen.hpp"
#include "utils/ptr_vector.hpp"
namespace irr { namespace scene { class ISceneNode; class ICameraSceneNode; class ILightSceneNode; } }
class KartProperties;
@ -13,12 +14,37 @@ class FeatureUnlockedCutScene : public GUIEngine::Screen, public GUIEngine::Scre
FeatureUnlockedCutScene();
/** Whichever of these is non-null decides whhat comes out of the chest */
KartProperties* m_unlocked_kart;
irr::video::ITexture* m_unlocked_thing_picture;
/** Whichever of these is non-null decides what comes out of the chest */
struct UnlockedThing
{
KartProperties* m_unlocked_kart;
irr::video::ITexture* m_picture;
/** Contains whatever is in the chest */
scene::ISceneNode* m_root_gift_node;
irr::core::stringw m_unlock_message;
UnlockedThing(KartProperties* kart, irr::core::stringw msg)
{
m_unlocked_kart = kart;
m_picture = NULL;
m_unlock_message = msg;
}
UnlockedThing(irr::video::ITexture* pict, irr::core::stringw msg)
{
m_unlocked_kart = NULL;
m_picture = pict;
m_unlock_message = msg;
}
~UnlockedThing()
{
if (m_root_gift_node != NULL) irr_driver->removeNode(m_root_gift_node);
m_root_gift_node = NULL;
}
};
ptr_vector<UnlockedThing, HOLD> m_unlocked_stuff;
/** Contains whatever is in the chest */
scene::ISceneNode* m_root_gift_node;
/** sky angle, 0-360 */
float m_sky_angle;
@ -51,10 +77,10 @@ public:
void eventCallback(GUIEngine::Widget* widget, const std::string& name, const int playerID);
/** Call before showing up the screen to make a kart come out of the chest */
void setUnlockedKart(KartProperties* unlocked_kart);
void addUnlockedKart(KartProperties* unlocked_kart, irr::core::stringw msg);
/** Call before showing up the screen to make a picture come out of the chest */
void setUnlockedPicture(irr::video::ITexture* picture);
void addUnlockedPicture(irr::video::ITexture* picture, irr::core::stringw msg);
/** override from base class to handle escape press */
virtual bool onEscapePressed();