00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <weapons/EconomyFreeMarket.h>
00022 #include <weapons/AccessoryStore.h>
00023 #include <server/ScorchedServer.h>
00024 #include <common/Defines.h>
00025 #include <common/OptionsScorched.h>
00026 #include <common/Logger.h>
00027 #include <XML/XMLFile.h>
00028 #include <XML/XMLParser.h>
00029 #include <tank/Tank.h>
00030 #include <tank/TankScore.h>
00031 #include <tank/TankAccessories.h>
00032 #include <stdlib.h>
00033
00034 REGISTER_CLASS_SOURCE(EconomyFreeMarket);
00035
00036 static std::string getEconomyFileName()
00037 {
00038 return S3D::getSettingsFile(S3D::formatStringBuffer("freemarket-%s-%i.xml",
00039 ScorchedServer::instance()->getOptionsGame().getMod(),
00040 ScorchedServer::instance()->getOptionsGame().getPortNo()));
00041 }
00042
00043 static bool validAccessory(Accessory *accessory)
00044 {
00045 return
00046 accessory->getStartingNumber() != -1 &&
00047 accessory->getMaximumNumber() != 0 &&
00048 !accessory->getAIOnly() &&
00049 !accessory->getBotOnly();
00050 }
00051
00052 EconomyFreeMarket::EconomyFreeMarket()
00053 {
00054 }
00055
00056 EconomyFreeMarket::~EconomyFreeMarket()
00057 {
00058 }
00059
00060 bool EconomyFreeMarket::loadPrices()
00061 {
00062
00063 XMLFile file;
00064 if (!file.readFile(getEconomyFileName()))
00065 {
00066 S3D::dialogMessage("EconomyFreeMarket", S3D::formatStringBuffer(
00067 "Failed to parse freemarket.xml file : %s",
00068 file.getParserError()));
00069 return false;
00070 }
00071
00072
00073 economyPrices_.clear();
00074 XMLNode *rootnode = file.getRootNode();
00075 if (rootnode)
00076 {
00077 std::list<XMLNode *> &nodes = rootnode->getChildren();
00078 std::list<XMLNode *>::iterator itor;
00079 for (itor = nodes.begin();
00080 itor != nodes.end();
00081 itor++)
00082 {
00083 XMLNode *node = *itor;
00084 XMLNode *nameNode, *buyNode;
00085 if (!node->getNamedChild("name", nameNode)) return false;
00086 if (!node->getNamedChild("buyprice", buyNode)) return false;
00087
00088 Accessory *accessory = ScorchedServer::instance()->getAccessoryStore().
00089 findByPrimaryAccessoryName(nameNode->getContent());
00090 if (accessory)
00091 {
00092
00093
00094 if (validAccessory(accessory))
00095 {
00096
00097 int price = atoi(buyNode->getContent());
00098 economyPrices_[accessory->getAccessoryId()] = price;
00099 }
00100 }
00101 }
00102 }
00103 calculatePrices();
00104
00105 return true;
00106 }
00107
00108 bool EconomyFreeMarket::savePrices()
00109 {
00110 FileLines file;
00111 file.addLine("<prices source=\"Scorched3D\">");
00112 std::map<unsigned int, int>::iterator itor;
00113 for (itor = economyPrices_.begin();
00114 itor != economyPrices_.end();
00115 itor++)
00116 {
00117 unsigned int accessoryId = itor->first;
00118 int price = itor->second;
00119
00120 Accessory *accessory =
00121 ScorchedServer::instance()->getAccessoryStore().findByAccessoryId(accessoryId);
00122 if (accessory && validAccessory(accessory))
00123 {
00124 std::string cleanName;
00125 std::string dirtyName(accessory->getName());
00126 XMLNode::removeSpecialChars(dirtyName, cleanName);
00127 file.addLine(" <accessory>");
00128 file.addLine(S3D::formatStringBuffer(" <!-- %s, original Price %i -->",
00129 cleanName.c_str(), accessory->getOriginalPrice()));
00130 file.addLine(S3D::formatStringBuffer(" <name>%s</name>", cleanName.c_str()));
00131 file.addLine(S3D::formatStringBuffer(" <buyprice>%i</buyprice>", price));
00132 file.addLine(" </accessory>");
00133 }
00134 }
00135 file.addLine("</prices>");
00136
00137 if (!file.writeFile(getEconomyFileName())) return false;
00138
00139 return true;
00140 }
00141
00142 void EconomyFreeMarket::calculatePrices()
00143 {
00144 std::map<unsigned int, int>::iterator itor;
00145 for (itor = economyPrices_.begin();
00146 itor != economyPrices_.end();
00147 itor++)
00148 {
00149 unsigned int accessoryId = itor->first;
00150 int price = itor->second;
00151
00152 Accessory *accessory =
00153 ScorchedServer::instance()->getAccessoryStore().findByAccessoryId(accessoryId);
00154 if (accessory && validAccessory(accessory))
00155 {
00156 setPrice(accessory, price);
00157 }
00158 }
00159 }
00160
00161 void EconomyFreeMarket::accessoryBought(Tank *tank,
00162 const char *accessoryName)
00163 {
00164
00165 Accessory *boughtAccessory =
00166 ScorchedServer::instance()->getAccessoryStore().
00167 findByPrimaryAccessoryName(accessoryName);
00168 DIALOG_ASSERT(boughtAccessory);
00169
00170
00171
00172
00173 std::list<Accessory *> possibleAccessories;
00174 {
00175 std::list<Accessory *> weapons =
00176 ScorchedServer::instance()->getAccessoryStore().
00177 getAllAccessories();
00178 std::list<Accessory *>::iterator itor;
00179 for (itor = weapons.begin();
00180 itor != weapons.end();
00181 itor++)
00182 {
00183 Accessory *accessory = *itor;
00184
00185 int accessoryPrice =
00186 accessory->getOriginalPrice() / accessory->getBundle();
00187 int boughtAccessoryPrice =
00188 boughtAccessory->getOriginalPrice() / accessory->getBundle();
00189 if (accessoryPrice >= int(float(boughtAccessoryPrice) * 0.33f) &&
00190 accessoryPrice <= int(float(boughtAccessoryPrice) * 3.33f) &&
00191 tank->getAccessories().accessoryAllowed(accessory, accessory->getBundle()) &&
00192 validAccessory(accessory))
00193 {
00194 possibleAccessories.push_back(accessory);
00195 }
00196 }
00197 }
00198
00199
00200 if (possibleAccessories.size() <= 1) return;
00201
00202
00203 int moneyShouldAquire = boughtAccessory->getPrice() / possibleAccessories.size();
00204
00205
00206 {
00207 std::list<Accessory *>::iterator itor;
00208 for (itor = possibleAccessories.begin();
00209 itor != possibleAccessories.end();
00210 itor++)
00211 {
00212 Accessory *accessory = (*itor);
00213
00214
00215 int moneyDidAquire = 0;
00216 if (accessory == boughtAccessory) moneyDidAquire =
00217 boughtAccessory->getPrice();
00218
00219
00220
00221 int adjustment =
00222 ScorchedServer::instance()->getOptionsGame().
00223 getFreeMarketAdjustment();
00224 int priceDiff = 0;
00225 if (moneyDidAquire < moneyShouldAquire)
00226 {
00227
00228 priceDiff = -adjustment / int(possibleAccessories.size());
00229
00230 }
00231 else if (moneyDidAquire >= moneyShouldAquire)
00232 {
00233
00234 priceDiff = int((float(adjustment) * (float(possibleAccessories.size()) - 1.0f))
00235 / float(possibleAccessories.size()));
00236 }
00237
00238
00239 std::map<unsigned int, int>::iterator findItor =
00240 economyPrices_.find(accessory->getAccessoryId());
00241 if (findItor == economyPrices_.end())
00242 {
00243 economyPrices_[accessory->getAccessoryId()] =
00244 accessory->getOriginalPrice() + priceDiff;
00245 }
00246 else
00247 {
00248 economyPrices_[accessory->getAccessoryId()] +=
00249 priceDiff;
00250 }
00251 }
00252 }
00253 }
00254
00255 void EconomyFreeMarket::setPrice(Accessory *accessory, int price)
00256 {
00257 float limit = float(accessory->getFreeMarketLimits()) / 100.0f;
00258 limit *= ScorchedServer::instance()->getOptionsGame().getFreeMarketLimits();
00259 if (limit == 0)
00260 {
00261 price = accessory->getOriginalPrice();
00262 }
00263 else
00264 {
00265
00266 if (price > int(float(accessory->getOriginalPrice()) * limit))
00267 price = int(float(accessory->getOriginalPrice()) * limit);
00268
00269 else if (price < int(float(accessory->getOriginalPrice()) / limit))
00270 price = int(float(accessory->getOriginalPrice()) / limit);
00271 }
00272 price = (price / 10) * 10;
00273
00274
00275 accessory->setPrice(price);
00276
00277
00278 int selPrice = int(float(accessory->getPrice()) /
00279 float(accessory->getBundle()) * 0.8f);
00280 selPrice = (selPrice / 10) * 10;
00281 accessory->setSellPrice(selPrice);
00282 }
00283
00284 void EconomyFreeMarket::accessorySold(Tank *tank,
00285 const char *accessoryName)
00286 {
00287
00288 }
00289