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:
auria 2012-02-23 01:36:24 +00:00
parent 4e0a3b826d
commit c953803f13
25 changed files with 122 additions and 76 deletions

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="city" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="4"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="farm" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="0"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="fortmagma" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="23"/>
<hard>
<karts number="2"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="hacienda" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="3"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="islandtrack" laps="3"/>
<mode major="single" minor="followtheleader"/>
<requirements trophies="6"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="jungle" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="1"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="lighthouse" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="16"/>
<hard>
<karts number="5"/>

View File

@ -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"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="minigolf" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="20"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="olivermath" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="0"/>
<hard>
<karts number="1"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="sandtrack" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="0"/>
<hard>
<karts number="1"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="scotland" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="5"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="snowmountain" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="0"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="snowtuxpeak" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="8"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="startrack" laps="3"/>
<mode major="single" minor="followtheleader"/>
<requirements trophies="5"/>
<hard>
<karts number="6"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="subsea" laps="2"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="2"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="tuxtollway" laps="3"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="19"/>
<hard>
<karts number="5"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="xr591" laps="2"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="20"/>
<hard>
<karts number="1"/>

View File

@ -2,6 +2,7 @@
<challenge version="2">
<track id="zengarden" laps="3"/>
<mode major="single" minor="timetrial"/>
<requirements trophies="4"/>
<hard>
<karts number="2"/>

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}
};