Better support Double-Faced Cards (#4753)

* Better support Double-Faced Cards

This patch allows cards to be (virtually) transformed into other cards
while preserving their state, essentially implemeting the MTG mechanic
of the same name.

On the server side, this is implemented by allowing cards to be "stashed
away". A card that is stashed away is not in any zone, but is instead
owned by another card. When a token is destroyed due to a zone change,
if it had a card stashed away, that card is placed in the target zone
instead of the token.

On the database side, `attach="transform"` is used on `<reverse>` and
`<reverse-related>` to indicate that the created token should be
transformed this way.

Old servers ignore the new field in `Command_CreateToken` and will
perform a regular attachment, as currently.

* Address review comments

* Prevent tokens from being stashed

* format.sh
This commit is contained in:
Basile Clement 2023-03-03 15:54:51 +00:00 committed by GitHub
parent 4558b1c7ef
commit 42e7a8b423
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 300 additions and 83 deletions

View file

@ -28,6 +28,8 @@
#include <QString>
class Server_CardZone;
class Event_SetCardCounter;
class Event_SetCardAttr;
class Server_Card : public Server_ArrowTarget
{
@ -49,6 +51,7 @@ private:
Server_Card *parentCard;
QList<Server_Card *> attachedCards;
Server_Card *stashedCard;
public:
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
@ -141,7 +144,7 @@ public:
{
name = _name;
}
void setCounter(int id, int value);
void setCounter(int id, int value, Event_SetCardCounter *event = nullptr);
void setTapped(bool _tapped)
{
tapped = _tapped;
@ -183,9 +186,31 @@ public:
{
attachedCards.removeOne(card);
}
void setStashedCard(Server_Card *card)
{
// setStashedCard should only be called on creation of a new card, so
// there should never be an already existing stashed card.
Q_ASSERT(!stashedCard);
// Stashed cards can't themselves have stashed cards, and tokens can't
// be stashed.
if (card->stashedCard || card->getDestroyOnZoneChange()) {
stashedCard = card->takeStashedCard();
card->deleteLater();
} else {
stashedCard = card;
}
}
Server_Card *takeStashedCard()
{
Server_Card *oldStashedCard = stashedCard;
stashedCard = nullptr;
return oldStashedCard;
}
void resetState();
QString setAttribute(CardAttribute attribute, const QString &avalue, bool allCards);
QString setAttribute(CardAttribute attribute, const QString &avalue, Event_SetCardAttr *event = nullptr);
void getInfo(ServerInfo_Card *info);
};