AccessoryStore.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 <XML/XMLFile.h>
00022 #include <common/Defines.h>
00023 #include <common/Logger.h>
00024 #include <weapons/AccessoryStore.h>
00025 #include <weapons/Weapon.h>
00026 #include <lang/LangResource.h>
00027 #include <math.h>
00028 #include <stdio.h>
00029 
00030 AccessoryStore::AccessoryStore() : muzzleFlash_(0)
00031 {
00032 
00033 }
00034 
00035 AccessoryStore::~AccessoryStore()
00036 {
00037 
00038 }
00039 
00040 bool AccessoryStore::parseFile(
00041         ScorchedContext &context, ProgressCounter *counter)
00042 {
00043         if (counter) counter->setNewOp(LANG_RESOURCE("LOADING_WEAPONS", "Loading Weapons"));
00044 
00045         std::string fileName = S3D::getDataFile("data/accessories.xml");
00046         clearAccessories();
00047 
00048         XMLFile file;
00049         if (!file.readFile(fileName.c_str()))
00050         {
00051                 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
00052                                           "Failed to parse \"%s\"\n%s", 
00053                                           fileName.c_str(),
00054                                           file.getParserError()));
00055                 return false;
00056         }
00057 
00058         // Check file exists
00059         if (!file.getRootNode())
00060         {
00061                 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
00062                                         "Failed to find accessory file \"%s\"",
00063                                         fileName.c_str()));
00064                 return false;           
00065         }
00066 
00067         // Itterate all of the accessories in the file
00068         int noChildren = file.getRootNode()->getChildren().size();
00069         int childCount = 0;
00070         XMLNode *currentNode = 0;
00071         while (file.getRootNode()->getNamedChild("accessory", currentNode, false))
00072         {
00073                 if (counter) counter->setNewPercentage(
00074                         float(++childCount) / float(noChildren) * 100.0f);
00075 
00076                 // Parse the accessory
00077                 AccessoryCreateContext createContext(context);
00078                 Accessory *accessory = new Accessory();
00079                 if (!accessory->parseXML(createContext, currentNode))
00080                 {
00081                         return currentNode->returnError(
00082                                 S3D::formatStringBuffer("Failed to create accessory \"%s\"",
00083                                 accessory->getName()));
00084                 }
00085 
00086                 // Check uniqueness
00087                 if (findByPrimaryAccessoryName(accessory->getName()))
00088                 {
00089                         return currentNode->returnError(
00090                                 S3D::formatStringBuffer("Accessory \"%s\" already exists",
00091                                 accessory->getName()));
00092                 }
00093 
00094                 if (!accessory->getNoBuy() &&
00095                         accessory->getMaximumNumber() != 0)
00096                 {
00097                         tabGroups_.insert(accessory->getTabGroupName());
00098                 }
00099 
00100                 // Add the accessory
00101                 accessories_.push_back(accessory);
00102 
00103                 // Add weapons to death animations, weighted by arms level
00104                 if (accessory->getAction()->getType() == AccessoryPart::AccessoryWeapon)
00105                 {
00106                         Weapon *weapon = (Weapon *) accessory->getAction();
00107                         if (0 == strcmp(accessory->getName(), "WeaponMuzzle"))
00108                         {
00109                                 muzzleFlash_ = weapon;
00110                         }
00111                         else if (0 == strcmp(accessory->getName(), "WeaponDeathAnimation"))
00112                         {
00113                                 deathAnimation_ = weapon;
00114                         }
00115                 }       
00116 
00117                 // Add to the map so references can find it
00118                 parsingNodes_[accessory->getName()] = currentNode;
00119         }
00120 
00121         if (!muzzleFlash_)
00122         {
00123                 return file.getRootNode()->returnError(
00124                         "Failed to find WeaponMuzzle weapon used for muzzle flash.");
00125         }
00126         if (!deathAnimation_)
00127         {
00128                 return file.getRootNode()->returnError(
00129                         "Failed to find WeaponDeathAnimation weapon used for tank explosions.");
00130         }
00131 
00132         // Clear mapping as it now contains invalid pointers
00133         parsingNodes_.clear();
00134         return file.getRootNode()->failChildren();
00135 }
00136 
00137 AccessoryPart *AccessoryStore::createAccessoryPart(
00138         AccessoryCreateContext &context, 
00139         Accessory *parent, XMLNode *currentNode)
00140 {
00141         XMLNode *typeNode = 0;
00142         if (!currentNode->getNamedParameter("type", typeNode)) return false;
00143 
00144         AccessoryPart *accessoryPart = 
00145                 AccessoryMetaRegistration::getNewAccessory(typeNode->getContent(), this);
00146         if (!accessoryPart)
00147         {
00148                 S3D::dialogMessage("AccessoryStore", S3D::formatStringBuffer(
00149                                                 "Failed to find accessory part type \"%s\"",
00150                                                 typeNode->getContent()));
00151                 return 0;
00152         }
00153         // Set the parent accessory
00154         accessoryPart->setParent(parent);
00155         
00156         // Tell this accessory instance to initialize its settings from
00157         // the current accessory xml definition node
00158         if (!accessoryPart->parseXML(context, currentNode)) return 0;
00159 
00160         // There should not be any children left
00161         // Any that are, are children that have not been
00162         // handled by the parse routine
00163         if (!currentNode->failChildren()) return 0;
00164         DIALOG_ASSERT(accessoryPart->getParent());
00165 
00166         // Add the accessory
00167         accessoryParts_.push_back(accessoryPart);
00168         return accessoryPart;
00169 }
00170 
00171 void AccessoryStore::sortList(std::list<Accessory *> &accList, int sortKey)
00172 {
00173         if (sortKey)
00174         {
00175                 std::vector<Accessory *> accVector;
00176                 std::list<Accessory *>::iterator itor;
00177                 for (itor = accList.begin();
00178                         itor != accList.end();
00179                         itor++)
00180                 {
00181                         accVector.push_back(*itor);
00182                 }
00183 
00184                 // Crudely sort by name or price
00185                 // stl sort method list is broken in visual c 6
00186                 // bubble sort
00187                 bool changed = true;
00188                 while (changed)
00189                 {
00190                         changed = false;
00191                         for (int i=0; i<int(accVector.size())-1; i++)
00192                         {
00193                                 bool swap = false;
00194 
00195                                 // When sorting by price, use accessory name as a
00196                                 // secondary sort key.
00197 
00198                                 if ((sortKey == SortName) ||
00199                                     (sortKey == SortPrice && accVector[i]->getPrice() == accVector[i + 1]->getPrice()))
00200                                 {
00201                                         swap = strcmp(accVector[i]->getName(), accVector[i + 1]->getName()) < 0;
00202                                 }
00203                                 else if (sortKey == SortPrice)
00204                                 {
00205                                         swap = accVector[i]->getPrice() < accVector[i + 1]->getPrice();
00206                                 }
00207 
00208                                 if (swap)
00209                                 {
00210                                         Accessory *tmp = accVector[i];
00211                                         accVector[i] = accVector[i+1];
00212                                         accVector[i+1] = tmp;
00213                                         changed = true;
00214                                         break;
00215                                 }
00216                         }
00217                 } 
00218                 
00219                 accList.clear();
00220                 for (int i=0; i<int(accVector.size()); i++)
00221                 {
00222                         accList.push_front(accVector[i]);
00223                 }
00224         }
00225         else
00226         {
00227                 std::set<Accessory *> accessorySet;
00228                 std::list<Accessory *>::iterator setItor;
00229                 for (setItor = accList.begin();
00230                         setItor != accList.end();
00231                         setItor++)
00232                 {
00233                         Accessory *accessory = *setItor;
00234                         accessorySet.insert(accessory);
00235                 }
00236 
00237                 accList.clear();
00238                 std::list<Accessory *>::iterator itor;
00239                 for (itor = accessories_.begin();
00240                         itor != accessories_.end();
00241                         itor++)
00242                 {
00243                         Accessory *accessory = *itor;
00244                         if (accessorySet.find(accessory) != accessorySet.end())
00245                         {
00246                                 accList.push_back(accessory);
00247                         }
00248                 }
00249         }
00250 }
00251 
00252 std::list<Accessory *> AccessoryStore::getAllAccessoriesByTabGroup(
00253         const char *tabgroup, int sortKey)
00254 {
00255         std::list<Accessory *> result;
00256         std::list<Accessory *>::iterator itor;
00257         for (itor = accessories_.begin();
00258                 itor != accessories_.end();
00259                 itor++)
00260         {
00261                 Accessory *accessory = (*itor);
00262                 if (0 == strcmp(tabgroup, accessory->getTabGroupName()))
00263                 {
00264                         result.push_back(*itor);
00265                 }
00266         }
00267 
00268         if (sortKey) sortList(result, sortKey);
00269         return result;
00270 }
00271 
00272 std::list<Accessory *> AccessoryStore::getAllAccessories(int sortKey)
00273 {
00274         std::list<Accessory *> result;
00275         std::list<Accessory *>::iterator itor;
00276         for (itor = accessories_.begin();
00277                 itor != accessories_.end();
00278                 itor++)
00279         {
00280                 result.push_back(*itor);
00281         }
00282 
00283         if (sortKey) sortList(result, sortKey);
00284         return result;
00285 }
00286 
00287 Weapon *AccessoryStore::getMuzzelFlash()
00288 {
00289         return muzzleFlash_;
00290 }
00291 
00292 Weapon *AccessoryStore::getDeathAnimation()
00293 {
00294         return deathAnimation_;
00295 }
00296 
00297 Accessory *AccessoryStore::findByPrimaryAccessoryName(const char *name)
00298 {
00299         std::list<Accessory *>::iterator itor;
00300         for (itor = accessories_.begin();
00301                 itor != accessories_.end();
00302                 itor++)
00303         {
00304                 Accessory *accessory = (*itor);
00305                 if (strcmp(accessory->getName(), name) == 0)
00306                 {
00307                         return accessory;
00308                 }
00309         }
00310         return 0;
00311 }
00312 
00313 Accessory *AccessoryStore::findByAccessoryId(unsigned int id)
00314 {
00315         std::list<Accessory *>::iterator itor;
00316         for (itor = accessories_.begin();
00317                 itor != accessories_.end();
00318                 itor++)
00319         {
00320                 Accessory *accessory = (*itor);
00321                 if (accessory->getAccessoryId() == id)
00322                 {
00323                         return accessory;
00324                 }
00325         }
00326         return 0;
00327 }
00328 
00329 AccessoryPart *AccessoryStore::findAccessoryPartByAccessoryId(unsigned int id, const char *type)
00330 {
00331         std::list<AccessoryPart *>::iterator itor;
00332         for (itor = accessoryParts_.begin();
00333                 itor != accessoryParts_.end();
00334                 itor++)
00335         {
00336                 AccessoryPart *accessoryPart = (*itor);
00337                 if (accessoryPart->getParent()->getAccessoryId() == id &&
00338                         0 == strcmp(accessoryPart->getAccessoryTypeName(), type))
00339                 {
00340                         return accessoryPart;
00341                 }
00342         }
00343         return 0;
00344 }
00345 
00346 AccessoryPart *AccessoryStore::findByAccessoryPartId(unsigned int id)
00347 {
00348         std::list<AccessoryPart *>::iterator itor;
00349         for (itor = accessoryParts_.begin();
00350                 itor != accessoryParts_.end();
00351                 itor++)
00352         {
00353                 AccessoryPart *accessoryPart = (*itor);
00354                 if (accessoryPart->getAccessoryPartId() == id)
00355                 {
00356                         return accessoryPart;
00357                 }
00358         }
00359         return 0;
00360 }
00361 
00362 void AccessoryStore::clearAccessories()
00363 {
00364         AccessoryPart::resetAccessoryPartIds();
00365         Accessory::resetAccessoryIds();
00366         muzzleFlash_ = 0;
00367         deathAnimation_ = 0;
00368         while (!accessories_.empty())
00369         {
00370                 Accessory *accessory = accessories_.front();
00371                 accessories_.pop_front();
00372                 delete accessory;
00373         }
00374         while (!accessoryParts_.empty())
00375         {
00376                 AccessoryPart *accessoryPart = accessoryParts_.front();
00377                 accessoryParts_.pop_front();
00378                 delete accessoryPart;
00379         }
00380 }
00381 
00382 bool AccessoryStore::writeWeapon(NetBuffer &buffer, Weapon *weapon)
00383 {
00384         return writeAccessoryPart(buffer, weapon);
00385 }
00386 
00387 Weapon *AccessoryStore::readWeapon(NetBufferReader &reader)
00388 {
00389         AccessoryPart *accessoryPart = readAccessoryPart(reader);
00390         if (accessoryPart &&
00391                 accessoryPart->getType() == AccessoryPart::AccessoryWeapon)
00392         {
00393                 return ((Weapon *) accessoryPart);
00394         }
00395         return 0;
00396 }
00397 
00398 bool AccessoryStore::writeAccessoryPart(NetBuffer &buffer, AccessoryPart *part)
00399 {
00400         if (part) buffer.addToBuffer(part->getAccessoryPartId());
00401         else buffer.addToBuffer((unsigned int) 0);
00402         return true;
00403 }
00404 
00405 AccessoryPart *AccessoryStore::readAccessoryPart(NetBufferReader &reader)
00406 {
00407         unsigned int partId;
00408         if (!reader.getFromBuffer(partId)) return 0;
00409         AccessoryPart *accessoryPart = findByAccessoryPartId(partId);
00410         if (accessoryPart &&
00411                 accessoryPart->getAccessoryPartId() == partId)
00412         {
00413                 return accessoryPart;
00414         }
00415         return 0;
00416 }
00417 
00418 bool AccessoryStore::writeEconomyToBuffer(NetBuffer &buffer)
00419 {
00420         std::list<Accessory *> accessories = getAllAccessories();
00421         buffer.addToBuffer((int) accessories.size());
00422 
00423         std::list<Accessory *>::iterator itor;
00424         for (itor = accessories.begin();
00425                 itor != accessories.end();
00426                 itor++)
00427         {
00428                 Accessory *accessory = (*itor);
00429                 buffer.addToBuffer(accessory->getAccessoryId());
00430                 buffer.addToBuffer(accessory->getPrice());
00431                 buffer.addToBuffer(accessory->getSellPrice());
00432         }
00433         return true;
00434 }
00435 
00436 bool AccessoryStore::readEconomyFromBuffer(NetBufferReader &reader)
00437 {
00438         int noAccessories = 0;
00439         if (!reader.getFromBuffer(noAccessories)) return false;
00440         for (int a=0; a<noAccessories; a++)
00441         {
00442                 unsigned int accessoryId = 0;
00443                 int price = 0, sellPrice = 0;
00444                 if (!reader.getFromBuffer(accessoryId)) return false;
00445                 if (!reader.getFromBuffer(price)) return false;
00446                 if (!reader.getFromBuffer(sellPrice)) return false;
00447 
00448                 Accessory *accessory = findByAccessoryId(accessoryId);
00449                 if (!accessory) return false;
00450                 accessory->setPrice(price);
00451                 accessory->setSellPrice(sellPrice);
00452         }
00453         return true;
00454 }

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