00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "../cl_shared.h"
00028 #include "../ui/ui_main.h"
00029 #include "../ui/ui_popup.h"
00030 #include "../cl_inventory.h"
00031 #include "cp_campaign.h"
00032 #include "cp_market.h"
00033 #include "cp_market_callbacks.h"
00034 #include "save/save_market.h"
00035
00036 void BS_AddItemToMarket (const objDef_t *od, int amount)
00037 {
00038 assert(amount >= 0);
00039 ccs.eMarket.numItems[od->idx] += amount;
00040 }
00041
00042 void BS_RemoveItemFromMarket (const objDef_t *od, int amount)
00043 {
00044 assert(amount >= 0);
00045 ccs.eMarket.numItems[od->idx] -= amount;
00046 if (ccs.eMarket.numItems[od->idx] < 0)
00047 ccs.eMarket.numItems[od->idx] = 0;
00048 }
00049
00050 void BS_AddAircraftToMarket (const aircraft_t *aircraft, int amount)
00051 {
00052 const humanAircraftType_t type = Com_DropShipShortNameToID(aircraft->id);
00053 assert(amount >= 0);
00054 assert(aircraft->type != AIRCRAFT_UFO);
00055 ccs.eMarket.numAircraft[type] += amount;
00056 }
00057
00058 void BS_RemoveAircraftFromMarket (const aircraft_t *aircraft, int amount)
00059 {
00060 const humanAircraftType_t type = Com_DropShipShortNameToID(aircraft->id);
00061 assert(amount >= 0);
00062 assert(aircraft->type != AIRCRAFT_UFO);
00063 ccs.eMarket.numAircraft[type] -= amount;
00064 if (ccs.eMarket.numAircraft[type] < 0)
00065 ccs.eMarket.numAircraft[type] = 0;
00066 }
00067
00073 int BS_GetAircraftOnMarket (const aircraft_t *aircraft)
00074 {
00075 const humanAircraftType_t type = Com_DropShipShortNameToID(aircraft->id);
00076 assert(aircraft->type != AIRCRAFT_UFO);
00077 return ccs.eMarket.numAircraft[type];
00078 }
00079
00085 int BS_GetAircraftSellingPrice (const aircraft_t *aircraft)
00086 {
00087 const humanAircraftType_t type = Com_DropShipShortNameToID(aircraft->id);
00088 assert(aircraft->type != AIRCRAFT_UFO);
00089 return ccs.eMarket.bidAircraft[type];
00090 }
00091
00097 int BS_GetAircraftBuyingPrice (const aircraft_t *aircraft)
00098 {
00099 const humanAircraftType_t type = Com_DropShipShortNameToID(aircraft->id);
00100 assert(aircraft->type != AIRCRAFT_UFO);
00101 return ccs.eMarket.askAircraft[type];
00102 }
00103
00109 int BS_GetItemSellingPrice (const objDef_t *od)
00110 {
00111 return ccs.eMarket.bidItems[od->idx];
00112 }
00113
00119 int BS_GetItemBuyingPrice (const objDef_t *od)
00120 {
00121 return ccs.eMarket.askItems[od->idx];
00122 }
00123
00130 qboolean BS_CheckAndDoBuyItem (base_t* base, const objDef_t *item, int number)
00131 {
00132 int numItems;
00133 const int price = BS_GetItemBuyingPrice(item);
00134
00135 assert(base);
00136
00137
00138 numItems = min(number, ccs.eMarket.numItems[item->idx]);
00139
00140
00142 if (price)
00143 numItems = min(numItems, ccs.credits / price);
00144 if (numItems <= 0)
00145 return qfalse;
00146
00147
00149 if (item->size)
00150 numItems = min(numItems, (base->capacities[CAP_ITEMS].max - base->capacities[CAP_ITEMS].cur) / item->size);
00151
00152
00153 if (numItems <= 0) {
00154 UI_Popup(_("Not enough storage space"), _("You cannot buy this item.\nNot enough space in storage.\nBuild more storage facilities."));
00155 return qfalse;
00156 }
00157
00158 B_UpdateStorageAndCapacity(base, item, numItems, qfalse, qfalse);
00159 BS_RemoveItemFromMarket(item, numItems);
00160 CL_UpdateCredits(ccs.credits - price * numItems);
00161 return qtrue;
00162 }
00163
00164
00169 void BS_ProcessCraftItemSale (const objDef_t *craftitem, const int numItems)
00170 {
00171 if (craftitem) {
00172 BS_AddItemToMarket(craftitem, numItems);
00173 CL_UpdateCredits(ccs.credits + BS_GetItemSellingPrice(craftitem) * numItems);
00174 }
00175 }
00176
00183 qboolean BS_SaveXML (mxml_node_t *parent)
00184 {
00185 int i;
00186 mxml_node_t *node;
00187
00188 node = mxml_AddNode(parent, SAVE_MARKET_MARKET);
00189 for (i = 0; i < csi.numODs; i++) {
00190 const objDef_t *od = INVSH_GetItemByIDX(i);
00191 if (BS_IsOnMarket(od)) {
00192 mxml_node_t * snode = mxml_AddNode(node, SAVE_MARKET_ITEM);
00193 mxml_AddString(snode, SAVE_MARKET_ID, od->id);
00194 mxml_AddIntValue(snode, SAVE_MARKET_NUM, ccs.eMarket.numItems[i]);
00195 mxml_AddIntValue(snode, SAVE_MARKET_BID, ccs.eMarket.bidItems[i]);
00196 mxml_AddIntValue(snode, SAVE_MARKET_ASK, ccs.eMarket.askItems[i]);
00197 mxml_AddDoubleValue(snode, SAVE_MARKET_EVO, ccs.eMarket.currentEvolutionItems[i]);
00198 mxml_AddBoolValue(snode, SAVE_MARKET_AUTOSELL, ccs.eMarket.autosell[i]);
00199 }
00200 }
00201 for (i = 0; i < AIRCRAFTTYPE_MAX; i++) {
00202 market_t *market = &ccs.eMarket;
00203 if (market->bidAircraft[i] > 0 || market->askAircraft[i] > 0) {
00204 mxml_node_t * snode = mxml_AddNode(node, SAVE_MARKET_AIRCRAFT);
00205 mxml_AddString(snode, SAVE_MARKET_ID, Com_DropShipTypeToShortName(i));
00206 mxml_AddIntValue(snode, SAVE_MARKET_NUM, market->numAircraft[i]);
00207 mxml_AddIntValue(snode, SAVE_MARKET_BID, market->bidAircraft[i]);
00208 mxml_AddIntValue(snode, SAVE_MARKET_ASK, market->askAircraft[i]);
00209 mxml_AddDoubleValue(snode, SAVE_MARKET_EVO, market->currentEvolutionAircraft[i]);
00210 }
00211 }
00212 return qtrue;
00213 }
00214
00221 qboolean BS_LoadXML (mxml_node_t *parent)
00222 {
00223 mxml_node_t *node, *snode;
00224 node = mxml_GetNode(parent, SAVE_MARKET_MARKET);
00225
00226 if (!node)
00227 return qfalse;
00228
00229 for (snode = mxml_GetNode(node, SAVE_MARKET_ITEM); snode; snode = mxml_GetNextNode(snode, node, SAVE_MARKET_ITEM)) {
00230 const char *s = mxml_GetString(snode, SAVE_MARKET_ID);
00231 const objDef_t *od = INVSH_GetItemByID(s);
00232
00233 if (!od) {
00234 Com_Printf("BS_LoadXML: Could not find item '%s'\n", s);
00235 continue;
00236 }
00237
00238 ccs.eMarket.numItems[od->idx] = mxml_GetInt(snode, SAVE_MARKET_NUM, 0);
00239 ccs.eMarket.bidItems[od->idx] = mxml_GetInt(snode, SAVE_MARKET_BID, 0);
00240 ccs.eMarket.askItems[od->idx] = mxml_GetInt(snode, SAVE_MARKET_ASK, 0);
00241 ccs.eMarket.currentEvolutionItems[od->idx] = mxml_GetDouble(snode, SAVE_MARKET_EVO, 0.0);
00242 ccs.eMarket.autosell[od->idx] = mxml_GetBool(snode, SAVE_MARKET_AUTOSELL, qfalse);
00243 }
00244 for (snode = mxml_GetNode(node, SAVE_MARKET_AIRCRAFT); snode; snode = mxml_GetNextNode(snode, node, SAVE_MARKET_AIRCRAFT)) {
00245 const char *s = mxml_GetString(snode, SAVE_MARKET_ID);
00246 humanAircraftType_t type = Com_DropShipShortNameToID(s);
00247
00248 ccs.eMarket.numAircraft[type] = mxml_GetInt(snode, SAVE_MARKET_NUM, 0);
00249 ccs.eMarket.bidAircraft[type] = mxml_GetInt(snode, SAVE_MARKET_BID, 0);
00250 ccs.eMarket.askAircraft[type] = mxml_GetInt(snode, SAVE_MARKET_ASK, 0);
00251 ccs.eMarket.currentEvolutionAircraft[type] = mxml_GetDouble(snode, SAVE_MARKET_EVO, 0.0);
00252 }
00253
00254 return qtrue;
00255 }
00256
00264 void BS_InitMarket (void)
00265 {
00266 int i;
00267 campaign_t *campaign = ccs.curCampaign;
00268 market_t *market = &ccs.eMarket;
00269
00270
00271 campaign->marketDef = INV_GetEquipmentDefinitionByID(campaign->market);
00272 campaign->asymptoticMarketDef = INV_GetEquipmentDefinitionByID(campaign->asymptoticMarket);
00273
00274 for (i = 0; i < csi.numODs; i++) {
00275 const objDef_t *od = INVSH_GetItemByIDX(i);
00276 if (market->askItems[i] == 0) {
00277 market->askItems[i] = od->price;
00278 market->bidItems[i] = floor(market->askItems[i] * BID_FACTOR);
00279 }
00280
00281 if (campaign->marketDef->numItems[i] <= 0)
00282 continue;
00283
00284 if (RS_IsResearched_ptr(RS_GetTechForItem(od))) {
00285
00286 market->numItems[i] = campaign->marketDef->numItems[i];
00287 } else {
00288 Com_Printf("BS_InitMarket: Could not add item %s to the market - not marked as researched in campaign %s\n",
00289 od->id, campaign->id);
00290 }
00291 }
00292
00293 for (i = 0; i < AIRCRAFTTYPE_MAX; i++) {
00294 const char* name = Com_DropShipTypeToShortName(i);
00295 const aircraft_t *aircraft = AIR_GetAircraft(name);
00296 if (market->askAircraft[i] == 0) {
00297 market->askAircraft[i] = aircraft->price;
00298 market->bidAircraft[i] = floor(market->askAircraft[i] * BID_FACTOR);
00299 }
00300
00301 if (campaign->marketDef->numAircraft[i] <= 0)
00302 continue;
00303
00304 if (RS_IsResearched_ptr(aircraft->tech)) {
00305
00306 market->numAircraft[i] = campaign->marketDef->numAircraft[i];
00307 } else {
00308 Com_Printf("BS_InitMarket: Could not add aircraft %s to the market - not marked as researched in campaign %s\n",
00309 aircraft->id, campaign->id);
00310 }
00311 }
00312 }
00313
00321 void CL_CampaignRunMarket (void)
00322 {
00323 int i;
00324 campaign_t *campaign = ccs.curCampaign;
00325 const float TYPICAL_TIME = 10.f;
00326 const int RESEARCH_LIMIT_DELAY = 30;
00329 assert(campaign->marketDef);
00330 assert(campaign->asymptoticMarketDef);
00331
00332 for (i = 0; i < csi.numODs; i++) {
00333 const objDef_t *od = INVSH_GetItemByIDX(i);
00334 const technology_t *tech = RS_GetTechForItem(od);
00335 int asymptoticNumber;
00336
00337 if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numItems[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) {
00338
00339
00340
00341 asymptoticNumber = campaign->asymptoticMarketDef->numItems[i] ? campaign->asymptoticMarketDef->numItems[i] : campaign->marketDef->numItems[i];
00342 } else {
00343
00344 asymptoticNumber = 0;
00345 }
00346
00347
00348 ccs.eMarket.currentEvolutionItems[i] += (asymptoticNumber - ccs.eMarket.numItems[i]) / TYPICAL_TIME;
00349
00350
00351 if (fabs(ccs.eMarket.currentEvolutionItems[i]) >= 1.0f) {
00352 const int num = (int)(ccs.eMarket.currentEvolutionItems[i]);
00353 if (num >= 0)
00354 BS_AddItemToMarket(od, num);
00355 else
00356 BS_RemoveItemFromMarket(od, -num);
00357 ccs.eMarket.currentEvolutionItems[i] -= num;
00358 }
00359 }
00360
00361 for (i = 0; i < AIRCRAFTTYPE_MAX; i++) {
00362 const humanAircraftType_t type = i;
00363 const char *aircraftID = Com_DropShipTypeToShortName(type);
00364 const aircraft_t* aircraft = AIR_GetAircraft(aircraftID);
00365 const technology_t *tech = aircraft->tech;
00366 int asymptoticNumber;
00367
00368 if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numAircraft[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) {
00369
00370
00371
00372 asymptoticNumber = campaign->asymptoticMarketDef->numAircraft[i] ? campaign->asymptoticMarketDef->numAircraft[i] : campaign->marketDef->numAircraft[i];
00373 } else {
00374
00375 asymptoticNumber = 0;
00376 }
00377
00378 ccs.eMarket.currentEvolutionAircraft[i] += (asymptoticNumber - ccs.eMarket.numAircraft[i]) / TYPICAL_TIME;
00379
00380
00381 if (fabs(ccs.eMarket.currentEvolutionAircraft[i]) >= 1.0f) {
00382 const int num = (int)(ccs.eMarket.currentEvolutionAircraft[i]);
00383 if (num >= 0)
00384 BS_AddAircraftToMarket(aircraft, num);
00385 else
00386 BS_RemoveAircraftFromMarket(aircraft, -num);
00387 ccs.eMarket.currentEvolutionAircraft[i] -= num;
00388 }
00389 }
00390 }
00391
00397 qboolean BS_IsOnMarket (const objDef_t const* item)
00398 {
00399 assert(item);
00400 return !(item->isVirtual || item->notOnMarket);
00401 }
00402
00408 qboolean BS_BuySellAllowed (const base_t* base)
00409 {
00410 if (base->baseStatus != BASE_UNDER_ATTACK
00411 && B_GetBuildingStatus(base, B_STORAGE)) {
00412 return qtrue;
00413 } else {
00414 return qfalse;
00415 }
00416 }
00417