Files
wagic/projects/mtg/src/WDataSrc.cpp
Anthony Calosa 458731778d add options show tokens
you can display tokens in editor (show tokens and choose 0 manacost) but
you can't add them, useful for tracking missing images...
2017-02-27 21:50:15 +08:00

712 lines
17 KiB
C++

#include "PrecompiledHeader.h"
#include "OptionItem.h"
#include "PlayerData.h"
#include "Translate.h"
#include "PriceList.h"
#include "Subtypes.h"
//WSyncable
bool WSyncable::Hook(WSyncable* s)
{
if (hooked) return false;
hooked = s;
return true;
}
int WSyncable::getPos()
{
if (hooked) return hooked->getPos() + currentPos;
return currentPos;
}
bool WSyncable::next()
{
if (hooked) return hooked->next();
++currentPos;
return true;
}
bool WSyncable::prev()
{
if (hooked) return hooked->prev();
--currentPos;
return true;
}
//WSrcImage
JQuadPtr WSrcImage::getImage(int)
{
return WResourceManager::Instance()->RetrieveTempQuad(filename);
}
WSrcImage::WSrcImage(string s)
{
filename = s;
}
//WSrcCards
WSrcCards::WSrcCards(float delay)
{
mDelay = delay;
mLastInput = 0;
currentPos = 0;
filtersRoot = NULL;
}
JQuadPtr WSrcCards::getImage(int offset)
{
if (!WResourceManager::Instance()->IsThreaded())
{
if (mDelay && mLastInput < mDelay)
{
return WResourceManager::Instance()->RetrieveCard(getCard(offset), RETRIEVE_EXISTING);
}
}
return WResourceManager::Instance()->RetrieveCard(getCard(offset));
}
JQuadPtr WSrcCards::getThumb(int offset)
{
return WResourceManager::Instance()->RetrieveCard(getCard(offset), RETRIEVE_THUMB);
}
WSrcCards::~WSrcCards()
{
clearFilters();
cards.clear();
}
void WSrcCards::bakeFilters()
{
vector<MTGCard*> temp;
setOffset(0);
for (int t = 0; t < Size(); t++)
{
temp.push_back(getCard(t));
}
setOffset(0);
cards.clear();
cards.swap(temp);
clearFilters();
return;
}
bool WSrcCards::matchesFilters(MTGCard * c)
{
if (!c) return false;
if (!filtersRoot) return true;
return filtersRoot->isMatch(c);
}
int WSrcCards::Size(bool all)
{
if (!all && filtersRoot) return (int) validated.size();
return (int) cards.size();
}
MTGCard * WSrcCards::getCard(int offset, bool ignore)
{
int oldpos;
int size = (int) cards.size();
MTGCard * c = NULL;
if (!ignore && filtersRoot) size = (int) validated.size();
if (!size) return NULL;
oldpos = currentPos;
if (offset != 0) currentPos += offset;
while (currentPos < 0)
currentPos = size + currentPos;
currentPos = currentPos % size;
if (!ignore && filtersRoot)
c = cards[validated[currentPos]];
else
c = cards[currentPos];
currentPos = oldpos;
return c;
}
int WSrcCards::loadMatches(MTGAllCards* ac)
{
map<int, MTGCard *>::iterator it;
int count = 0;
if (!ac) return count;
for (it = ac->collection.begin(); it != ac->collection.end(); it++)
{
if (it->second && (matchesFilters(it->second)))
{
cards.push_back(it->second);
count++;
}
}
validate();
return count;
}
int WSrcCards::loadMatches(MTGDeck * deck)
{
map<int, int>::iterator it;
int count = 0;
if (!deck) return count;
for (it = deck->cards.begin(); it != deck->cards.end(); it++)
{
MTGCard * c = deck->getCardById(it->first);
if (c && (matchesFilters(c)))
{
cards.push_back(c);
count++;
}
}
validate();
return count;
}
int WSrcCards::loadMatches(WSrcCards* src, bool all)
{
int count = 0;
if (!src) return count;
MTGCard * c = NULL;
int oldp = src->getOffset();
src->setOffset(0);
for (int t = 0; t < src->Size(all); t++)
{
c = src->getCard(t, all);
if (matchesFilters(c))
{
cards.push_back(c);
count++;
}
}
src->setOffset(oldp);
validate();
return count;
}
int WSrcCards::addRandomCards(MTGDeck * i, int howmany)
{
if (!cards.size() || (filtersRoot && !validated.size())) return howmany;
for (int x = 0; x < howmany; x++)
{
if (validated.size())
{
size_t pos = rand() % validated.size();
MTGCard * c = cards[validated[pos]];
i->add(c);
}
else
{
size_t pos = rand() % cards.size();
i->add(cards[pos]);
}
}
return 0;
}
int WSrcCards::addToDeck(MTGDeck * i, int num)
{
int oldpos = getOffset();
int added = 0;
int cycles = 0;
if (!i)
{
if (num < 0) return 0;
return num;
}
setOffset(0);
if (num < 0)
{ //Add it all;
MTGCard * c;
for (;;)
{
c = getCard();
if (!c || !next()) break;
i->add(c);
}
}
else
while (added < num)
{
MTGCard * c = getCard();
if (!next() || !c)
{
if (++cycles == WSrcCards::MAX_CYCLES)
{ //Abort the search, too many cycles.
setOffset(oldpos);
return num - added;
}
setOffset(0);
continue;
}
else
{
i->add(c);
added++;
}
}
setOffset(oldpos);
return 0;
}
bool WSrcCards::next()
{
int size = (int) cards.size();
if (filtersRoot) size = (int) validated.size();
if (currentPos + 1 >= size) return false;
currentPos++;
return true;
}
bool WSrcCards::prev()
{
if (currentPos == 0) return false;
currentPos--;
return true;
}
bool WSrcCards::setOffset(int pos)
{
if (pos < 0 || pos >= (int) cards.size()) return false;
currentPos = pos;
if (!matchesFilters(cards[currentPos])) return next();
return true;
}
void WSrcCards::Shuffle()
{
std::random_shuffle(cards.begin(), cards.end());
validate();
}
void WSrcCards::validate()
{
validated.clear();
updateCounts();
if (!filtersRoot) return;
for (size_t t = 0; t < cards.size(); t++)
{
if(!options[Options::SHOWTOKENS].number)
{//don't add tokens or negative id
if (matchesFilters(cards[t]) && (cards[t]->getId() > 0) && (cards[t]->getRarity() != Constants::RARITY_T)) validated.push_back(t);
}
else
{//show but you cant add
if (matchesFilters(cards[t])) validated.push_back(t);
}
}
}
bool WSrcCards::thisCard(int mtgid)
{
for (size_t t = 0; t < cards.size(); t++)
{
if (cards[t] && cards[t]->getId() == mtgid)
{
currentPos = (int) t;
return matchesFilters(cards[currentPos]);
}
}
return false;
}
bool WSrcCards::isEmptySet(WCardFilter * f)
{
size_t max = cards.size();
if (validated.size()) max = validated.size();
if (!f) return (max > 0);
for (size_t t = 0; t < max; t++)
{
if (validated.size())
{
if (f->isMatch(cards[validated[t]])) return false;
}
else if (f->isMatch(cards[t])) return false;
}
return true;
}
void WSrcCards::addFilter(WCardFilter * f)
{
if (filtersRoot == NULL)
filtersRoot = f;
else
filtersRoot = NEW WCFilterAND(f, filtersRoot);
validate();
currentPos = 0;
}
float WSrcCards::filterFee()
{
if (filtersRoot) return filtersRoot->filterFee();
return 0;
}
void WSrcCards::clearFilters()
{
SAFE_DELETE(filtersRoot);
validated.clear();
}
WCardFilter* WSrcCards::unhookFilters()
{
WCardFilter* temp = filtersRoot;
filtersRoot = NULL;
clearFilters();
return temp;
}
void WSrcCards::Sort(int method)
{
switch (method)
{
case WSrcCards::SORT_COLLECTOR:
std::sort(cards.begin(), cards.end(), WCSortCollector());
break;
case WSrcCards::SORT_RARITY:
std::sort(cards.begin(), cards.end(), WCSortRarity());
break;
case WSrcCards::SORT_ALPHA:
default:
std::sort(cards.begin(), cards.end(), WCSortAlpha());
break;
}
validate();
}
//WSrcUnlockedCards
WSrcUnlockedCards::WSrcUnlockedCards(float delay) :
WSrcCards(delay)
{
MTGAllCards * ac = MTGCollection();
map<int, MTGCard*>::iterator it;
char * unlocked = NULL;
unlocked = (char *) calloc(setlist.size(), sizeof(char));
//Figure out which sets are available.
for (int i = 0; i < setlist.size(); i++)
{
unlocked[i] = options[Options::optionSet(i)].number;
}
for (it = ac->collection.begin(); it != ac->collection.end(); it++)
{
if(!options[Options::SHOWTOKENS].number)
{//dont show tokens & negative id's
if (it->second && unlocked[it->second->setId] && (it->second->getId() > 0) && (it->second->getRarity() != Constants::RARITY_T)) cards.push_back(it->second);
}
else
{//show but you cant add
if (it->second && unlocked[it->second->setId]) cards.push_back(it->second);
}
}
if (unlocked)
{
free(unlocked);
unlocked = NULL;
}
if (cards.size())
{
Shuffle();
currentPos = 0;
}
}
//WSrcDeck
int WSrcDeck::loadMatches(MTGDeck * deck)
{
map<int, int>::iterator it;
int count = 0;
if (!deck) return count;
for (it = deck->cards.begin(); it != deck->cards.end(); it++)
{
MTGCard * c = deck->getCardById(it->first);
if(!options[Options::SHOWTOKENS].number)
{//dont show tokens & negative id's
if (c && matchesFilters(c) && (c->getId() > 0) && (c->getRarity() != Constants::RARITY_T))
{
Add(c, it->second);
count++;
}
}
else
{//show but you cant add
if (c && matchesFilters(c))
{
Add(c, it->second);
count++;
}
}
}
validate();
return count;
}
void WSrcDeck::updateCounts()
{
vector<MTGCard*>::iterator it;
map<int, int>::iterator ccount;
clearCounts();
for (it = cards.begin(); it != cards.end(); it++)
{
ccount = copies.find((*it)->getMTGId());
if (ccount == copies.end()) continue;
addCount((*it), ccount->second);
}
}
void WSrcDeck::clearCounts()
{
counts[UNFILTERED_MIN_COPIES] = -1;
counts[UNFILTERED_MAX_COPIES] = 0;
for (int i = 0; i < MAX_COUNTS; i++)
counts[i] = 0;
}
void WSrcDeck::addCount(MTGCard * c, int qty)
{
if (!c || !c->data) return;
map<int, int>::iterator cp = copies.find(c->getMTGId());
if (matchesFilters(c))
{
counts[FILTERED_COPIES] += qty;
if (qty > 0 && cp != copies.end() && (*cp).second == qty)
counts[FILTERED_UNIQUE]++;
else if (qty < 0 && (cp == copies.end() || (*cp).second == 0)) counts[FILTERED_UNIQUE]--;
}
counts[UNFILTERED_COPIES] += qty;
if (qty > 0 && cp != copies.end() && (*cp).second == qty)
counts[UNFILTERED_UNIQUE]++;
else if (qty < 0 && (cp == copies.end() || (*cp).second == 0)) counts[UNFILTERED_UNIQUE]--;
for (int i = Constants::MTG_COLOR_ARTIFACT; i <= Constants::MTG_COLOR_LAND; i++)
if (c->data->hasColor(i)) counts[i] += qty;
if (counts[UNFILTERED_MIN_COPIES] < 0 || qty < counts[UNFILTERED_MIN_COPIES]) counts[UNFILTERED_MIN_COPIES] = qty;
if (qty > counts[UNFILTERED_MAX_COPIES]) counts[UNFILTERED_MAX_COPIES] = qty;
}
int WSrcDeck::Add(MTGCard * c, int quantity)
{
if (!c) return 0;
if (copies.find(c->getMTGId()) == copies.end())
{
cards.push_back(c);
}
copies[c->getMTGId()] += quantity;
addCount(c, quantity);
return 1;
}
int WSrcDeck::Remove(MTGCard * c, int quantity, bool erase)
{
if (!c) return 0;
map<int, int>::iterator it = copies.find(c->getMTGId());
if (it == copies.end()) return 0;
int amt = it->second;
if (amt < quantity) return 0;
amt -= quantity;
it->second = amt;
if (erase && amt == 0)
{
copies.erase(it);
vector<MTGCard*>::iterator i = find(cards.begin(), cards.end(), c);
if (i != cards.end()) cards.erase(i);
}
addCount(c, -quantity);
return 1;
}
void WSrcDeck::Rebuild(MTGDeck * d)
{
d->removeAll();
map<int, int>::iterator it;
for (it = copies.begin(); it != copies.end(); it++)
{
for (int i = 0; i < it->second; i++)
{
d->add(it->first);
}
}
}
int WSrcDeck::count(MTGCard * c)
{
if (!c) return counts[UNFILTERED_COPIES];
if (copies.find(c->getMTGId()) == copies.end()) return 0;
return copies[c->getMTGId()];
}
int WSrcDeck::countByName(MTGCard * card, bool editions)
{
string name = card->data->getLCName();
int total = 0;
vector<MTGCard*>::iterator it;
for (it = cards.begin(); it != cards.end(); it++)
{
if (*it && (*it)->data->getLCName() == name)
{
if (editions)
total++;
else
{
map<int, int>::iterator mi = copies.find((*it)->getMTGId());
if (mi != copies.end()) total += mi->second;
}
}
}
return total;
}
int WSrcDeck::getCount(int count)
{
if (count < 0 || count >= MAX_COUNTS) return counts[UNFILTERED_COPIES];
return counts[count];
}
int WSrcDeck::totalPrice()
{
int total = 0;
PriceList * pricelist = NEW PriceList("settings/prices.dat", MTGCollection());
map<int, int>::iterator it;
for (it = copies.begin(); it != copies.end(); it++)
{
int nb = it->second;
if (nb) total += pricelist->getPrice(it->first);
}
SAFE_DELETE(pricelist);
return total;
}
//WSrcDeckViewer
WSrcDeckViewer::WSrcDeckViewer(WSrcCards * _active, WSrcCards * _inactive) :
WSrcCards(0.2f)
{
active = _active;
inactive = _inactive;
}
void WSrcDeckViewer::swapSrc()
{
WSrcCards * temp = active;
active = inactive;
inactive = temp;
}
WSrcDeckViewer::~WSrcDeckViewer()
{
//Do nothing.
}
//Sorting methods:
int WCSortRarity::rareToInt(char r)
{
switch (r)
{
default:
case Constants::RARITY_T:
return 0;
case Constants::RARITY_L:
return 1;
case Constants::RARITY_C:
return 2;
case Constants::RARITY_U:
return 3;
case Constants::RARITY_R:
return 4;
case Constants::RARITY_M:
return 5;
case Constants::RARITY_S:
return 6;
}
}
bool WCSortRarity::operator()(const MTGCard*l, const MTGCard*r)
{
if (!l || !r || !l->data || !r->data) return false;
return (rareToInt(l->getRarity()) < rareToInt(r->getRarity()));
}
bool WCSortAlpha::operator()(const MTGCard*l, const MTGCard*r)
{
if (!l || !r || !l->data || !r->data) return false;
string ln = l->data->getLCName();
string rn = r->data->getLCName();
if (ln == rn) return l->getMTGId() < r->getMTGId();
return (ln < rn);
}
bool WCSortCollector::operator()(const MTGCard*l, const MTGCard*r)
{
if (!l || !r || !l->data || !r->data) return false;
if (l->setId != r->setId) return (l->setId < r->setId);
int lc, rc;
lc = l->data->countColors();
rc = r->data->countColors();
if (lc == 0) lc = 999;
if (rc == 0) rc = 999;
int isW = (int) l->data->hasColor(Constants::MTG_COLOR_WHITE) - (int) r->data->hasColor(Constants::MTG_COLOR_WHITE);
int isU = (int) l->data->hasColor(Constants::MTG_COLOR_BLUE) - (int) r->data->hasColor(Constants::MTG_COLOR_BLUE);
int isB = (int) l->data->hasColor(Constants::MTG_COLOR_BLACK) - (int) r->data->hasColor(Constants::MTG_COLOR_BLACK);
int isR = (int) l->data->hasColor(Constants::MTG_COLOR_RED) - (int) r->data->hasColor(Constants::MTG_COLOR_RED);
int isG = (int) l->data->hasColor(Constants::MTG_COLOR_GREEN) - (int) r->data->hasColor(Constants::MTG_COLOR_GREEN);
int isArt = (int) l->data->hasType(Subtypes::TYPE_ARTIFACT) - (int) r->data->hasType(Subtypes::TYPE_ARTIFACT);
int isLand = (int) l->data->hasType(Subtypes::TYPE_LAND) - (int) r->data->hasType(Subtypes::TYPE_LAND);
//Nested if hell. TODO: Farm these out to their own objects as a user-defined filter/sort system.
if (!isLand)
{
int isBasic = (int) l->data->hasType("Basic") - (int) r->data->hasType("Basic");
if (!isBasic)
{
if (!isArt)
{
if (lc == rc)
{
if (!isG)
{
if (!isR)
{
if (!isB)
{
if (!isU)
{
if (!isW)
{
string ln = l->data->getLCName();
string rn = r->data->getLCName();
if (ln.substr(0, 4) == "the ") ln = ln.substr(4);
if (rn.substr(0, 4) == "the ") rn = rn.substr(4);
return (ln < rn);
}
return (isW < 0);
}
return (isU < 0);
}
return (isB < 0);
}
return (isR < 0);
}
return (isG < 0);
}
return (lc < rc);
}
return (isArt < 0);
}
else
return (isBasic < 0);
}
return (isLand < 0);
}