Handling of tokens/related cards improved. (#2773)

This commit is contained in:
Psithief 2017-06-21 06:35:06 +08:00 committed by Zach H
parent 029a4a39ad
commit ae15f5df06
6 changed files with 298 additions and 64 deletions

View file

@ -33,7 +33,7 @@ CardSet::CardSet(const QString &_shortName, const QString &_longName, const QStr
QString CardSet::getCorrectedShortName() const
{
// Because windows is horrible.
// For Windows machines.
QSet<QString> invalidFileNames;
invalidFileNames << "CON" << "PRN" << "AUX" << "NUL" << "COM1" << "COM2" <<
"COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8" << "COM9" <<
@ -176,8 +176,8 @@ CardInfo::CardInfo(const QString &_name,
const QString &_powtough,
const QString &_text,
const QStringList &_colors,
const QStringList &_relatedCards,
const QStringList &_reverseRelatedCards,
const QList<CardRelation *> &_relatedCards,
const QList<CardRelation *> &_reverseRelatedCards,
bool _upsideDownArt,
int _loyalty,
bool _cipt,
@ -348,14 +348,45 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
for (int i = 0; i < colors.size(); i++)
xml.writeTextElement("color", colors[i]);
const QStringList &related = info->getRelatedCards();
for (int i = 0; i < related.size(); i++)
xml.writeTextElement("related", related[i]);
const QStringList &reverseRelated = info->getReverseRelatedCards();
for (int i = 0; i < reverseRelated.size(); i++)
xml.writeTextElement("reverse-related", reverseRelated[i]);
const QList<CardRelation *> related = info->getRelatedCards();
for (int i = 0; i < related.size(); i++) {
xml.writeStartElement("related");
if (related[i]->getDoesAttach())
xml.writeAttribute("attach", "attach");
if (related[i]->getIsCreateAllExclusion())
xml.writeAttribute("exclude", "exclude");
if (related[i]->getIsVariable()) {
if (1 == related[i]->getDefaultCount())
xml.writeAttribute("count", "x");
else
xml.writeAttribute("count", "x=" + QString::number(related[i]->getDefaultCount()));
}
else if (1 != related[i]->getDefaultCount()) {
xml.writeAttribute("count", QString::number(related[i]->getDefaultCount()));
}
xml.writeCharacters(related[i]->getName());
xml.writeEndElement();
}
const QList<CardRelation *> reverseRelated = info->getReverseRelatedCards();
for (int i = 0; i < reverseRelated.size(); i++) {
xml.writeStartElement("reverse-related");
if (reverseRelated[i]->getDoesAttach())
xml.writeAttribute("attach", "attach");
if (reverseRelated[i]->getIsCreateAllExclusion())
xml.writeAttribute("exclude", "exclude");
if (reverseRelated[i]->getIsVariable()) {
if (1 == reverseRelated[i]->getDefaultCount())
xml.writeAttribute("count", "x");
else
xml.writeAttribute("count", "x=" + QString::number(reverseRelated[i]->getDefaultCount()));
}
else if (1 != reverseRelated[i]->getDefaultCount()) {
xml.writeAttribute("count", QString::number(reverseRelated[i]->getDefaultCount()));
}
xml.writeCharacters(reverseRelated[i]->getName());
xml.writeEndElement();
}
xml.writeTextElement("manacost", info->getManaCost());
xml.writeTextElement("cmc", info->getCmc());
xml.writeTextElement("type", info->getCardType());
@ -419,6 +450,13 @@ void CardDatabase::addCard(CardInfo *card)
void CardDatabase::removeCard(CardInfo *card)
{
foreach(CardRelation * cardRelation, card->getRelatedCards())
cardRelation->deleteLater();
foreach(CardRelation * cardRelation, card->getReverseRelatedCards())
cardRelation->deleteLater();
foreach(CardRelation * cardRelation, card->getReverseRelatedCards2Me())
cardRelation->deleteLater();
cards.remove(card->getName());
simpleNameCards.remove(card->getSimpleName());
emit cardRemoved(card);
@ -505,7 +543,8 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
break;
if (xml.name() == "card") {
QString name, manacost, cmc, type, pt, text;
QStringList colors, relatedCards, reverseRelatedCards;
QStringList colors;
QList<CardRelation *> relatedCards, reverseRelatedCards;
QStringMap customPicURLs;
MuidMap muids;
QStringMap collectorNumbers, rarities;
@ -548,11 +587,38 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
}
} else if (xml.name() == "color")
colors << xml.readElementText();
else if (xml.name() == "related")
relatedCards << xml.readElementText();
else if (xml.name() == "reverse-related")
reverseRelatedCards << xml.readElementText();
else if (xml.name() == "tablerow")
else if (xml.name() == "related" || xml.name() == "reverse-related") {
bool attach = false;
bool exclude = false;
bool variable = false;
int count = 1;
QXmlStreamAttributes attrs = xml.attributes();
QString cardName = xml.readElementText();
if (attrs.hasAttribute("count")) {
if (attrs.value("count").toString().indexOf("x=") == 0) {
variable = true;
count = attrs.value("count").toString().remove(0, 2).toInt();
}
else if (attrs.value("count").toString().indexOf("x") == 0)
variable = true;
else
count = attrs.value("count").toString().toInt();
if (count < 1)
count = 1;
}
if (attrs.hasAttribute("attach")) {
attach = true;
}
if (attrs.hasAttribute("exclude")) {
exclude = true;
}
CardRelation * relation = new CardRelation(cardName, attach, exclude, variable, count);
if (xml.name() == "reverse-related") {
reverseRelatedCards << relation;
} else {
relatedCards << relation;
}
} else if (xml.name() == "tablerow")
tableRow = xml.readElementText().toInt();
else if (xml.name() == "cipt")
cipt = (xml.readElementText() == "1");
@ -725,12 +791,16 @@ void CardDatabase::refreshCachedReverseRelatedCards()
else
relatedCardName = card->getName(); // "name"
foreach(QString targetCard, card->getReverseRelatedCards())
foreach(CardRelation * cardRelation, card->getReverseRelatedCards())
{
const QString & targetCard = cardRelation->getName();
if (!cards.contains(targetCard))
continue;
cards.value(targetCard)->addReverseRelatedCards2Me(relatedCardName);
CardRelation *newCardRelation = new CardRelation(relatedCardName, cardRelation->getDoesAttach(),
cardRelation->getIsCreateAllExclusion(),
cardRelation->getIsVariable(),
cardRelation->getDefaultCount());
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
}
}
}
@ -830,4 +900,26 @@ bool CardDatabase::saveCustomTokensToFile()
xml.writeEndDocument();
return true;
}
CardRelation::CardRelation(const QString &_name,
bool _doesAttach,
bool _isCreateAllExclusion,
bool _isVariableCount,
int _defaultCount
)
: name(_name),
doesAttach(_doesAttach),
isCreateAllExclusion(_isCreateAllExclusion),
isVariableCount(_isVariableCount),
defaultCount(_defaultCount)
{
}
void CardInfo::resetReverseRelatedCards2Me() {
foreach(CardRelation * cardRelation, this->getReverseRelatedCards2Me()) {
cardRelation->deleteLater();
}
reverseRelatedCardsToMe = QList<CardRelation *>();
}

View file

@ -11,6 +11,7 @@
class CardDatabase;
class CardInfo;
class CardRelation;
typedef QMap<QString, QString> QStringMap;
@ -78,11 +79,11 @@ private:
QString text;
QStringList colors;
// the cards i'm related to
QStringList relatedCards;
QList<CardRelation *> relatedCards;
// the card i'm reverse-related to
QStringList reverseRelatedCards;
QList<CardRelation *> reverseRelatedCards;
// the cards thare are reverse-related to me
QStringList reverseRelatedCardsToMe;
QList<CardRelation *> reverseRelatedCardsToMe;
QString setsNames;
bool upsideDownArt;
int loyalty;
@ -102,8 +103,8 @@ public:
const QString &_powtough = QString(),
const QString &_text = QString(),
const QStringList &_colors = QStringList(),
const QStringList &_relatedCards = QStringList(),
const QStringList &_reverseRelatedCards = QStringList(),
const QList<CardRelation *> &_relatedCards = QList<CardRelation *>(),
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
bool _upsideDownArt = false,
int _loyalty = 0,
bool _cipt = false,
@ -136,11 +137,11 @@ public:
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
const QChar getColorChar() const;
const QStringList &getColors() const { return colors; }
const QStringList &getRelatedCards() const { return relatedCards; }
const QStringList &getReverseRelatedCards() const { return reverseRelatedCards; }
const QStringList &getReverseRelatedCards2Me() const { return reverseRelatedCardsToMe; }
void resetReverseRelatedCards2Me() { reverseRelatedCardsToMe = QStringList(); }
void addReverseRelatedCards2Me(QString & cardName) { reverseRelatedCardsToMe.append(cardName); }
const QList<CardRelation *> &getRelatedCards() const { return relatedCards; }
const QList<CardRelation *> &getReverseRelatedCards() const { return reverseRelatedCards; }
const QList<CardRelation *> &getReverseRelatedCards2Me() const { return reverseRelatedCardsToMe; }
void resetReverseRelatedCards2Me();
void addReverseRelatedCards2Me(CardRelation * cardRelation) { reverseRelatedCardsToMe.append(cardRelation); }
bool getUpsideDownArt() const { return upsideDownArt; }
QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
int getMuId(const QString &set) const { return muIds.value(set); }
@ -245,4 +246,27 @@ signals:
void cardRemoved(CardInfo *card);
};
class CardRelation : public QObject {
Q_OBJECT
private:
QString name;
bool doesAttach;
bool isCreateAllExclusion;
bool isVariableCount;
int defaultCount;
public:
CardRelation(const QString &_name = QString(),
bool _doesAttach = false,
bool _isCreateAllExclusion = false,
bool _isVariableCount = false,
int _defaultCount = 1
);
inline const QString &getName() const { return name; }
bool getDoesAttach() const { return doesAttach; }
bool getCanCreateAnother() const { return !doesAttach; }
bool getIsCreateAllExclusion() const { return isCreateAllExclusion; }
bool getIsVariable() const { return isVariableCount; }
int getDefaultCount() const { return defaultCount; }
};
#endif

