TutorialFile.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Parse all the steps
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                                         // Create condition
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                                         // Store this condition to be parsed later
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         // Parse the conditions afterwards, as they may point to any of the
00199         // file entries.  So all the file entries need to be constructed 1st
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         // Get the startnode
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         // Check the file has been parsed
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 }

Generated on Mon Feb 16 15:14:46 2009 for Scorched3D by  doxygen 1.5.3