/* The shop is where the player can buy cards, decks... */ #include "PrecompiledHeader.h" #include #include "GameStateShop.h" #include "GameApp.h" #include "MTGDeck.h" #include "MTGPack.h" #include "Translate.h" #include "TestSuiteAI.h" #include #include "WFont.h" float GameStateShop::_x1[] = { 79, 19, 27, 103, 154, 187, 102, 144, 198, 133, 183 }; float GameStateShop::_y1[] = { 150, 194, 222, 167, 164, 156, 195, 190, 175, 220, 220 }; float GameStateShop::_x2[] = { 103, 48, 74, 135, 183, 215, 138, 181, 231, 171, 225 }; float GameStateShop::_y2[] = { 155, 179, 218, 165, 166, 155, 195, 186, 177, 225, 216 }; float GameStateShop::_x3[] = { 48, 61, 9, 96, 139, 190, 81, 146, 187, 97, 191 }; float GameStateShop::_y3[] = { 164, 205, 257, 184, 180, 170, 219, 212, 195, 251, 252 }; float GameStateShop::_x4[] = { 76, 90, 65, 131, 171, 221, 123, 187, 225, 141, 237 }; float GameStateShop::_y4[] = { 169, 188, 250, 182, 182, 168, 220, 208, 198, 259, 245 }; namespace { float kGamepadIconSize = 0.5f; std::string kOtherCardsString(": Other cards"); std::string kCreditsString("Credits: "); } BoosterDisplay::BoosterDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener, TargetChooser * tc, int nb_displayed_items) : CardDisplay(id, game, x, y, listener, tc, nb_displayed_items) { } bool BoosterDisplay::CheckUserInput(JButton key) { if (JGE_BTN_UP == key || JGE_BTN_DOWN == key) return false; return CardDisplay::CheckUserInput(key); } GameStateShop::GameStateShop(GameApp* parent) : GameState(parent, "shop") { menu = NULL; boosterDisplay = NULL; taskList = NULL; srcCards = NULL; shopMenu = NULL; bigDisplay = NULL; myCollection = NULL; packlist = NULL; pricelist = NULL; playerdata = NULL; booster = NULL; lightAlpha = 0; filterMenu = NULL; alphaChange = 0; for (int i = 0; i < SHOP_ITEMS; i++) { mPrices[i] = 0; mCounts[i] = 0; } mTouched = false; kOtherCardsString = _(kOtherCardsString); kCreditsString = _(kCreditsString); cycleCardsButton = NEW InteractiveButton(NULL, kCycleCardsButtonId, Fonts::MAIN_FONT, "New Cards", SCREEN_WIDTH_F - 80, SCREEN_HEIGHT_F - 15, JGE_BTN_PRI); showCardListButton = NEW InteractiveButton(NULL, kShowCardListButtonId, Fonts::MAIN_FONT, "Show List", SCREEN_WIDTH_F - 150, SCREEN_HEIGHT_F - 15, JGE_BTN_SEC); disablePurchase = false; } GameStateShop::~GameStateShop() { SAFE_DELETE( cycleCardsButton ); SAFE_DELETE( showCardListButton ); End(); } void GameStateShop::Create() { } void GameStateShop::Start() { menu = NULL; bListCards = false; mTouched = false; mStage = STAGE_FADE_IN; mElapsed = 0; needLoad = true; booster = NULL; srcCards = NEW WSrcUnlockedCards(0); srcCards->setElapsed(15); srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); bigSync = 0; shopMenu = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, true, &bigSync); MTGAllCards * ac = MTGCollection(); playerdata = NEW PlayerData(ac); myCollection = NEW DeckDataWrapper(playerdata->collection); pricelist = NEW PriceList("settings/prices.dat", ac); for (int i = 0; i < SHOP_SLOTS; i++) { WGuiCardDistort * dist; if (i < BOOSTER_SLOTS) dist = NEW WGuiCardDistort(NULL, true); else { dist = NEW WGuiCardDistort(srcCards, true); dist->mOffset.setOffset(i - BOOSTER_SLOTS); } dist->xy = WDistort(_x1[i], _y1[i], _x2[i], _y2[i], _x3[i], _y3[i], _x4[i], _y4[i]); shopMenu->Add(NEW WGuiButton(dist, -102, i, this)); } shopMenu->Entering(JGE_BTN_NONE); if (!bigDisplay) { bigDisplay = NEW WGuiCardImage(srcCards); bigDisplay->mOffset.Hook(&bigSync); bigDisplay->mOffset.setOffset(-BOOSTER_SLOTS); bigDisplay->setX(385); bigDisplay->setY(135); } for (int i = 0; i < 8; ++i) { std::ostringstream stream; stream << "iconspsp" << i; pspIcons[i] = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, stream.str(), RETRIEVE_MANAGE); pspIcons[i]->SetHotSpot(16, 16); } JRenderer::GetInstance()->EnableVSync(true); taskList = NULL; packlist = NEW MTGPacks(); packlist->loadAll(); load(); } string GameStateShop::descPurchase(int controlId, bool tiny) { char buffer[4096]; string name; if (controlId < BOOSTER_SLOTS) { name = mBooster[controlId].getName(); } else { MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); if (!c) return ""; name = _(c->data->getName()); } if (mInventory[controlId] <= 0) { if (tiny) sprintf(buffer, _("SOLD OUT").c_str(), name.c_str()); else sprintf(buffer, _("%s : SOLD OUT").c_str(), name.c_str()); return buffer; } if (tiny) { if (controlId < BOOSTER_SLOTS || mCounts[controlId] == 0) return name; sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]); return buffer; } switch (options[Options::ECON_DIFFICULTY].number) { case Constants::ECON_HARD: case Constants::ECON_NORMAL: if (mCounts[controlId] < 1) sprintf(buffer, _("%s").c_str(), name.c_str()); else sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]); break; default: if (mCounts[controlId] < 1) sprintf(buffer, _("%s : %i credits").c_str(), name.c_str(), mPrices[controlId]); else sprintf(buffer, _("%s (%i) : %i credits").c_str(), name.c_str(), mCounts[controlId], mPrices[controlId]); break; } return buffer; } void GameStateShop::beginPurchase(int controlId) { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MENU_FONT); mFont->SetScale(DEFAULT_MENU_FONT_SCALE); SAFE_DELETE(menu); if (mInventory[controlId] <= 0) { menu = NEW SimpleMenu(JGE::GetInstance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Sold Out").c_str()); menu->Add(-1, "Ok"); } else if (playerdata->credits - mPrices[controlId] < 0) { menu = NEW SimpleMenu(JGE::GetInstance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Not enough credits").c_str()); menu->Add(-1, "Ok"); if (options[Options::CHEATMODE].number) { menu->Add(-2, "Steal it"); } } else { char buf[512]; if (controlId < BOOSTER_SLOTS) sprintf(buf, _("Purchase Booster: %i credits").c_str(), mPrices[controlId]); else sprintf(buf, _("Purchase Card: %i credits").c_str(), mPrices[controlId]); menu = NEW SimpleMenu(JGE::GetInstance(), -145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, buf); menu->Add(controlId, "Yes"); menu->Add(-1, "No"); } } void GameStateShop::cancelCard(int controlId) { //Update prices MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0) return; //We only care about their opinion if they /can/ buy it. int price = mPrices[controlId]; int rnd; switch (options[Options::ECON_DIFFICULTY].number) { case Constants::ECON_HARD: rnd = rand() % 10; break; case Constants::ECON_EASY: rnd = rand() % 50; break; default: rnd = rand() % 25; break; } price = price - (rnd * price) / 100; if (price < pricelist->getPrice(c->getMTGId())) //filters have a tendancy to increase the price instead of lowering it! pricelist->setPrice(c->getMTGId(), price); //Prices do not immediately go down when you ignore something. return; } void GameStateShop::cancelBooster(int controlId) { return; //TODO FIXME Tie boosters into pricelist. } void GameStateShop::purchaseCard(int controlId) { MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0) return; myCollection->Add(c); int price = mPrices[controlId]; pricelist->setPrice(c->getMTGId(), price); // In case they changed their minds after cancelling. playerdata->credits -= price; //Update prices int rnd; switch (options[Options::ECON_DIFFICULTY].number) { case Constants::ECON_HARD: rnd = rand() % 50; break; case Constants::ECON_EASY: rnd = rand() % 10; break; default: rnd = rand() % 25; break; } price = price + (rnd * price) / 100; pricelist->setPrice(c->getMTGId(), price); mPrices[controlId] = pricelist->getPurchasePrice(c->getMTGId()); //Prices go up immediately. mInventory[controlId]--; updateCounts(); mTouched = true; menu->Close(); } void GameStateShop::purchaseBooster(int controlId) { if (playerdata->credits - mPrices[controlId] < 0) return; playerdata->credits -= mPrices[controlId]; mInventory[controlId]--; SAFE_DELETE(booster); deleteDisplay(); booster = NEW MTGDeck(MTGCollection()); boosterDisplay = NEW BoosterDisplay(12, NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT / 2, this, NULL, 5); mBooster[controlId].addToDeck(booster, srcCards); string sort = mBooster[controlId].getSort(); DeckDataWrapper * ddw = NEW DeckDataWrapper(booster); if (sort == "alpha") ddw->Sort(WSrcCards::SORT_ALPHA); else if (sort == "collector") ddw->Sort(WSrcCards::SORT_COLLECTOR); else ddw->Sort(WSrcCards::SORT_RARITY); for (int x = 0; x < ddw->Size(); x++) { MTGCard * c = ddw->getCard(x); for (int copies = 0; copies < ddw->count(c); ++copies) { MTGCardInstance * ci = NEW MTGCardInstance(c, NULL); boosterDisplay->AddCard(ci); subBooster.push_back(ci); } } SAFE_DELETE(ddw); myCollection->loadMatches(booster); mTouched = true; save(true); menu->Close(); } int GameStateShop::purchasePrice(int offset) { MTGCard * c = NULL; if (!pricelist || !srcCards || (c = srcCards->getCard(offset)) == NULL) return 0; float price = (float) pricelist->getPurchasePrice(c->getMTGId()); int filteradd = srcCards->Size(true); filteradd = ((filteradd - srcCards->Size()) / filteradd); switch (options[Options::ECON_DIFFICULTY].number) { case Constants::ECON_EASY: filteradd /= 2; break; case Constants::ECON_HARD: filteradd *= 2; break; default: break; } return (int) (price + price * (filteradd * srcCards->filterFee())); } void GameStateShop::updateCounts() { for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++) { MTGCard * c = srcCards->getCard(i - BOOSTER_SLOTS); if (!c) mCounts[i] = 0; else mCounts[i] = myCollection->countByName(c); } } void GameStateShop::load() { for (int i = 0; i < BOOSTER_SLOTS; i++) { mBooster[i].randomize(packlist); mInventory[i] = 1 + rand() % mBooster[i].maxInventory(); mPrices[i] = pricelist->getOtherPrice(mBooster[i].basePrice()); } for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++) { MTGCard * c = NULL; if ((c = srcCards->getCard(i - BOOSTER_SLOTS)) == NULL) { mPrices[i] = 0; mCounts[i] = 0; mInventory[i] = 0; continue; } mPrices[i] = purchasePrice(i - BOOSTER_SLOTS); mCounts[i] = myCollection->countByName(c); switch (c->getRarity()) { case Constants::RARITY_C: mInventory[i] = 2 + rand() % 8; break; case Constants::RARITY_L: mInventory[i] = 100; break; default: //We're using some non-coded rarities (S) in cards.dat. case Constants::RARITY_U: mInventory[i] = 1 + rand() % 5; break; case Constants::RARITY_R: mInventory[i] = 1 + rand() % 2; break; } } } void GameStateShop::save(bool force) { if (mTouched || force) { if (myCollection) myCollection->Rebuild(playerdata->collection); if (playerdata) playerdata->save(); if (pricelist) pricelist->save(); } mTouched = false; } void GameStateShop::End() { save(); JRenderer::GetInstance()->EnableVSync(false); mElapsed = 0; SAFE_DELETE(shopMenu); SAFE_DELETE(bigDisplay); SAFE_DELETE(srcCards); SAFE_DELETE(playerdata); SAFE_DELETE(pricelist); SAFE_DELETE(myCollection); SAFE_DELETE(booster); SAFE_DELETE(filterMenu); SAFE_DELETE(packlist); deleteDisplay(); SAFE_DELETE(menu); SAFE_DELETE(taskList); } void GameStateShop::Destroy() { } void GameStateShop::beginFilters() { if (!filterMenu) { filterMenu = NEW WGuiFilters("Ask about...", srcCards); filterMenu->setY(2); filterMenu->setHeight(SCREEN_HEIGHT - 2); } mStage = STAGE_ASK_ABOUT; filterMenu->Entering(JGE_BTN_NONE); } void GameStateShop::Update(float dt) { if (menu && menu->isClosed()) SAFE_DELETE(menu); srcCards->Update(dt); alphaChange = 25 - static_cast((float) (rand() - 1) / (RAND_MAX) * 50.0f); lightAlpha += alphaChange; if (lightAlpha < 0) lightAlpha = 0; if (lightAlpha > 50) lightAlpha = 50; if (mStage != STAGE_FADE_IN) mElapsed += dt; JButton btn; switch (mStage) { case STAGE_SHOP_PURCHASE: if (menu) menu->Update(dt); beginPurchase(mBuying); mStage = STAGE_SHOP_SHOP; break; case STAGE_SHOP_MENU: if (menu) menu->Update(dt); else { menu = NEW SimpleMenu(JGE::GetInstance(), 11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20); menu->Add(22, "Ask about..."); menu->Add(14, "Check task board"); if (options[Options::CHEATMODE].number) menu->Add(-2, "Steal 1,000 credits"); menu->Add(12, "Save & Back to Main Menu"); menu->Add(kCancelMenuID, "Cancel"); } break; case STAGE_SHOP_TASKS: if (menu) { menu->Update(dt); return; } if (taskList) { btn = mEngine->ReadButton(); taskList->Update(dt); if (taskList->getState() != TaskList::TASKS_INACTIVE) { if (btn == JGE_BTN_SEC || btn == JGE_BTN_CANCEL || btn == JGE_BTN_PREV) { taskList->End(); return; } else if (taskList->getState() == TaskList::TASKS_ACTIVE && btn == JGE_BTN_MENU) { if (!menu) { menu = NEW SimpleMenu(JGE::GetInstance(), 11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20); menu->Add(15, "Return to shop"); menu->Add(12, "Save & Back to Main Menu"); menu->Add(kCancelMenuID, "Cancel"); } } } else mStage = STAGE_SHOP_SHOP; } #ifdef TESTSUITE if ((mEngine->GetButtonClick(JGE_BTN_PRI)) && (taskList)) { taskList->passOneDay(); if (taskList->getTaskCount() < 6) { taskList->addRandomTask(); taskList->addRandomTask(); } taskList->save(); } #endif break; case STAGE_ASK_ABOUT: btn = mEngine->ReadButton(); if (menu && !menu->isClosed()) { menu->CheckUserInput(btn); menu->Update(dt); return; } if (filterMenu) { if (btn == JGE_BTN_CTRL) { needLoad = filterMenu->Finish(); filterMenu->Update(dt); return; } if (filterMenu->isFinished()) { if (needLoad) { srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); if (!srcCards->Size()) { srcCards->clearFilters(); //Repetition of check at end of filterMenu->Finish(), for the token removal srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); } load(); } mStage = STAGE_SHOP_SHOP; } else { filterMenu->CheckUserInput(btn); filterMenu->Update(dt); } return; } break; case STAGE_SHOP_SHOP: btn = mEngine->ReadButton(); if (menu && !menu->isClosed()) { menu->CheckUserInput(btn); menu->Update(dt); return; } if (btn == JGE_BTN_MENU) { if (boosterDisplay) { deleteDisplay(); return; } mStage = STAGE_SHOP_MENU; return; } else if (btn == JGE_BTN_CTRL) beginFilters(); else if (btn == JGE_BTN_NEXT) { mStage = STAGE_SHOP_TASKS; if (!taskList) taskList = NEW TaskList(); taskList->Start(); } else if (btn == JGE_BTN_PRI) { srcCards->Shuffle(); load(); } else if (btn == JGE_BTN_CANCEL) options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; else if (boosterDisplay) { if (btn == JGE_BTN_SEC) deleteDisplay(); else { boosterDisplay->CheckUserInput(btn); boosterDisplay->Update(dt); } return; } else if (btn == JGE_BTN_SEC) bListCards = !bListCards; else if (shopMenu) { if (cycleCardsButton->ButtonPressed() || showCardListButton->ButtonPressed()) { disablePurchase = true; return; } else if (btn == JGE_BTN_OK && disablePurchase) { disablePurchase = false; } else if (shopMenu->CheckUserInput(btn)) srcCards->Touch(); } if (shopMenu) shopMenu->Update(dt); break; case STAGE_FADE_IN: mParent->DoAnimation(TRANSITION_FADE_IN); mStage = STAGE_SHOP_SHOP; break; } } void GameStateShop::deleteDisplay() { vector::iterator i; for (i = subBooster.begin(); i != subBooster.end(); i++) { if (!*i) continue; delete *i; } subBooster.clear(); SAFE_DELETE(boosterDisplay); } void GameStateShop::enableButtons() { cycleCardsButton->setIsSelectionValid(true); showCardListButton->setIsSelectionValid(true); } void GameStateShop::renderButtons() { cycleCardsButton->Render(); showCardListButton->Render(); } void GameStateShop::Render() { //Erase WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); JRenderer * r = JRenderer::GetInstance(); r->ClearScreen(ARGB(0,0,0,0)); if (mStage == STAGE_FADE_IN) return; JQuadPtr mBg = WResourceManager::Instance()->RetrieveTempQuad("shop.jpg", TEXTURE_SUB_5551); if (mBg.get()) r->RenderQuad(mBg.get(), 0, 0); JQuadPtr quad = WResourceManager::Instance()->RetrieveTempQuad("shop_light.jpg", TEXTURE_SUB_5551); if (quad.get()) { r->EnableTextureFilter(false); r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); quad->SetColor(ARGB(lightAlpha,255,255,255)); r->RenderQuad(quad.get(), 0, 0); r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); r->EnableTextureFilter(true); } if (shopMenu) shopMenu->Render(); if (filterMenu && !filterMenu->isFinished()) filterMenu->Render(); else { if (boosterDisplay) boosterDisplay->Render(); else if (bigDisplay) { if (bigDisplay->mOffset.getPos() >= 0) bigDisplay->setSource(srcCards); else bigDisplay->setSource(NULL); bigDisplay->Render(); float elp = srcCards->getElapsed(); //Render the card list overlay. if (bListCards || elp > LIST_FADEIN) { int alpha = 200; if (!bListCards && elp < LIST_FADEIN + .25) { alpha = static_cast (800 * (elp - LIST_FADEIN)); } r->FillRoundRect(300, 10, 160, SHOP_SLOTS * 20 + 15, 5, ARGB(alpha,0,0,0)); alpha += 55; for (int i = 0; i < SHOP_SLOTS; i++) { if (i == shopMenu->getSelected()) mFont->SetColor(ARGB(alpha,255,255,0)); else mFont->SetColor(ARGB(alpha,255,255,255)); char buffer[512]; string s = descPurchase(i, true); sprintf(buffer, "%s", s.c_str()); float x = 310; float y = static_cast (25 + 20 * i); mFont->DrawString(buffer, x, y); } } } } //Render the info bar r->FillRect(0, SCREEN_HEIGHT - 17, SCREEN_WIDTH, 17, ARGB(128,0,0,0)); std::ostringstream stream; stream << kCreditsString << playerdata->credits; mFont->SetColor(ARGB(255,255,255,255)); mFont->DrawString(stream.str(), 5, SCREEN_HEIGHT - 14); #ifndef TOUCH_ENABLED float len = 4 + mFont->GetStringWidth(kOtherCardsString.c_str()); r->RenderQuad(pspIcons[6].get(), SCREEN_WIDTH - len - kGamepadIconSize - 10, SCREEN_HEIGHT - 8, 0, kGamepadIconSize, kGamepadIconSize); mFont->DrawString(kOtherCardsString, SCREEN_WIDTH - len, SCREEN_HEIGHT - 14); #else enableButtons(); #endif mFont->SetColor(ARGB(255,255,255,0)); mFont->DrawString(descPurchase(bigSync.getPos()).c_str(), SCREEN_WIDTH / 2, SCREEN_HEIGHT - 14, JGETEXT_CENTER); mFont->SetColor(ARGB(255,255,255,255)); if (mStage == STAGE_SHOP_TASKS && taskList) { taskList->Render(); } if (menu) menu->Render(); renderButtons(); } void GameStateShop::ButtonPressed(int controllerId, int controlId) { int sel = bigSync.getOffset(); switch (controllerId) { case -102: //Buying something... mStage = STAGE_SHOP_PURCHASE; if (menu) menu->Close(); mBuying = controlId; return; case -145: if (controlId == -1) { //Nope, don't buy. if (sel < BOOSTER_SLOTS) cancelBooster(sel); else cancelCard(sel); menu->Close(); mStage = STAGE_SHOP_SHOP; return; } if (sel > -1 && sel < SHOP_ITEMS) { if (controlId == -2) playerdata->credits += mPrices[sel]; //We stole it. if (sel < BOOSTER_SLOTS) //Clicked a booster. purchaseBooster(sel); else purchaseCard(sel); //Check if we just scored an award... if (myCollection && myCollection->totalPrice() > 10000) { GameOptionAward * goa = dynamic_cast (&options[Options::AWARD_COLLECTOR]); if (goa) goa->giveAward(); } } mStage = STAGE_SHOP_SHOP; return; } //Basic Menu. switch (controlId) { case 12: if (taskList) taskList->save(); mStage = STAGE_SHOP_SHOP; mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); save(); break; case 14: mStage = STAGE_SHOP_TASKS; if (!taskList) taskList = NEW TaskList(); taskList->Start(); break; case 15: if (taskList) taskList->End(); break; case 22: beginFilters(); break; case -2: playerdata->credits += 1000; default: mStage = STAGE_SHOP_SHOP; } menu->Close(); } void GameStateShop::OnScroll(int inXVelocity, int inYVelocity) { // we ignore magnitude since there isn't any scrolling in the shop if (abs(inXVelocity) > 200) { bool flickRight = (inXVelocity >= 0); if (flickRight) mEngine->HoldKey_NoRepeat(JGE_BTN_PRI); } } //ShopBooster ShopBooster::ShopBooster() { pack = NULL; mainSet = NULL; altSet = NULL; } string ShopBooster::getSort() { if (pack) return pack->getSort(); return ""; } ; string ShopBooster::getName() { char buffer[512]; if (!mainSet && pack) return pack->getName(); if (altSet == mainSet) altSet = NULL; if (altSet) sprintf(buffer, _("%s & %s (15 Cards)").c_str(), mainSet->id.c_str(), altSet->id.c_str()); else if (mainSet) sprintf(buffer, _("%s Booster (15 Cards)").c_str(), mainSet->id.c_str()); return buffer; } void ShopBooster::randomize(MTGPacks * packlist) { mainSet = NULL; altSet = NULL; pack = NULL; if (!setlist.size()) return; if (packlist && setlist.size() > 10) { //FIXME make these an unlockable item. int rnd = rand() % 100; if (rnd <= Constants::CHANCE_CUSTOM_PACK) { randomCustom(packlist); return; } } randomStandard(); } int ShopBooster::basePrice() { if (pack) return pack->getPrice(); else if (altSet) return Constants::PRICE_MIXED_BOOSTER; return Constants::PRICE_BOOSTER; } void ShopBooster::randomCustom(MTGPacks * packlist) { pack = packlist->randomPack(); if (pack && !pack->isUnlocked()) pack = NULL; if (!pack) randomStandard(); } void ShopBooster::randomStandard() { MTGSetInfo * si = setlist.randomSet(-1); mainSet = si; altSet = NULL; int mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; if (mSetCount < 80) { if (rand() % 100 < Constants::CHANCE_PURE_OVERRIDE) { //Chance of picking a pure pack instead. si = setlist.randomSet(-1, 80); mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; mainSet = si; } else altSet = setlist.randomSet(si->block, 80 - mSetCount); } else if (rand() % 100 < Constants::CHANCE_MIXED_OVERRIDE) //Chance of having a mixed booster anyways. altSet = setlist.randomSet(si->block); for (int attempts = 0; attempts < 10; attempts++) { //Try to prevent altSet == mainSet. if (altSet != mainSet) break; altSet = setlist.randomSet(-1, 80 - mSetCount); } if (altSet == mainSet) altSet = NULL; //Prevent "10E & 10E Booster" if (!altSet) pack = mainSet->mPack; } int ShopBooster::maxInventory() { if (altSet || pack) return 2; return 5; } void ShopBooster::addToDeck(MTGDeck * d, WSrcCards * srcCards) { if (!pack) { //A combination booster. MTGPack * mP = MTGPacks::getDefault(); if (!altSet && mainSet->mPack) mP = mainSet->mPack; char buf[512]; if (!altSet) sprintf(buf, "set:%s;", mainSet->id.c_str()); else sprintf(buf, "set:%s;|set:%s;", mainSet->id.c_str(), altSet->id.c_str()); mP->pool = buf; mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool. } else pack->assemblePack(d); } #ifdef TESTSUITE bool ShopBooster::unitTest() { //this tests the default random pack creation. MTGDeck * d = NEW MTGDeck(MTGCollection()); char result[1024]; randomStandard(); MTGPack * mP = MTGPacks::getDefault(); if(!altSet && mainSet->mPack) mP = mainSet->mPack; char buf[512]; if(!altSet) sprintf(buf,"set:%s;",mainSet->id.c_str()); else sprintf(buf,"set:%s;|set:%s;",mainSet->id.c_str(),altSet->id.c_str()); mP->pool = buf; mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool. DeckDataWrapper* ddw = NEW DeckDataWrapper(d); bool res = true; int u = 0, r = 0, s = 0; int card = 0; for(int i=0;iSize(true);i++) { MTGCard * c = ddw->getCard(i); if(!c) break; if(c->getRarity() == Constants::RARITY_R || c->getRarity() == Constants::RARITY_M) r+=ddw->count(c); else if(c->getRarity() == Constants::RARITY_U) u+=ddw->count(c); else if(c->getRarity() == Constants::RARITY_S) s+=ddw->count(c); card++; } int count = ddw->getCount(); SAFE_DELETE(ddw); SAFE_DELETE(d); //Note: When there are special cards, the count IS going to be messed up, so do not perform the check for Rare and Uncommon in that case //also see http://code.google.com/p/wagic/issues/detail?id=644 if(!s && (r != 1 || u != 3) ) { sprintf(result, "==Unexpected rarity count==
"); TestSuite::Log(result); res = false; } if(count < 14) { sprintf(result, "==Unexpected card count==
"); TestSuite::Log(result); res = false; } sprintf(result, "==Test Succesful !==
"); TestSuite::Log(result); SAFE_DELETE(ddw); SAFE_DELETE(d); return res; } #endif