TankAccessories.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 <weapons/AccessoryStore.h>
00022 #include <tank/TankModelStore.h>
00023 #include <tank/TankModelContainer.h>
00024 #include <tank/TankAccessories.h>
00025 #include <tank/TankType.h>
00026 #include <tank/Tank.h>
00027 #include <target/TargetParachute.h>
00028 #include <target/TargetShield.h>
00029 #include <target/TargetLife.h>
00030 #ifndef S3D_SERVER
00031         #include <tankgraph/TankKeyboardControlUtil.h>
00032 #endif
00033 #include <common/OptionsScorched.h>
00034 #include <common/OptionsTransient.h>
00035 #include <lang/LangResource.h>
00036 
00037 TankAccessories::TankAccessories(ScorchedContext &context) :
00038         context_(context),
00039         tankWeapon_(context),
00040         tankAuto_(context),
00041         tankBatteries_(context)
00042 {
00043 }
00044 
00045 TankAccessories::~TankAccessories()
00046 {
00047 }
00048 
00049 void TankAccessories::setTank(Tank *tank)
00050 {
00051         tank_ = tank;
00052         tankWeapon_.setTank(tank);
00053         tankAuto_.setTank(tank);
00054         tankBatteries_.setTank(tank);
00055 }
00056 
00057 void TankAccessories::newMatch()
00058 {
00059         clearAccessories();
00060 
00061         tankWeapon_.newMatch();
00062         tankAuto_.newMatch();
00063         tankBatteries_.newMatch();
00064 
00065         // Add all the accessories the tank should start with
00066         // this is the accessories from the global accessories file
00067         // and also if give all accessories is set
00068         {
00069                 std::list<Accessory *> accessories = 
00070                         context_.getAccessoryStore().getAllAccessories();
00071                 std::list<Accessory *>::iterator itor;
00072                 for (itor = accessories.begin();
00073                         itor != accessories.end();
00074                         itor++)
00075                 {
00076                         Accessory *accessory = (*itor);
00077                         if (accessory->getMaximumNumber() > 0)
00078                         {
00079                                 int startingNumber = accessory->getStartingNumber();
00080                                 if (context_.getOptionsGame().getGiveAllWeapons())
00081                                 {
00082                                         startingNumber = -1;
00083                                 }
00084 
00085                                 if (startingNumber != 0)
00086                                 {
00087                                         add_(accessory, startingNumber, true);
00088                                 }
00089                         }
00090                 }
00091         }
00092 
00093         // Add all of the accessories that come from the tank's type
00094         {
00095                 TankType *type = context_.getTankModels().getTypeByName(
00096                         tank_->getModelContainer().getTankTypeName());
00097                 std::map<Accessory *, int> accessories = type->getAccessories();
00098                 std::map<Accessory *, int>::iterator itor;
00099                 for (itor = accessories.begin();
00100                         itor != accessories.end();
00101                         itor++)
00102                 {
00103                         Accessory *accessory = (*itor).first;
00104                         int count = (*itor).second;
00105 
00106                         add_(accessory, count, true);
00107                 }
00108         }
00109 
00110         changed();
00111 }
00112 
00113 void TankAccessories::clearAccessories()
00114 {
00115         accessories_.clear();
00116 
00117         std::map<std::string, AccessoryList*>::iterator groupsItor;
00118         for (groupsItor = accessoryGroups_.begin();
00119                 groupsItor != accessoryGroups_.end();
00120                 groupsItor++)
00121         {
00122                 delete (*groupsItor).second;
00123         }
00124         accessoryGroups_.clear();
00125 
00126         std::map<AccessoryPart::AccessoryType, AccessoryList*>::iterator typesItor;
00127         for (typesItor = accessoryTypes_.begin();
00128                 typesItor != accessoryTypes_.end();
00129                 typesItor++)
00130         {
00131                 delete (*typesItor).second;
00132         }
00133         accessoryTypes_.clear();
00134 
00135 }
00136 
00137 void TankAccessories::getAllAccessories(std::list<Accessory *> &result)
00138 {
00139         std::map<Accessory *, int>::iterator itor;
00140         for (itor = accessories_.begin();
00141                 itor != accessories_.end();
00142                 itor++)
00143         {
00144                 Accessory *accessory = (*itor).first;
00145                 result.push_back(accessory);
00146         }
00147 }
00148 
00149 std::list<Accessory *> &TankAccessories::getAllAccessoriesByType(
00150         AccessoryPart::AccessoryType type)
00151 {
00152         std::map<AccessoryPart::AccessoryType, AccessoryList*>::iterator itor =
00153                 accessoryTypes_.find(type);
00154         if (itor != accessoryTypes_.end())
00155         {
00156                 return *((*itor).second);
00157         }
00158 
00159         static std::list<Accessory *> emptyList;
00160         return emptyList;
00161 }
00162 
00163 std::list<Accessory *> &TankAccessories::getAllAccessoriesByGroup(
00164         const char *groupName)
00165 {
00166         std::map<std::string, AccessoryList*>::iterator itor =
00167                 accessoryGroups_.find(groupName);
00168         if (itor != accessoryGroups_.end())
00169         {
00170                 return *((*itor).second);
00171         }
00172 
00173         static std::list<Accessory *> emptyList;
00174         return emptyList;
00175 }
00176 
00177 bool TankAccessories::canUse(Accessory *accessory)
00178 {
00179         int count = getAccessoryCount(accessory);
00180         if (count == 0) return false;
00181         if (count == -1 || count >= accessory->getUseNumber()) return true;
00182         return false;
00183 }
00184 
00185 int TankAccessories::getAccessoryCount(Accessory *accessory)
00186 {
00187         std::map<Accessory *, int>::iterator foundAccessory =
00188                 accessories_.find(accessory);
00189         int currentNumber = 0;
00190         if (foundAccessory != accessories_.end())
00191         {
00192                 currentNumber = foundAccessory->second;
00193         }
00194         return currentNumber;
00195 }
00196 
00197 bool TankAccessories::accessoryAllowed(Accessory *accessory, int count)
00198 {
00199         // Check if this tank type allows this accessory
00200         TankType *type = context_.getTankModels().getTypeByName(
00201                 tank_->getModelContainer().getTankTypeName());
00202         if (type->getAccessoryDisabled(accessory)) return false;
00203 
00204         // Check if this accessory is allowed at all
00205         if (accessory->getMaximumNumber() == 0) return false;
00206         int currentCount = getAccessoryCount(accessory);
00207         if (currentCount + count >
00208                 accessory->getMaximumNumber())
00209         {
00210                 return false;
00211         }
00212 
00213         // Check if this accessory exceeds the current arms level
00214         if (10 - accessory->getArmsLevel() > 
00215                 context_.getOptionsTransient().getArmsLevel())
00216         {
00217                 return false;
00218         }
00219 
00220         // Check if an infinite weapon is being bought twice
00221         if (currentCount == -1)
00222         {
00223                 return false;
00224         }
00225 
00226         // Check if this is an ai only weapon
00227         if (accessory->getAIOnly())
00228         {
00229                 if (!tank_->isTemp())
00230                 {
00231                         return false;
00232                 }
00233         }
00234         
00235         // Check if this is a bot only weapon
00236         if (accessory->getBotOnly())
00237         {
00238                 if(tank_->getDestinationId() != 0)
00239                 {
00240                         return false;
00241                 }
00242         }
00243 
00244         return true;
00245 }
00246 
00247 void TankAccessories::add(Accessory *accessory, int count, bool check)
00248 {
00249         add_(accessory, count, check);
00250         changed();
00251 }
00252 
00253 void TankAccessories::add_(Accessory *accessory, int count, bool check)
00254 {
00255         if (check)
00256         {
00257                 // Check if this tank is allowed this accessory
00258                 if (!accessoryAllowed(accessory, count)) return;
00259         }
00260         else
00261         {
00262                 // Check if an infinite weapon is being bought twice
00263                 if (getAccessoryCount(accessory) == -1)
00264                 {
00265                         return;
00266                 }
00267         }
00268 
00269         // Add this accessory
00270         std::map<Accessory *, int>::iterator itor = accessories_.find(accessory);
00271         if (itor == accessories_.end() || count < 0)
00272         {
00273                 accessories_[accessory] = count;
00274         }
00275         else
00276         {
00277                 accessories_[accessory] += count;
00278         }
00279 
00280         // Add to groups
00281         {
00282                 std::map<std::string, AccessoryList*>::iterator groupItor =
00283                         accessoryGroups_.find(accessory->getGroupName());
00284                 if (groupItor != accessoryGroups_.end())
00285                 {
00286                         (*groupItor).second->remove(accessory);
00287                         (*groupItor).second->push_back(accessory);
00288                 }
00289                 else
00290                 {
00291                         AccessoryList *newList = new AccessoryList();
00292                         accessoryGroups_[accessory->getGroupName()] = newList;
00293                         newList->push_back(accessory);
00294                 }
00295         }
00296 
00297         // Add to types
00298         {
00299                 std::map<AccessoryPart::AccessoryType, AccessoryList*>::iterator typeItor =
00300                         accessoryTypes_.find(accessory->getType());
00301                 if (typeItor != accessoryTypes_.end())
00302                 {
00303                         (*typeItor).second->remove(accessory);
00304                         (*typeItor).second->push_back(accessory);
00305                 }
00306                 else
00307                 {
00308                         AccessoryList *newList = new AccessoryList();
00309                         accessoryTypes_[accessory->getType()] = newList;
00310                         newList->push_back(accessory);
00311                 }
00312         }
00313 }
00314 
00315 void TankAccessories::rm(Accessory *accessory, int count)
00316 {
00317         std::map<Accessory *, int>::iterator itor = 
00318                 accessories_.find(accessory);
00319         if (itor != accessories_.end())
00320         {
00321                 if (accessories_[accessory] > 0)
00322                 {
00323                         accessories_[accessory] -= count;
00324                         if (accessories_[accessory] <= 0)
00325                         {
00326                                 accessories_.erase(accessory);
00327 
00328                                 { // Remove from groups
00329                                         std::map<std::string, AccessoryList*>::iterator groupItor =
00330                                                 accessoryGroups_.find(accessory->getGroupName());
00331                                         if (groupItor != accessoryGroups_.end())
00332                                         {
00333                                                 (*groupItor).second->remove(accessory);
00334                                         }
00335                                 }
00336                                 { // Remove from types
00337                                         std::map<AccessoryPart::AccessoryType, AccessoryList*>::iterator typeItor =
00338                                                 accessoryTypes_.find(accessory->getType());
00339                                         if (typeItor != accessoryTypes_.end())
00340                                         {
00341                                                 (*typeItor).second->remove(accessory);
00342                                         }
00343                                 }
00344                         }
00345                 }
00346         }
00347 
00348         changed();
00349 }
00350 
00351 LangString TankAccessories::getAccessoryCountString(Accessory *accessory)
00352 {
00353         int count = getAccessoryCount(accessory);
00354         LangString buffer;
00355         if (count >= 0)
00356         {
00357                 buffer.append(LANG_STRING(S3D::formatStringBuffer("%i", count)));
00358         }
00359         else
00360         {
00361                 LANG_RESOURCE_VAR(INF, "INF", "In");
00362                 buffer.append(INF);
00363         }
00364 
00365         return buffer;
00366 }
00367 
00368 LangString TankAccessories::getAccessoryAndCountString(Accessory *accessory)
00369 {
00370         int count = getAccessoryCount(accessory);
00371         LangString buffer;
00372         buffer.append(LANG_RESOURCE(accessory->getName(), accessory->getName())).
00373                 append(LANG_STRING(" ("));
00374         buffer.append(getAccessoryCountString(accessory));
00375         buffer.append(LANG_STRING(")"));
00376 
00377         return buffer;
00378 }
00379 
00380 void TankAccessories::changed()
00381 {
00382         // Tell the appropriate container that the count has changed
00383         tankAuto_.changed();
00384         tankWeapon_.changed();
00385         tankBatteries_.changed();
00386 }
00387 
00388 bool TankAccessories::writeMessage(NetBuffer &buffer, bool writeAccessories)
00389 {
00390         // Send the fact we are not sending any accessories
00391         if (!writeAccessories)
00392         {
00393                 buffer.addToBuffer((int) -1);
00394                 return true;
00395         }
00396 
00397         // Write accessories in partid order
00398         std::map<unsigned int, int> ordered;
00399         std::map<unsigned int, int>::iterator itor2;
00400         std::map<Accessory *, int>::iterator itor;
00401         for (itor = accessories_.begin();
00402                 itor != accessories_.end();
00403                 itor++)
00404         {
00405                 ordered[itor->first->getAccessoryId()] = itor->second;
00406         }
00407 
00408         // Add all the accessories that are sent to the client
00409         buffer.addToBuffer((int) ordered.size());
00410         for (itor2 = ordered.begin();
00411                 itor2 != ordered.end();
00412                 itor2++)
00413         {
00414                 buffer.addToBuffer(itor2->first);
00415                 buffer.addToBuffer(itor2->second);
00416         }
00417 
00418         return true;
00419 }
00420 
00421 bool TankAccessories::readMessage(NetBufferReader &reader)
00422 {
00423         int totalAccessories = 0;
00424         if (!reader.getFromBuffer(totalAccessories)) return false;
00425 
00426         // Check if we've been sent any accessories, if not return
00427         if (totalAccessories == -1) 
00428         {
00429                 return true;
00430         }
00431 
00432         // Clear all the current accessories
00433         clearAccessories();
00434 
00435         // Check all the servers accessories exist
00436         for (int w=0; w<totalAccessories; w++)
00437         {
00438                 unsigned int accessoryId = 0;
00439                 int accessoryCount = 0;
00440                 if (!reader.getFromBuffer(accessoryId)) return false;
00441                 if (!reader.getFromBuffer(accessoryCount)) return false;
00442 
00443                 Accessory *accessory = 
00444                         context_.getAccessoryStore().findByAccessoryId(accessoryId);
00445                 if (!accessory)
00446                 {
00447                         return false;
00448                 }
00449 
00450                 add_(accessory, accessoryCount, false);
00451         }
00452 
00453         changed();
00454         return true;
00455 }
00456 
00457 void TankAccessories::activate(Accessory *accessory)
00458 {
00459         DIALOG_ASSERT(!context_.getServerMode());
00460 
00461 #ifndef S3D_SERVER
00462         switch (accessory->getType())
00463         {
00464         case AccessoryPart::AccessoryParachute:
00465                 TankKeyboardControlUtil::parachutesUpDown(
00466                         tank_,
00467                         (tank_->getParachute().getCurrentParachute()==accessory)?
00468                         0:accessory->getAccessoryId());
00469                 break;
00470         case AccessoryPart::AccessoryShield:
00471                 TankKeyboardControlUtil::shieldsUpDown(
00472                         tank_,
00473                         (tank_->getShield().getCurrentShield()==accessory)?
00474                         0:accessory->getAccessoryId());
00475                 break;
00476         case AccessoryPart::AccessoryWeapon:
00477                 getWeapons().setWeapon(accessory);
00478                 break;
00479         case AccessoryPart::AccessoryBattery:
00480                 if (tank_->getLife().getLife() < 
00481                         tank_->getLife().getMaxLife())
00482                 {
00483                         TankKeyboardControlUtil::useBattery(
00484                                 tank_, accessory->getAccessoryId());
00485                 }
00486                 break;
00487         case AccessoryPart::AccessoryAutoDefense:
00488                 default:
00489                 break;
00490         }
00491 #endif
00492 }

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