00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <graph/TutorialFile.h>
00022 #include <GLW/GLWWindowManager.h>
00023 #include <client/ScorchedClient.h>
00024 #include <common/OptionsTransient.h>
00025 #include <tank/TankContainer.h>
00026 #include <server/ServerCommon.h>
00027
00028 TutorialFileEntry *TutorialConditionWindowVisible::checkCondition()
00029 {
00030 GLWWindow *window =
00031 GLWWindowManager::instance()->getWindowByName(window_.c_str());
00032
00033 if (!window ||
00034 !GLWWindowManager::instance()->windowVisible(window->getId()))
00035 {
00036 return next_;
00037 }
00038 return 0;
00039 }
00040
00041 bool TutorialConditionWindowVisible::parseXML(TutorialFile *file, XMLNode *node)
00042 {
00043 std::string next;
00044 if (!node->getNamedChild("window", window_)) return false;
00045 if (!node->getNamedChild("next", next)) return false;
00046
00047 if (!(next_ = file->getEntry(next.c_str())))
00048 {
00049 return node->returnError(
00050 "Failed to find the tutorial pointed to by next");
00051 }
00052
00053 return true;
00054 }
00055
00056 TutorialFileEntry *TutorialConditionFirstMove::checkCondition()
00057 {
00058 if (ScorchedClient::instance()->getOptionsTransient().getCurrentGameNo() > 1)
00059 {
00060 return next_;
00061 }
00062 return 0;
00063 }
00064
00065 bool TutorialConditionFirstMove::parseXML(TutorialFile *file, XMLNode *node)
00066 {
00067 std::string next;
00068 if (!node->getNamedChild("next", next)) return false;
00069
00070 if (!(next_ = file->getEntry(next.c_str())))
00071 {
00072 return node->returnError(
00073 "Failed to find the tutorial pointed to by next");
00074 }
00075
00076 return true;
00077 }
00078
00079 TutorialFileEntry *TutorialConditionTankDead::checkCondition()
00080 {
00081 if (ScorchedClient::instance()->getTankContainer().getNoOfTanks() -
00082 ScorchedClient::instance()->getTankContainer().aliveCount() > 1)
00083 {
00084 ServerCommon::killAll();
00085 return next_;
00086 }
00087 return 0;
00088 }
00089
00090 bool TutorialConditionTankDead::parseXML(TutorialFile *file, XMLNode *node)
00091 {
00092 std::string next;
00093 if (!node->getNamedChild("next", next)) return false;
00094
00095 if (!(next_ = file->getEntry(next.c_str())))
00096 {
00097 return node->returnError(
00098 "Failed to find the tutorial pointed to by next");
00099 }
00100
00101 return true;
00102 }
00103
00104 TutorialCondition *TutorialCondition::create(const char *type)
00105 {
00106 if (0 == strcmp(type, "WindowVisible")) return new TutorialConditionWindowVisible;
00107 else if (0 == strcmp(type, "FirstMove")) return new TutorialConditionFirstMove;
00108 else if (0 == strcmp(type, "TankDead")) return new TutorialConditionTankDead;
00109 return 0;
00110 }
00111
00112 TutorialFileEntry *TutorialFileEntry::checkConditions()
00113 {
00114 std::list<TutorialCondition *>::iterator itor;
00115 for (itor = conditions_.begin();
00116 itor != conditions_.end();
00117 itor++)
00118 {
00119 TutorialCondition *condition = (*itor);
00120
00121 TutorialFileEntry *entry = condition->checkCondition();
00122 if (entry) return entry;
00123 }
00124 return 0;
00125 }
00126
00127 TutorialFile::TutorialFile() : file_(true)
00128 {
00129 }
00130
00131 TutorialFile::~TutorialFile()
00132 {
00133 }
00134
00135 bool TutorialFile::parseFile(const std::string &file)
00136 {
00137 if (!file_.readFile(file) ||
00138 !file_.getRootNode())
00139 {
00140 S3D::dialogMessage("Scorched Tutorial", S3D::formatStringBuffer(
00141 "Failed to parse \"%s\"\n%s",
00142 file.c_str(),
00143 file_.getParserError()));
00144 return false;
00145 }
00146
00147 XMLNode *steps = 0;
00148 if (!file_.getRootNode()->getNamedChild("steps", steps)) return false;
00149
00150
00151 std::list<std::pair<TutorialCondition *, XMLNode *> > conditions;
00152 std::list<XMLNode *>::iterator stepitor;
00153 for (stepitor = steps->getChildren().begin();
00154 stepitor != steps->getChildren().end();
00155 stepitor++)
00156 {
00157 XMLNode *node = (*stepitor);
00158
00159 if (node->getType() == XMLNode::XMLNodeType)
00160 {
00161 TutorialFileEntry *entry = new TutorialFileEntry();
00162 if (!node->getNamedChild("name", entry->name_)) return false;
00163 if (!node->getNamedChild("text", entry->text_)) return false;
00164
00165 XMLNode *conditionsNode;
00166 if (node->getNamedChild("conditions", conditionsNode, false))
00167 {
00168 XMLNode *conditionNode;
00169 while (conditionsNode->getNamedChild("condition", conditionNode, false))
00170 {
00171 std::string type;
00172 if (!conditionNode->getNamedParameter("type", type)) return false;
00173
00174
00175 TutorialCondition *condition =
00176 TutorialCondition::create(type.c_str());
00177 if (!condition) return
00178 conditionNode->returnError("Failed to find condition type");
00179 entry->conditions_.push_back(condition);
00180
00181
00182 std::pair<TutorialCondition *, XMLNode *>
00183 cond(condition, conditionNode);
00184 conditions.push_back(cond);
00185 }
00186 }
00187
00188 if (entries_.find(entry->name_) != entries_.end())
00189 {
00190 return node->returnError("Duplicate name exists in file");
00191 }
00192 entries_[entry->name_] = entry;
00193
00194 if (!node->failChildren()) return false;
00195 }
00196 }
00197
00198
00199
00200 std::list<std::pair<TutorialCondition *, XMLNode *> >::iterator conditor;
00201 for (conditor = conditions.begin();
00202 conditor != conditions.end();
00203 conditor++)
00204 {
00205 TutorialCondition *condition = (*conditor).first;
00206 XMLNode *conditionNode = (*conditor).second;
00207
00208 if (!condition->parseXML(
00209 this, conditionNode)) return false;
00210 if (!conditionNode->failChildren()) return false;
00211 }
00212
00213
00214 std::string start;
00215 if (!file_.getRootNode()->getNamedChild("start", start)) return false;
00216 start_ = getEntry(start.c_str());
00217 if (!start_)
00218 {
00219 S3D::dialogMessage("TutorialFile", "Failed to find start node");
00220 return false;
00221 }
00222
00223
00224 if (!file_.getRootNode()->failChildren()) return false;
00225 return true;
00226 }
00227
00228 TutorialFileEntry *TutorialFile::getEntry(const char *name)
00229 {
00230 std::map<std::string, TutorialFileEntry *>::iterator findItor
00231 = entries_.find(name);
00232 if (findItor == entries_.end())
00233 {
00234 return 0;
00235 }
00236 return (*findItor).second;
00237 }