View file

@ -1087,7 +1087,7 @@ void Player::actCreateToken()
lastTokenAnnotation = dlg.getAnnotation();
lastTokenDestroy = dlg.getDestroy();
aCreateAnotherToken->setEnabled(true);
aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(lastTokenName));
actCreateAnotherToken();
}
@ -1126,17 +1126,21 @@ void Player::actCreateRelatedCard()
CardItem * sourceCard = game->getActiveCard();
if(!sourceCard)
return;
QAction *action = static_cast<QAction *>(sender());
const QString &actionDisplayName = action->text();
createCard(sourceCard, dbNameFromTokenDisplayName(actionDisplayName));
//If there is a better way of passing a CardRelation through a QAction, please add it here.
QList<CardRelation *> relatedCards = QList<CardRelation *>();
relatedCards.append(sourceCard->getInfo()->getRelatedCards());
relatedCards.append(sourceCard->getInfo()->getReverseRelatedCards2Me());
CardRelation * cardRelation = relatedCards.at(action->data().toInt());
/*
* If we made a token via "Token: TokenName"
* then lets allow it to be created via create another
* If we make a token via "Token: TokenName"
* then let's allow it to be created via "create another token"
*/
CardInfo *cardInfo = db->getCard(dbNameFromTokenDisplayName(actionDisplayName));
setLastToken(cardInfo);
if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) {
CardInfo *cardInfo = db->getCard(dbNameFromTokenDisplayName(cardRelation->getName()));
setLastToken(cardInfo);
}
}
void Player::actCreateAllRelatedCards()
@ -1145,27 +1149,111 @@ void Player::actCreateAllRelatedCards()
if(!sourceCard)
return;
QStringList relatedCards = * new QStringList();
QList<CardRelation *> relatedCards = QList<CardRelation *>();
relatedCards.append(sourceCard->getInfo()->getRelatedCards());
relatedCards.append(sourceCard->getInfo()->getReverseRelatedCards2Me());
foreach (const QString &tokenName, relatedCards)
{
createCard(sourceCard, dbNameFromTokenDisplayName(tokenName));
QList<CardRelation *> nonExcludedRelatedCards = QList<CardRelation *>();
QString dbName;
CardRelation * cardRelation = nullptr;
int tokensTypesCreated = 0;
switch(relatedCards.length()) { //Is an if/elseif/else pattern better?
case 0: //if (relatedCards.length() == 0)
return;
case 1: //else if (relatedCards.length() == 1)
cardRelation = relatedCards.at(0);
if (createRelatedFromRelation(sourceCard, cardRelation))
tokensTypesCreated++;
break;
default: //else
foreach (CardRelation * cardRelationTemp, relatedCards) {
if(!cardRelationTemp->getIsCreateAllExclusion() && !cardRelationTemp->getDoesAttach()) {
nonExcludedRelatedCards.append(cardRelationTemp);
}
}
switch(nonExcludedRelatedCards.length()) {
case 1: //if nonExcludedRelatedCards == 1
cardRelation = nonExcludedRelatedCards.at(0);
if (createRelatedFromRelation(sourceCard, cardRelation))
tokensTypesCreated++;
break;
//If all are marked "Exclude", then treat the situation as if none of them are.
//We won't accept "garbage in, garbage out", here.
case 0: //else if nonExcludedRelatedCards == 0
foreach (CardRelation * cardRelationAll, relatedCards) {
if (!cardRelationAll->getDoesAttach() && !cardRelationAll->getIsVariable()) {
dbName = dbNameFromTokenDisplayName(cardRelationAll->getName());
for (int i = 0; i < cardRelationAll->getDefaultCount(); i++) {
createCard(sourceCard, dbName);
}
tokensTypesCreated++;
if(tokensTypesCreated == 1) {
cardRelation = cardRelationAll;
}
}
}
break;
default: //else
foreach (CardRelation * cardRelationNotExcluded, nonExcludedRelatedCards) {
if (!cardRelationNotExcluded->getDoesAttach() && !cardRelationNotExcluded->getIsVariable()) {
dbName = dbNameFromTokenDisplayName(cardRelationNotExcluded->getName());
for (int i = 0; i < cardRelationNotExcluded->getDefaultCount(); i++) {
createCard(sourceCard, dbName);
}
tokensTypesCreated++;
if(tokensTypesCreated == 1) {
cardRelation = cardRelationNotExcluded;
}
}
}
break;
}
break;
}
/*
* If we made a token via "Token: TokenName"
* then lets allow it to be created via create another
* If we made at least one token via "Create All Tokens"
* then assign the first to the "Create another" shortcut.
*/
if (relatedCards.length() == 1)
if (cardRelation != nullptr && cardRelation->getCanCreateAnother())
{
CardInfo *cardInfo = db->getCard(dbNameFromTokenDisplayName(relatedCards.at(0)));
CardInfo *cardInfo = db->getCard(dbNameFromTokenDisplayName(cardRelation->getName()));
setLastToken(cardInfo);
}
}
void Player::createCard(const CardItem *sourceCard, const QString &dbCardName) {
bool Player::createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation)
{
if (sourceCard == nullptr || cardRelation == nullptr)
return false;
QString dbName = dbNameFromTokenDisplayName(cardRelation->getName());
if(cardRelation->getIsVariable()) {
bool ok;
dialogSemaphore = true;
int count = QInputDialog::getInt(0, tr("Create tokens"), tr("Number:"), cardRelation->getDefaultCount(), 1, MAX_TOKENS_PER_DIALOG, 1, &ok);
dialogSemaphore = false;
if (!ok)
return false;
for (int i = 0; i < count; i++) {
createCard(sourceCard, dbName);
}
} else if (cardRelation->getDefaultCount() > 1) {
for (int i = 0; i < cardRelation->getDefaultCount(); i++) {
createCard(sourceCard, dbName);
}
} else {
if (cardRelation->getDoesAttach()) {
createAttachedCard(sourceCard, dbName);
} else {
createCard(sourceCard, dbName);
}
}
return true;
}
void Player::createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach)
{
CardInfo *cardInfo = db->getCard(dbCardName);
if (cardInfo == nullptr || sourceCard == nullptr)
@ -1179,7 +1267,10 @@ void Player::createCard(const CardItem *sourceCard, const QString &dbCardName) {
Command_CreateToken cmd;
cmd.set_zone("table");
cmd.set_card_name(cardInfo->getName().toStdString());
cmd.set_color(cardInfo->getColors().isEmpty() ? QString().toStdString() : cardInfo->getColors().first().toLower().toStdString());
if(cardInfo->getColors().length() > 1) //Multicoloured
cmd.set_color("m");
else
cmd.set_color(cardInfo->getColors().isEmpty() ? QString().toStdString() : cardInfo->getColors().first().toLower().toStdString());
cmd.set_pt(cardInfo->getPowTough().toStdString());
cmd.set_annotation(settingsCache->getAnnotateTokens() ? cardInfo->getText().toStdString() : QString().toStdString());
cmd.set_destroy_on_zone_change(true);
@ -1187,12 +1278,17 @@ void Player::createCard(const CardItem *sourceCard, const QString &dbCardName) {
cmd.set_x(gridPoint.x());
cmd.set_y(gridPoint.y());
if(!cardInfo->getIsToken())
if(attach)
cmd.set_target_card_id(sourceCard->getId());
sendGameCommand(cmd);
}
void Player::createAttachedCard(const CardItem *sourceCard, const QString &dbCardName)
{
createCard(sourceCard, dbCardName, true);
}
void Player::actSayMessage()
{
QAction *a = qobject_cast<QAction *>(sender());
@ -2533,7 +2629,7 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) {
if (card == nullptr || cardMenu == nullptr || card->getInfo() == nullptr)
return;
QStringList relatedCards = *new QStringList();
QList<CardRelation *> relatedCards = QList<CardRelation *>();
relatedCards.append(card->getInfo()->getRelatedCards());
relatedCards.append(card->getInfo()->getReverseRelatedCards2Me());
@ -2542,7 +2638,11 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) {
break;
case 1: {
cardMenu->addSeparator();
QAction *createRelatedCards = new QAction(tr("Token: ") + relatedCards.at(0), this);
QAction *createRelatedCards;
if (relatedCards.at(0)->getDoesAttach()) {
createRelatedCards = new QAction(tr("Token: ") + tr("Attach to ") + relatedCards.at(0)->getName(), this);
} else
createRelatedCards = new QAction(tr("Token: ") + (relatedCards.at(0)->getIsVariable() ? "X " : QString(relatedCards.at(0)->getDefaultCount() == 1 ? QString() : QString::number(relatedCards.at(0)->getDefaultCount()) + " ")) + relatedCards.at(0)->getName(), this);
connect(createRelatedCards, SIGNAL(triggered()), this, SLOT(actCreateAllRelatedCards()));
if (shortcutsActive) {
createRelatedCards->setShortcut(settingsCache->shortcuts().getSingleShortcut("Player/aCreateRelatedTokens"));
@ -2552,11 +2652,19 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) {
}
default: {
cardMenu->addSeparator();
foreach (QString cardName, relatedCards)
int i = 0;
foreach (CardRelation * cardRelation, relatedCards)
{
QAction *createRelated = new QAction(tr("Token: ") + cardName, this);
QString cardName = cardRelation->getName();
QAction *createRelated;
if (cardRelation->getDoesAttach())
createRelated = new QAction(tr("Token: ") + tr("Attach to ") + cardName, this);
else
createRelated = new QAction(tr("Token: ") + (cardRelation->getIsVariable() ? "X " : QString(cardRelation->getDefaultCount() == 1 ? QString() : QString::number(cardRelation->getDefaultCount()) + " ")) + cardName, this);
createRelated->setData(QVariant(i));
connect(createRelated, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
cardMenu->addAction(createRelated);
i++;
}
QAction *createRelatedCards = new QAction(tr("All tokens"), this);
connect(createRelatedCards, SIGNAL(triggered()), this, SLOT(actCreateAllRelatedCards()));
@ -2643,5 +2751,6 @@ void Player::setLastToken(CardInfo *cardInfo)
lastTokenAnnotation = settingsCache->getAnnotateTokens() ? cardInfo->getText() : "";
lastTokenTableRow = table->clampValidTableRow(2 - cardInfo->getTableRow());
lastTokenDestroy = true;
aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(lastTokenName));
aCreateAnotherToken->setEnabled(true);
}
}

View file

@ -57,6 +57,8 @@ class Event_RevealCards;
class Event_ChangeZoneProperties;
class PendingCommand;
const int MAX_TOKENS_PER_DIALOG = 99;
class PlayerArea : public QObject, public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
@ -215,7 +217,9 @@ private:
void setCardAttrHelper(const GameEventContext &context, CardItem *card, CardAttribute attribute, const QString &avalue, bool allCards);
void addRelatedCardActions(const CardItem *card, QMenu *cardMenu);
void createCard(const CardItem *sourceCard, const QString &dbCardName);
void createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach = false);
void createAttachedCard(const CardItem *sourceCard, const QString &dbCardName);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
QString dbNameFromTokenDisplayName(const QString &tokenName);
QRectF bRect;

View file

@ -64,8 +64,8 @@ CardInfo *OracleImporter::addCard(const QString &setName,
int cardLoyalty,
const QString &cardText,
const QStringList & colors,
const QStringList & relatedCards,
const QStringList & reverseRelatedCards,
const QList<CardRelation *> & relatedCards,
const QList<CardRelation *> & reverseRelatedCards,
bool upsideDown,
QString &rarity
)
@ -147,8 +147,8 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
QString cardPT;
QString cardText;
QStringList colors;
QStringList relatedCards;
QStringList reverseRelatedCards; // dummy
QList<CardRelation *> relatedCards;
QList<CardRelation *> reverseRelatedCards; // dummy
int cardId;
QString setNumber;
QString rarity;
@ -185,8 +185,12 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
setNumber = map.contains("number") ? map.value("number").toString() : QString("");
rarity = map.contains("rarity") ? map.value("rarity").toString() : QString("");
cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0;
relatedCards = map.contains("names") ? map.value("names").toStringList() : QStringList();
relatedCards.removeAll(cardName);
relatedCards = QList<CardRelation *>();
if(map.contains("names"))
foreach(const QString & name, map.value("names").toStringList()) {
if(name != cardName)
relatedCards.append(new CardRelation(name, true));
}
if(0 == QString::compare(map.value("layout").toString(), QString("flip"), Qt::CaseInsensitive))
{
@ -289,8 +293,9 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
}
colors.removeDuplicates();
relatedCards = QStringList();
reverseRelatedCards = QStringList();
//Fortunately, there are no split cards that flip, transform or meld.
relatedCards = QList<CardRelation *>();
reverseRelatedCards = QList<CardRelation *>();
upsideDown = false;
// add the card

View file

@ -43,8 +43,8 @@ private:
int cardLoyalty,
const QString &cardText,
const QStringList & colors,
const QStringList & relatedCards,
const QStringList & reverseRelatedCards,
const QList<CardRelation *> & relatedCards,
const QList<CardRelation *> & reverseRelatedCards,
bool upsideDown,
QString &rarity
);