Start refactor to turn around a bad design decision regarding challenges. Oops. Number of required trophies moved from scene.xml to .challenge file.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10885 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
4e0a3b826d
commit
c953803f13
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="city" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="4"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="farm" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="fortmagma" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="23"/>
|
||||
|
||||
<hard>
|
||||
<karts number="2"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="hacienda" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="3"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="islandtrack" laps="3"/>
|
||||
<mode major="single" minor="followtheleader"/>
|
||||
<requirements trophies="6"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="jungle" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="1"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="lighthouse" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="16"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,7 +2,8 @@
|
||||
<challenge version="2">
|
||||
<track id="mines" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
|
||||
<requirements trophies="22"/>
|
||||
|
||||
<hard>
|
||||
<karts number="4"/>
|
||||
<requirements time="175"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="minigolf" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="20"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="olivermath" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<hard>
|
||||
<karts number="1"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="sandtrack" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<hard>
|
||||
<karts number="1"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="scotland" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="5"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="snowmountain" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="snowtuxpeak" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="8"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="startrack" laps="3"/>
|
||||
<mode major="single" minor="followtheleader"/>
|
||||
<requirements trophies="5"/>
|
||||
|
||||
<hard>
|
||||
<karts number="6"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="subsea" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="2"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="tuxtollway" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="19"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="xr591" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="20"/>
|
||||
|
||||
<hard>
|
||||
<karts number="1"/>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="zengarden" laps="3"/>
|
||||
<mode major="single" minor="timetrial"/>
|
||||
<requirements trophies="4"/>
|
||||
|
||||
<hard>
|
||||
<karts number="2"/>
|
||||
|
@ -35,13 +35,14 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
throw(std::runtime_error)
|
||||
#endif
|
||||
{
|
||||
m_filename = filename;
|
||||
m_major = RaceManager::MAJOR_MODE_SINGLE;
|
||||
m_minor = RaceManager::MINOR_MODE_NORMAL_RACE;
|
||||
m_num_laps = -1;
|
||||
m_track_id = "";
|
||||
m_gp_id = "";
|
||||
m_version = 0;
|
||||
m_filename = filename;
|
||||
m_major = RaceManager::MAJOR_MODE_SINGLE;
|
||||
m_minor = RaceManager::MINOR_MODE_NORMAL_RACE;
|
||||
m_num_laps = -1;
|
||||
m_track_id = "";
|
||||
m_gp_id = "";
|
||||
m_version = 0;
|
||||
m_num_trophies = 0;
|
||||
|
||||
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++)
|
||||
{
|
||||
@ -97,6 +98,15 @@ ChallengeData::ChallengeData(const std::string& filename)
|
||||
error("laps");
|
||||
}
|
||||
|
||||
|
||||
const XMLNode* requirements_node = root->getNode("requirements");
|
||||
if (requirements_node == NULL)
|
||||
{
|
||||
throw std::runtime_error("Challenge file " + filename + " has no <requirements> node!");
|
||||
}
|
||||
requirements_node->get("trophies", &m_num_trophies);
|
||||
|
||||
|
||||
const XMLNode* mode_node = root->getNode("mode");
|
||||
if (mode_node == NULL)
|
||||
{
|
||||
|
@ -76,6 +76,9 @@ private:
|
||||
/** Features to unlock. */
|
||||
std::vector<UnlockableFeature> m_feature;
|
||||
|
||||
/** Number of trophies required to access this challenge */
|
||||
int m_num_trophies;
|
||||
|
||||
irr::core::stringw m_challenge_description;
|
||||
|
||||
public:
|
||||
@ -110,6 +113,9 @@ public:
|
||||
|
||||
int getNumLaps() const { return m_num_laps; }
|
||||
|
||||
/** get number of required trophies to start this challenge */
|
||||
int getNumTrophies() const { return m_num_trophies; }
|
||||
|
||||
void addUnlockTrackReward(const std::string &track_name);
|
||||
void addUnlockModeReward(const std::string &internal_mode_name,
|
||||
const irr::core::stringw &user_mode_name);
|
||||
|
@ -141,7 +141,7 @@ void OverWorld::onFirePressed(Controller* who)
|
||||
Vec3 kart_xyz = getKart(0)->getXYZ();
|
||||
for (unsigned int n=0; n<challenges.size(); n++)
|
||||
{
|
||||
if (challenges[n].m_force_field.m_is_locked) continue;
|
||||
if (challenges[n].getForceField().m_is_locked) continue;
|
||||
|
||||
if ((kart_xyz - Vec3(challenges[n].m_position)).length2_2d() < CHALLENGE_DISTANCE_SQUARED)
|
||||
{
|
||||
|
@ -318,7 +318,7 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
|
||||
//const ChallengeData* c = unlock_manager->getChallenge(challenges[n].m_challenge_id);
|
||||
// bool locked = (m_locked_challenges.find(c) != m_locked_challenges.end());
|
||||
int state = (challenges[n].m_force_field.m_is_locked ? LOCKED : OPEN);
|
||||
int state = (challenges[n].getForceField().m_is_locked ? LOCKED : OPEN);
|
||||
|
||||
const Challenge* c = unlock_manager->getCurrentSlot()->getChallenge(challenges[n].m_challenge_id);
|
||||
if (c->isSolved(RaceManager::RD_HARD)) state = COMPLETED_HARD;
|
||||
@ -340,7 +340,7 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
// ---- Draw nearby challenge if any
|
||||
for (unsigned int n=0; n<challenges.size(); n++)
|
||||
{
|
||||
if (challenges[n].m_force_field.m_is_locked) continue;
|
||||
if (challenges[n].getForceField().m_is_locked) continue;
|
||||
|
||||
if ((kart_xyz - Vec3(challenges[n].m_position)).length2_2d() < CHALLENGE_DISTANCE_SQUARED)
|
||||
{
|
||||
|
@ -748,53 +748,60 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
{
|
||||
if (!irr_driver->supportsSplatting()) continue;
|
||||
}
|
||||
else if (condition.find("trophies") == 0)
|
||||
{
|
||||
std::vector<std::string> split = StringUtils::split(condition, ' ');
|
||||
if (split.size() != 3)
|
||||
else if (condition == "trophies")
|
||||
{
|
||||
// Associate force fields and challenges
|
||||
// FIXME: this assumes that challenges will appear before force fields in scene.xml
|
||||
// (which however seems to be the case atm)
|
||||
int f = m_force_fields.size() - 1;
|
||||
int closest_challenge_id = -1;
|
||||
float closest_distance = 99999.0f;
|
||||
for (unsigned int c=0; c<m_challenges.size(); c++)
|
||||
{
|
||||
fprintf(stderr, "[Track] WARNING: unexpected number of tokens in '%s'\n", condition.c_str());
|
||||
|
||||
float dist = xyz.getDistanceFromSQ(m_challenges[c].m_position);
|
||||
if (closest_challenge_id == -1 || dist < closest_distance)
|
||||
{
|
||||
closest_challenge_id = c;
|
||||
closest_distance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
assert(closest_challenge_id >= 0);
|
||||
assert(closest_challenge_id < (int)m_challenges.size());
|
||||
|
||||
const ChallengeData* challenge = unlock_manager->getChallenge(m_challenges[closest_challenge_id].m_challenge_id);
|
||||
if (challenge == NULL)
|
||||
{
|
||||
fprintf(stderr, "[Track] WARNING: Cannot find challenge named '%s'\n",
|
||||
m_challenges[closest_challenge_id].m_challenge_id.c_str());
|
||||
continue;
|
||||
}
|
||||
const std::string& op = split[1];
|
||||
int val = -1;
|
||||
if (StringUtils::fromString(split[2], val))
|
||||
{
|
||||
// only 'lt' is supported atm
|
||||
if (op != "lt")
|
||||
{
|
||||
fprintf(stderr, "[Track] WARNING: operator '%s' not supported in '%s'\n", op.c_str(),
|
||||
condition.c_str());
|
||||
}
|
||||
|
||||
bool shown = (unlock_manager->getCurrentSlot()->getPoints() < val);
|
||||
|
||||
m_force_fields.push_back(OverworldForceField(xyz, shown, val));
|
||||
|
||||
core::stringw msg = StringUtils::toWString(val);
|
||||
core::dimension2d<u32> textsize = GUIEngine::getHighresDigitFont()->getDimension(msg.c_str());
|
||||
scene::ISceneManager* sm = irr_driver->getSceneManager();
|
||||
|
||||
assert(GUIEngine::getHighresDigitFont() != NULL);
|
||||
|
||||
scene::ISceneNode* sn =
|
||||
sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(),
|
||||
msg.c_str(),
|
||||
NULL,
|
||||
core::dimension2df(textsize.Width/45.0f,
|
||||
textsize.Height/45.0f),
|
||||
xyz,
|
||||
-1 /* id */,
|
||||
video::SColor(255, 255, 225, 0),
|
||||
video::SColor(255, 255, 89, 0));
|
||||
m_all_nodes.push_back(sn);
|
||||
if (!shown) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "[Track] WARNING: token '%s' in '%s' should have been a number\n",
|
||||
split[2].c_str(), condition.c_str());
|
||||
}
|
||||
|
||||
const int val = challenge->getNumTrophies();
|
||||
bool shown = (unlock_manager->getCurrentSlot()->getPoints() < val);
|
||||
m_force_fields.push_back(OverworldForceField(xyz, shown, val));
|
||||
|
||||
m_challenges[closest_challenge_id].setForceField(m_force_fields[f]);
|
||||
|
||||
core::stringw msg = StringUtils::toWString(val);
|
||||
core::dimension2d<u32> textsize = GUIEngine::getHighresDigitFont()->getDimension(msg.c_str());
|
||||
scene::ISceneManager* sm = irr_driver->getSceneManager();
|
||||
|
||||
assert(GUIEngine::getHighresDigitFont() != NULL);
|
||||
|
||||
scene::ISceneNode* sn =
|
||||
sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(),
|
||||
msg.c_str(),
|
||||
NULL,
|
||||
core::dimension2df(textsize.Width/45.0f,
|
||||
textsize.Height/45.0f),
|
||||
xyz,
|
||||
-1 /* id */,
|
||||
video::SColor(255, 255, 225, 0),
|
||||
video::SColor(255, 255, 89, 0));
|
||||
m_all_nodes.push_back(sn);
|
||||
if (!shown) continue;
|
||||
}
|
||||
else if (condition.size() > 0)
|
||||
{
|
||||
@ -968,26 +975,6 @@ bool Track::loadMainTrack(const XMLNode &root)
|
||||
|
||||
} // for i
|
||||
|
||||
// Associate force fields and challenges
|
||||
for (unsigned int c=0; c<m_challenges.size(); c++)
|
||||
{
|
||||
int closest_field_id = -1;
|
||||
float closest_distance = 99999.0f;
|
||||
for (unsigned int f=0; f<m_force_fields.size(); f++)
|
||||
{
|
||||
float dist = m_force_fields[f].m_position.getDistanceFromSQ(m_challenges[c].m_position);
|
||||
if (closest_field_id == -1 || dist < closest_distance)
|
||||
{
|
||||
closest_field_id = f;
|
||||
closest_distance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
assert(closest_field_id >= 0);
|
||||
assert(closest_field_id < (int)m_force_fields.size());
|
||||
m_challenges[c].m_force_field = m_force_fields[closest_field_id];
|
||||
}
|
||||
|
||||
// Create LOD nodes
|
||||
std::vector<LODNode*> lod_nodes;
|
||||
lodLoader.done(m_root, m_all_cached_meshes, lod_nodes);
|
||||
|
@ -83,14 +83,38 @@ struct OverworldForceField
|
||||
};
|
||||
struct OverworldChallenge
|
||||
{
|
||||
private:
|
||||
OverworldForceField m_force_field;
|
||||
bool m_force_field_set;
|
||||
public:
|
||||
|
||||
core::vector3df m_position;
|
||||
std::string m_challenge_id;
|
||||
OverworldForceField m_force_field;
|
||||
|
||||
OverworldChallenge(core::vector3df position, std::string challenge_id)
|
||||
{
|
||||
m_position = position;
|
||||
m_challenge_id = challenge_id;
|
||||
m_force_field_set = false;
|
||||
}
|
||||
|
||||
void setForceField(OverworldForceField f)
|
||||
{
|
||||
m_force_field = f;
|
||||
m_force_field_set = true;
|
||||
}
|
||||
|
||||
OverworldForceField& getForceField()
|
||||
{
|
||||
assert(m_force_field_set);
|
||||
return m_force_field;
|
||||
}
|
||||
|
||||
|
||||
const OverworldForceField& getForceField() const
|
||||
{
|
||||
assert(m_force_field_set);
|
||||
return m_force_field;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user