#include "PrecompiledHeader.h" #include #include #include "GameApp.h" #include "Translate.h" #include "WDataSrc.h" #include "WFilter.h" #include "DeckDataWrapper.h" #include "MTGPack.h" #include "../../../JGE/src/tinyxml/tinyxml.h" MTGPack MTGPacks::defaultBooster; int MTGPackEntryRandom::addCard(WSrcCards *pool, MTGDeck *to) { int fails = 0; if (!pool) return 1; WCFilterFactory * ff = WCFilterFactory::GetInstance(); WCardFilter * oldf = pool->unhookFilters(); pool->addFilter(ff->Construct(filter)); fails = pool->addRandomCards(to, copies); pool->clearFilters(); pool->addFilter(oldf); return fails; } int MTGPackEntrySpecific::addCard(WSrcCards *pool, MTGDeck *to) { if (!card) return copies; for (int i = 0; i < copies; i++) to->add(card); return 0; } int MTGPackSlot::add(WSrcCards * ocean, MTGDeck *to, int carryover) { if (!entries.size()) return copies; int fails = 0; int amt = copies + carryover; WSrcCards * myPool = NULL; if (pool.size()) myPool = MTGPack::getPool(pool); if (!myPool) myPool = ocean; for (int i = 0; i < amt; i++) { size_t pos = rand() % entries.size(); while (pos < entries.size() && entries[pos]->addCard(myPool, to)) pos++; if (pos == entries.size()) fails++; } if (myPool != ocean) SAFE_DELETE(myPool); return fails; } WSrcCards * MTGPack::getPool(string poolstr) { WSrcCards * mySrc = NULL; size_t s = poolstr.find("all"); WCFilterFactory * ff = WCFilterFactory::GetInstance(); if (s == string::npos) { //Default to just unlocked cards mySrc = NEW WSrcUnlockedCards(); s = poolstr.find("unlocked"); string sub = poolstr; if (s != string::npos) sub = trim(poolstr.substr(s + 8)); if (sub.size()) { mySrc->addFilter(ff->Construct(sub)); mySrc->bakeFilters(); } } else { //Use everything. mySrc = NEW WSrcCards(); string sub = poolstr.substr(s + 3); if (sub.size()) { mySrc->addFilter(ff->Construct(sub)); mySrc->loadMatches(MTGCollection()); mySrc->bakeFilters(); } else mySrc->loadMatches(MTGCollection()); } mySrc->Shuffle(); return mySrc; } void MTGPackSlot::addEntry(MTGPackEntry*item) { if (item) entries.push_back(item); } int MTGPack::assemblePack(MTGDeck *to) { int carryover = 0; WSrcCards * p = getPool(pool); if (!p) return -1; p->Shuffle(); for (size_t i = 0; i < slotss.size(); i++) { carryover = slotss[i]->add(p, to, carryover); if (carryover > 0) carryover = carryover; //This means we're failing. } SAFE_DELETE(p); return carryover; } void MTGPack::countCards() { minCards = 0; maxCards = 0; for (size_t i = 0; i < slotss.size(); i++) { MTGPackSlot * ps = slotss[i]; int top = 0; int bot = 999999999; for (size_t y = 0; y < ps->entries.size(); y++) { int test = ps->entries[y]->copies * ps->copies; if (test > top) top = test; if (test < bot) bot = test; } maxCards += top; minCards += bot; } } void MTGPack::load(string filename) { //TODO Placeholder until XML format available. TiXmlDocument packfile(filename.c_str()); if (!packfile.LoadFile()) return; TiXmlHandle hDoc(&packfile); TiXmlElement * pPack; pPack = hDoc.FirstChildElement().Element(); if (!pPack) { return; } //root should be "pack" string tag = pPack->Value(); std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); if (tag != "pack") return; //After validating, handle actual loading. TiXmlElement * pSlot; const char * holder = NULL; holder = pPack->Attribute("price"); if (holder) price = atoi(holder); else price = Constants::PRICE_BOOSTER; holder = pPack->Attribute("pool"); if (holder) pool = holder; else pool = ""; holder = pPack->Attribute("type"); if (holder) { type = holder; } else type = "Booster"; holder = pPack->Attribute("name"); if (holder) name = holder; else name = "Special"; holder = pPack->Attribute("requires"); if (holder) check = holder; holder = pPack->Attribute("sort"); if (holder) sort = holder; else sort = ""; std::transform(sort.begin(), sort.end(), sort.begin(), ::tolower); for (pSlot = pPack->FirstChildElement(); pSlot != NULL; pSlot = pSlot->NextSiblingElement()) { TiXmlElement * pEntry; //Load slot. tag = pSlot->Value(); std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); if (tag != "slot") continue; MTGPackSlot * s = NEW MTGPackSlot(); slotss.push_back(s); holder = pSlot->Attribute("copies"); if (holder) s->copies = atoi(holder); else s->copies = 1; holder = pSlot->Attribute("pool"); if (holder) s->pool = holder; for (pEntry = pSlot->FirstChildElement(); pEntry != NULL; pEntry = pEntry->NextSiblingElement()) { tag = pEntry->Value(); std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); if (tag == "card") { //Load specific card MTGPackEntrySpecific * es = NEW MTGPackEntrySpecific(); holder = pEntry->Attribute("copies"); if (holder) es->copies = atoi(holder); else es->copies = 1; es->card = MTGCollection()->getCardByName(pEntry->Value()); s->addEntry(es); } else if (tag == "random_card") { //Load random card MTGPackEntryRandom * er = NEW MTGPackEntryRandom(); holder = pEntry->Attribute("copies"); if (holder) er->copies = atoi(holder); else er->copies = 1; const char * text = pEntry->GetText(); if (text) er->filter = text; s->addEntry(er); } else if (tag == "nothing") { MTGPackEntryNothing * nt = NEW MTGPackEntryNothing(); s->addEntry(nt); } } } bValid = true; countCards(); return; } MTGPackSlot::~MTGPackSlot() { for (size_t t = 0; t < entries.size(); t++) { SAFE_DELETE(entries[t]); } entries.clear(); } MTGPack::~MTGPack() { for (size_t t = 0; t < slotss.size(); t++) { SAFE_DELETE(slotss[t]); } slotss.clear(); } MTGPacks::~MTGPacks() { for (size_t t = 0; t < packs.size(); t++) { SAFE_DELETE(packs[t]); } packs.clear(); } MTGPack * MTGPacks::randomPack(int key) { if (!key) key = rand(); size_t s = packs.size(); if (!s) return NULL; return packs[key % s]; } void MTGPacks::loadAll() { DIR *mDip = opendir(JGE_GET_RES("packs/").c_str()); struct dirent *mDit; if (!mDip) return; while ((mDit = readdir(mDip))) { char myFilename[4096]; sprintf(myFilename, JGE_GET_RES("packs/%s").c_str(), mDit->d_name); if (mDit->d_name[0] == '.') continue; if (!strcmp(mDit->d_name, "default_booster.txt")) continue; MTGPack * p = NEW MTGPack(myFilename); if (!p->isValid()) { SAFE_DELETE(p); continue; } packs.push_back(p); } closedir(mDip); } string MTGPack::getName() { string n = _(name); string t = _(type); char buf[1024]; if (minCards != maxCards) sprintf(buf, "%s %s (%i-%i cards)", n.c_str(), t.c_str(), minCards, maxCards); else sprintf(buf, "%s %s (%i cards)", n.c_str(), t.c_str(), maxCards); return buf; } bool MTGPack::meetsRequirements() { bool unlocked = true; WCFilterFactory * ff = WCFilterFactory::GetInstance(); WSrcCards * myC = getPool(pool); if (!myC || myC->Size() < maxCards) unlocked = false; //Top pool lacks cards. SAFE_DELETE(myC); if (!check.size() || !unlocked) return unlocked; myC = NEW WSrcUnlockedCards(); //Requirements are independent of pool; WCardFilter * cf = ff->Construct(check); unlocked = !myC->isEmptySet(cf); //Quick check for empty set status. SAFE_DELETE(cf); //delete requirement filter SAFE_DELETE(myC); //delete pool. return unlocked; } bool MTGPack::isUnlocked() { if (unlockStatus == 0) { if (meetsRequirements()) unlockStatus = 1; else unlockStatus = -1; } return (unlockStatus > 0); } MTGPack * MTGPacks::getDefault() { if (!defaultBooster.isValid()) { defaultBooster.load(JGE_GET_RES("packs/default_booster.txt")); defaultBooster.unlockStatus = 1; if (!defaultBooster.isValid()) { MTGPackSlot * ps = NEW MTGPackSlot(); ps->copies = 1; ps->addEntry(NEW MTGPackEntryRandom("rarity:mythic;")); for (int i = 0; i < 7; i++) ps->addEntry(NEW MTGPackEntryRandom("rarity:rare;")); defaultBooster.slotss.push_back(ps); ps = NEW MTGPackSlot(); ps->copies = 3; ps->addEntry(NEW MTGPackEntryRandom("rarity:uncommon;")); defaultBooster.slotss.push_back(ps); ps = NEW MTGPackSlot(); ps->copies = 1; ps->addEntry(NEW MTGPackEntryRandom("rarity:land;&type:basic;")); defaultBooster.slotss.push_back(ps); ps = NEW MTGPackSlot(); ps->copies = 10; ps->addEntry(NEW MTGPackEntryRandom("rarity:common;")); defaultBooster.slotss.push_back(ps); defaultBooster.bValid = true; defaultBooster.unlockStatus = 1; } } return &defaultBooster; } void MTGPacks::refreshUnlocked() { for (size_t t = 0; t < packs.size(); t++) { if (packs[t]->unlockStatus < 0) packs[t]->unlockStatus = 0; } }